daShangDao_psiWebApp/backups/ReviewIllegalBook.vue.bak
97694731 0543936df8
Some checks failed
CI / build (20.x) (push) Waiting to run
CI / lint (push) Waiting to run
CI / test (push) Waiting to run
CI / deploy-preview (push) Blocked by required conditions
CI / security (push) Waiting to run
CI / build (18.x) (push) Has been cancelled
change store
2026-06-04 11:18:46 +08:00

476 lines
17 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="review-page">
<el-card class="section-card">
<template #header>
<div class="card-header">
<span>异常书目审核</span>
</div>
</template>
<!-- 搜索筛选栏 -->
<div class="search-bar">
<div class="search-item">
<span>ISBN</span>
<el-input v-model="searchForm.isbn" placeholder="请输入ISBN" style="width: 180px" clearable />
</div>
<div class="search-item">
<span>状态:</span>
<el-select v-model="searchForm.status" placeholder="请选择状态" style="width: 140px" clearable>
<el-option label="待审核" value="0" />
<el-option label="已通过" value="1" />
<el-option label="已驳回" value="2" />
</el-select>
</div>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="handleReset">重置</el-button>
</div>
<!-- 数据表格 -->
<el-table :data="tableData" v-loading="loading" border stripe style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column prop="status" label="状态" width="150" align="center">
<template #default="{ row }">
<el-tag :type="statusTagType(row.status)" size="small">
{{ statusText(row.status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="barcode" label="ISBN" width="160" align="center" />
<el-table-column label="书名" min-width="200" show-overflow-tooltip align="center">
<template #default="{ row }">
<el-popover placement="bottom" :width="280" trigger="hover" popper-class="diff-popover">
<template #reference>
<span :class="{ 'diff-cell': isChanged(row.old_name, row.new_name) }">{{ row.old_name }}</span>
</template>
<div class="diff-content">
<div class="diff-row old"><span class="diff-label">旧值:</span><span class="diff-val">{{ row.old_name }}</span></div>
<div class="diff-row new"><span class="diff-label">新值:</span><span class="diff-val">{{ row.new_name }}</span></div>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="作者" width="150" show-overflow-tooltip align="center">
<template #default="{ row }">
<el-popover placement="bottom" :width="280" trigger="hover" popper-class="diff-popover">
<template #reference>
<span :class="{ 'diff-cell': isChanged(row.old_author, row.new_author) }">{{ row.old_author }}</span>
</template>
<div class="diff-content">
<div class="diff-row old"><span class="diff-label">旧值:</span><span class="diff-val">{{ row.old_author }}</span></div>
<div class="diff-row new"><span class="diff-label">新值:</span><span class="diff-val">{{ row.new_author }}</span></div>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="出版社" width="150" show-overflow-tooltip align="center">
<template #default="{ row }">
<el-popover placement="bottom" :width="280" trigger="hover" popper-class="diff-popover">
<template #reference>
<span :class="{ 'diff-cell': isChanged(row.old_publisher, row.new_publisher) }">{{ row.old_publisher }}</span>
</template>
<div class="diff-content">
<div class="diff-row old"><span class="diff-label">旧值:</span><span class="diff-val">{{ row.old_publisher }}</span></div>
<div class="diff-row new"><span class="diff-label">新值:</span><span class="diff-val">{{ row.new_publisher }}</span></div>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="套装书" width="150" show-overflow-tooltip align="center">
<template #default="{ row }">
<el-popover placement="bottom" :width="280" trigger="hover" popper-class="diff-popover">
<template #reference>
<el-tag type="info" size="small" :class="{ 'diff-cell': isChanged(row.old_is_suit, row.new_is_suit) }">
{{ row.old_is_suit === 0 ? '非套装书' : '套装书' }}
</el-tag>
</template>
<div class="diff-content">
<div class="diff-row old"><span class="diff-label">旧值:</span><span class="diff-val">{{ row.old_is_suit === 0 ? '非套装书' : '套装书' }}</span></div>
<div class="diff-row new"><span class="diff-label">新值:</span><span class="diff-val">{{ row.new_is_suit === 0 ? '非套装书' : '套装书' }}</span></div>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="定价" width="150" show-overflow-tooltip align="center">
<template #default="{ row }">
<el-popover placement="bottom" :width="280" trigger="hover" popper-class="diff-popover">
<template #reference>
<span :class="{ 'diff-cell': isChanged(row.old_price, row.new_price) }">{{ row.old_price }}</span>
</template>
<div class="diff-content">
<div class="diff-row old"><span class="diff-label">旧值:</span><span class="diff-val">{{ row.old_price }}</span></div>
<div class="diff-row new"><span class="diff-label">新值:</span><span class="diff-val">{{ row.new_price }}</span></div>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="装帧" width="150" show-overflow-tooltip align="center">
<template #default="{ row }">
<el-popover placement="bottom" :width="280" trigger="hover" popper-class="diff-popover">
<template #reference>
<span :class="{ 'diff-cell': isChanged(row.old_binding_layout, row.new_binding_layout) }">{{ row.old_binding_layout }}</span>
</template>
<div class="diff-content">
<div class="diff-row old"><span class="diff-label">旧值:</span><span class="diff-val">{{ row.old_binding_layout }}</span></div>
<div class="diff-row new"><span class="diff-label">新值:</span><span class="diff-val">{{ row.new_binding_layout }}</span></div>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="页数" width="150" show-overflow-tooltip align="center">
<template #default="{ row }">
<el-popover placement="bottom" :width="280" trigger="hover" popper-class="diff-popover">
<template #reference>
<span :class="{ 'diff-cell': isChanged(row.old_page_count, row.new_page_count) }">{{ row.old_page_count }}</span>
</template>
<div class="diff-content">
<div class="diff-row old"><span class="diff-label">旧值:</span><span class="diff-val">{{ row.old_page_count }}</span></div>
<div class="diff-row new"><span class="diff-label">新值:</span><span class="diff-val">{{ row.new_page_count }}</span></div>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="字数" width="150" show-overflow-tooltip align="center">
<template #default="{ row }">
<el-popover placement="bottom" :width="280" trigger="hover" popper-class="diff-popover">
<template #reference>
<span :class="{ 'diff-cell': isChanged(row.old_word_count, row.new_word_count) }">{{ row.old_word_count }}</span>
</template>
<div class="diff-content">
<div class="diff-row old"><span class="diff-label">旧值:</span><span class="diff-val">{{ row.old_word_count }}</span></div>
<div class="diff-row new"><span class="diff-label">新值:</span><span class="diff-val">{{ row.new_word_count }}</span></div>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="出版时间" width="150" show-overflow-tooltip align="center">
<template #default="{ row }">
<el-popover placement="bottom" :width="280" trigger="hover" popper-class="diff-popover">
<template #reference>
<span :class="{ 'diff-cell': isPubTimeChanged(row.old_publication_time, row.new_publication_time) }">{{ formatPubTime(row.old_publication_time) }}</span>
</template>
<div class="diff-content">
<div class="diff-row old"><span class="diff-label">旧值:</span><span class="diff-val">{{ formatPubTime(row.old_publication_time) }}</span></div>
<div class="diff-row new"><span class="diff-label">新值:</span><span class="diff-val">{{ formatPubTime(row.new_publication_time) }}</span></div>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="提交时间" width="180" align="center">
<template #default="{ row }">
{{ formatDateTime(row.created_at) }}
</template>
</el-table-column>
<el-table-column label="操作" width="180" fixed="right" align="center">
<template #default="{ row }">
<el-button type="primary" @click="handleApprove(row)">
查看
</el-button>
<el-button type="danger" @click="handleReject(row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination-wrapper">
<el-pagination v-model:current-page="pagination.current" v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 50, 100]" :total="pagination.total" layout="total, sizes, prev, pager, next, jumper"
@size-change="handlePageChange" @current-change="handlePageChange" />
</div>
</el-card>
<!-- 查看详情弹窗 -->
<el-dialog v-model="detailVisible" title="调剂记录详情" width="60%" :close-on-click-modal="false">
<template v-if="detailData">
<el-descriptions :column="2" border>
<el-descriptions-item label="ISBN">{{ detailData.isbn }}</el-descriptions-item>
<el-descriptions-item label="书名">{{ detailData.bookName }}</el-descriptions-item>
<el-descriptions-item label="作者">{{ detailData.author }}</el-descriptions-item>
<el-descriptions-item label="出版社">{{ detailData.publisher }}</el-descriptions-item>
<el-descriptions-item label="异常类型">{{ detailData.abnormalType }}</el-descriptions-item>
<el-descriptions-item label="状态">
<el-tag :type="statusTagType(detailData.status)" size="small">
{{ statusText(detailData.status) }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="异常说明" :span="2">
{{ detailData.abnormalDesc || '' }}
</el-descriptions-item>
<el-descriptions-item label="提交时间">{{ detailData.createdAt }}</el-descriptions-item>
<el-descriptions-item v-if="detailData.reviewTime" label="审核时间">{{ detailData.reviewTime
}}</el-descriptions-item>
</el-descriptions>
</template>
</el-dialog>
<!-- 审核弹窗 - 使用 SubmIllegalBook 组件 -->
<SubmIllegalBook
v-model:visible="reviewDialogVisible"
:review-data="reviewRecord"
:goods="null"
@review="handleReviewResult"
/>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/utils/request'
import SubmIllegalBook from '@/components/dialog/submIllegalBook/SubmIllegalBook.vue'
// 搜索表单
const searchForm = reactive({
isbn: '',
status: ''
})
// 表格数据
const tableData = ref<any[]>([])
const loading = ref(false)
const selectedRows = ref<any[]>([])
// 分页
const pagination = reactive({
current: 1,
pageSize: 20,
total: 0
})
// 详情弹窗
const detailVisible = ref(false)
const detailData = ref<any>(null)
// 审核弹窗
const reviewDialogVisible = ref(false)
const reviewRecord = ref<any>(null)
// 状态标签样式
function statusTagType(status: string): string {
const map: Record<string, string> = {
0: 'warning',
1: 'success',
2: 'danger'
}
return map[status] || 'info'
}
// 格式化出版时间为 yyyy-mm输入为10位时间戳秒级
function formatPubTime(time: any): string {
if (time === null || time === undefined || time === '') return ''
const ts = Number(time)
if (isNaN(ts) || ts <= 0) return ''
const d = new Date(ts * 1000)
const y = d.getFullYear()
const m = String(d.getMonth() + 1).padStart(2, '0')
return `${y}-${m}`
}
// 格式化为完整时间 yyyy-mm-dd HH:mm:ss输入为10位时间戳秒级
function formatDateTime(time: any): string {
if (time === null || time === undefined || time === '') return ''
const ts = Number(time)
if (isNaN(ts) || ts <= 0) return ''
const d = new Date(ts * 1000)
const y = d.getFullYear()
const M = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
const h = String(d.getHours()).padStart(2, '0')
const m = String(d.getMinutes()).padStart(2, '0')
const s = String(d.getSeconds()).padStart(2, '0')
return `${y}-${M}-${day} ${h}:${m}:${s}`
}
// 判断新旧数据是否不同
function isChanged(oldVal: any, newVal: any): boolean {
// 如果新旧值都是空值,视为相同
if ((oldVal === null || oldVal === undefined || oldVal === '') &&
(newVal === null || newVal === undefined || newVal === '')) {
return false
}
return String(oldVal) !== String(newVal)
}
// 判断出版时间是否不同(处理时间戳空值情况)
function isPubTimeChanged(oldTs: any, newTs: any): boolean {
return isChanged(formatPubTime(oldTs), formatPubTime(newTs))
}
// 状态文本
function statusText(status: string): string {
const map: Record<string, string> = {
0: '待审核',
1: '已通过',
2: '已驳回'
}
return map[status] || status
}
// 查询
function handleSearch() {
pagination.current = 1
fetchData()
}
// 重置
function handleReset() {
searchForm.isbn = ''
searchForm.status = ''
handleSearch()
}
// 多选
function handleSelectionChange(rows: any[]) {
selectedRows.value = rows
}
// 分页变化
function handlePageChange() {
fetchData()
}
// 获取数据
async function fetchData() {
loading.value = true
try {
const res = await request.get('/product_log/list', {
params: {
barcode: searchForm.isbn || undefined,
status: searchForm.status || undefined,
page: pagination.current,
page_size: pagination.pageSize
}
})
const data = res?.data
if (data) {
tableData.value = Array.isArray(data.list) ? data.list : Array.isArray(data) ? data : []
pagination.total = data.total || 0
} else {
tableData.value = []
pagination.total = 0
}
} catch (err) {
ElMessage.error('获取列表失败')
} finally {
loading.value = false
}
}
// 审核 - 打开审核弹窗
function handleApprove(row: any) {
reviewRecord.value = row
reviewDialogVisible.value = true
}
// 删除
async function handleReject(row: any) {
try {
await ElMessageBox.confirm('确认删除该条记录?', '提示', {
type: 'warning'
})
const formData = new FormData()
formData.append('id', String(row.id))
await request.post('/product_log/delete', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
})
ElMessage.success('已删除')
fetchData()
} catch {
// 取消
}
}
// 审核结果处理 - 弹窗关闭后刷新列表
function handleReviewResult(action: 'approve' | 'reject', record: any) {
fetchData()
}
// 查看详情
function handleViewDetail(row: any) {
detailData.value = row
detailVisible.value = true
}
onMounted(() => {
fetchData()
})
</script>
<style scoped>
.review-page {
padding: 0;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.section-card {
margin-bottom: 16px;
}
.search-bar {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 16px;
}
.search-item {
display: flex;
align-items: center;
gap: 8px;
}
.search-item span {
font-size: 14px;
color: #606266;
white-space: nowrap;
}
.pagination-wrapper {
display: flex;
justify-content: flex-end;
margin-top: 16px;
}
</style>
<style>
/* 新旧数据对比 - 单元格变红 */
.diff-cell {
color: #f56c6c !important;
font-weight: bold;
}
/* Popover 内容样式(全局,因 popover 渲染在 body 下) */
.diff-popover {
padding: 8px 12px !important;
}
.diff-content {
font-size: 13px;
line-height: 1.6;
}
.diff-row {
display: flex;
align-items: flex-start;
gap: 4px;
padding: 2px 0;
}
.diff-label {
white-space: nowrap;
color: #909399;
flex-shrink: 0;
}
.diff-val {
color: #303133;
word-break: break-all;
}
.diff-row.new .diff-val {
color: #e6a23c;
font-weight: bold;
}
</style>