借库逻辑实现

This commit is contained in:
dxc
2026-02-06 17:11:47 +08:00
parent 387c8973d6
commit 04ee938cd1
15 changed files with 1766 additions and 268 deletions

View File

@ -0,0 +1,198 @@
<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 prop="borrow_no" label="单号" width="180" show-overflow-tooltip />
<el-table-column prop="borrower_name" label="借用人" width="100" />
<el-table-column prop="sku" label="SKU" width="120" show-overflow-tooltip />
<el-table-column prop="borrow_time" label="借出时间" width="160" sortable />
<el-table-column 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 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 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 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" 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" 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')
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>