Files
KCGL/inventory-web/src/views/transaction/records.vue
dxc 42b0cddd3e feat: add column permission checks to transaction records table
Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
2026-02-27 14:07:48 +08:00

225 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<div class="filter-container">
<el-radio-group v-model="status" @change="fetchData" style="margin-right: 20px">
<el-radio-button label="all">全部</el-radio-button>
<el-radio-button label="borrowed">未归还</el-radio-button>
<el-radio-button label="returned">已归还</el-radio-button>
</el-radio-group>
<el-input v-model="keyword" placeholder="搜索借用人/SKU" style="width: 200px" @keyup.enter="fetchData" />
<el-button type="primary" @click="fetchData">查询</el-button>
</div>
<el-table
:data="list"
border
stripe
style="margin-top:20px"
v-loading="loading"
:row-class-name="tableRowClassName"
>
<el-table-column v-if="hasColumnPermission('borrow_no')" prop="borrow_no" label="单号" width="180" show-overflow-tooltip />
<el-table-column v-if="hasColumnPermission('borrower_name')" prop="borrower_name" label="借用人" width="100" />
<el-table-column v-if="hasColumnPermission('sku')" prop="sku" label="SKU" width="120" show-overflow-tooltip />
<el-table-column v-if="hasColumnPermission('borrow_time')" prop="borrow_time" label="借出时间" width="160" sortable />
<el-table-column v-if="hasColumnPermission('expected_return_time') || hasColumnPermission('return_time')" label="归还时间 / 预计" min-width="200">
<template #default="{row}">
<div v-if="row.status === 'returned'">
<el-tag type="success" size="small">实际</el-tag>
{{ row.return_time || '-' }}
</div>
<div v-else>
<el-tag type="info" size="small">预计</el-tag>
{{ formatExpectedTime(row.expected_return_time).text }}
<span :class="formatExpectedTime(row.expected_return_time).cssClass">
{{ formatExpectedTime(row.expected_return_time).diffText }}
</span>
</div>
</template>
</el-table-column>
<el-table-column v-if="hasColumnPermission('status')" label="状态" width="100" align="center">
<template #default="{row}">
<el-tag :type="row.status==='returned'?'success':'warning'">
{{ row.status==='returned'?'已还':'借出中' }}
</el-tag>
</template>
</el-table-column>
<el-table-column v-if="hasColumnPermission('return_location')" label="归还库位" min-width="120">
<template #default="{row}">
<span v-if="row.return_location">{{ row.return_location }}</span>
<span v-else style="color:#ccc">-</span>
</template>
</el-table-column>
<el-table-column v-if="hasColumnPermission('borrow_signature') || hasColumnPermission('return_signature')" label="电子签名" width="140" align="center">
<template #default="{row}">
<div style="display:flex; justify-content: center; gap:10px">
<el-popover trigger="hover" placement="top" v-if="row.borrow_signature && hasColumnPermission('borrow_signature')" width="220">
<template #reference><el-tag size="small"></el-tag></template>
<img :src="row.borrow_signature" style="width:200px; border:1px solid #eee" />
</el-popover>
<el-popover trigger="hover" placement="top" v-if="row.return_signature && hasColumnPermission('return_signature')" width="220">
<template #reference><el-tag type="success" size="small"></el-tag></template>
<img :src="row.return_signature" style="width:200px; border:1px solid #eee" />
</el-popover>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:total="total"
@current-change="handlePage"
style="margin-top:10px; text-align:right"
/>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import request from '@/utils/request'
import dayjs from 'dayjs' // 建议使用 dayjs 处理日期,如果没有安装,可以用原生 Date
import 'dayjs/locale/zh-cn' // 导入中文包
dayjs.locale('zh-cn')
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
// 列与权限Code的映射关系数据库中的code
const permissionMap: Record<string, string> = {
borrow_no: 'op_records:borrow_no',
borrower_name: 'op_records:borrower_name',
sku: 'op_records:sku',
borrow_time: 'op_records:borrow_time',
return_time: 'op_records:return_time',
status: 'op_records:status',
expected_return_time: 'op_records:expected_return_time',
return_location: 'op_records:return_location',
borrow_signature: 'op_records:borrow_signature',
return_signature: 'op_records:return_signature',
}
// 检查列权限
const hasColumnPermission = (prop: string) => {
if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
return true
}
const code = permissionMap[prop]
return code ? userStore.hasPermission(code) : false
}
const list = ref<any[]>([])
const total = ref(0)
// ★ 修改点:默认状态改为 'borrowed' (未归还)
const status = ref('borrowed')
const keyword = ref('')
const page = ref(1)
const loading = ref(false)
const fetchData = async () => {
loading.value = true
try {
const res = await request({
url: '/v1/transactions/records',
method: 'get',
params: {
page: page.value,
status: status.value,
keyword: keyword.value
}
})
list.value = res.data.items
total.value = res.data.total
} finally { loading.value = false }
}
const handlePage = (val: number) => {
page.value = val
fetchData()
}
// ★ 新增:格式化预计归还时间及倒计时逻辑
const formatExpectedTime = (timeStr: string) => {
if (!timeStr) return { text: '-', diffText: '', cssClass: '' }
// 后端返回的可能是 YYYY-MM-DD HH:mm:ss我们只取日期部分比较
const expected = dayjs(timeStr).startOf('day')
const today = dayjs().startOf('day')
const diffDays = expected.diff(today, 'day')
let diffText = ''
let cssClass = ''
// 这里的 timeStr 只展示前10位 (日期),或者展示完整
// 需求说单号规则是日期,预计归还也主要看日期
const displayTime = timeStr.substring(0, 10)
if (diffDays < 0) {
// 逾期
diffText = ` (逾期 ${Math.abs(diffDays)} 天)`
cssClass = 'text-danger'
} else if (diffDays === 0) {
// 今天到期
diffText = ` (今天到期)`
cssClass = 'text-warning'
} else {
// 剩余
diffText = ` (剩 ${diffDays} 天)`
cssClass = 'text-normal' // 正常,或者灰色
}
return { text: displayTime, diffText, cssClass }
}
// ★ 新增:表格行样式逻辑
const tableRowClassName = ({ row }: { row: any }) => {
// 如果已归还,不标颜色
if (row.status === 'returned') return ''
if (!row.expected_return_time) return ''
const expected = dayjs(row.expected_return_time).startOf('day')
const today = dayjs().startOf('day')
const diffDays = expected.diff(today, 'day')
if (diffDays < 0) {
return 'danger-row' // 逾期标红
} else if (diffDays === 0) {
return 'warning-row' // 当天标黄
}
return ''
}
onMounted(fetchData)
</script>
<style>
/* 注意Element Plus Table 的 row-class-name 样式通常不能放在 scoped 中 */
.el-table .warning-row {
--el-table-tr-bg-color: #fdf6ec !important; /* 浅橙色/黄色 */
}
.el-table .danger-row {
--el-table-tr-bg-color: #fef0f0 !important; /* 浅红色 */
color: #F56C6C; /* 文字变红增强警示 */
}
/* 文字颜色辅助类 */
.text-danger {
color: #F56C6C;
font-weight: bold;
}
.text-warning {
color: #E6A23C;
font-weight: bold;
}
.text-normal {
color: #909399;
}
</style>