|
|
@@ -15,9 +15,9 @@
|
|
|
v-model="searchType"
|
|
|
class="audit-tabs"
|
|
|
>
|
|
|
- <el-radio-button label="全部" value="0" />
|
|
|
- <el-radio-button label="待审核" value="1" />
|
|
|
- <el-radio-button label="已完成" value="2" />
|
|
|
+ <el-radio-button label="全部" :value="0" />
|
|
|
+ <el-radio-button label="待审核" :value="1" />
|
|
|
+ <el-radio-button label="已完成" :value="2" />
|
|
|
</el-radio-group>
|
|
|
</template>
|
|
|
|
|
|
@@ -34,109 +34,112 @@
|
|
|
|
|
|
<template #info="{ row }">
|
|
|
<div class="flex flex-col text-sm">
|
|
|
- <div class="mb-1">
|
|
|
- <span class="font-bold">书名: </span>{{ row.bookName }}
|
|
|
- </div>
|
|
|
- <div class="mb-1">
|
|
|
- <span class="font-bold">作者: </span>{{ row.author }}
|
|
|
- </div>
|
|
|
- <div class="mb-1">
|
|
|
- <span class="font-bold">ISBN: </span>{{ row.isbn }}
|
|
|
- </div>
|
|
|
- <div class="mb-1">
|
|
|
- <span class="font-bold">出版社: </span
|
|
|
- >{{ row.publisher }}
|
|
|
- </div>
|
|
|
- <div class="mb-1">
|
|
|
- <span class="font-bold">出版时间: </span
|
|
|
- >{{ row.pubDate }}
|
|
|
- </div>
|
|
|
- <div class="mb-1">
|
|
|
- <span class="font-bold">所属类型: </span>{{ row.type }}
|
|
|
- </div>
|
|
|
- <div class="mb-1">
|
|
|
- <span class="font-bold">回收状态: </span
|
|
|
- >{{ row.recycleStatus }}
|
|
|
+ <div class="info-basic-grid">
|
|
|
+ <div><span class="font-bold">书名: </span>{{ row.bookName }}</div>
|
|
|
+ <div><span class="font-bold">作者: </span>{{ row.author }}</div>
|
|
|
+ <div><span class="font-bold">ISBN: </span>{{ row.isbn }}</div>
|
|
|
+ <div><span class="font-bold">出版社: </span>{{ row.publish }}</div>
|
|
|
+ <div><span class="font-bold">出版时间: </span>{{ row.pubDate }}</div>
|
|
|
+ <div><span class="font-bold">所属类型: </span>{{ row.bookTagName }}</div>
|
|
|
+ <div><span class="font-bold">回收状态: </span>{{ row.recycleStatusName }}</div>
|
|
|
</div>
|
|
|
<div class="mt-2 border-t pt-2">
|
|
|
<span class="mr-4">定价: {{ row.price }}</span>
|
|
|
<span class="mr-4"
|
|
|
>回收折扣: {{ row.recycleDiscount }}折
|
|
|
<span class="text-red-500 text-xs"
|
|
|
- >建议0.5-0.6折</span
|
|
|
+ >{{ row.sugDiscountStr || '' }}</span
|
|
|
></span
|
|
|
>
|
|
|
<span>回收价格: {{ row.recyclePrice }}</span>
|
|
|
</div>
|
|
|
<div class="mb-1">
|
|
|
<span class="text-green-500 text-xs"
|
|
|
- >谢程娟: 2025-06-15</span
|
|
|
+ >{{ row.productPriceChangeLog?.operatorName || '' }} {{ row.productPriceChangeLog?.createTime || '' }}</span
|
|
|
>
|
|
|
</div>
|
|
|
<div class="mb-1">
|
|
|
- <span class="mr-4">销售价格: {{ row.salesPrice }}</span>
|
|
|
+ <span class="mr-4">销售价格: {{ row.oldPrice }}</span>
|
|
|
<span class="text-green-500 text-xs"
|
|
|
- >谢程娟: 2025-06-15</span
|
|
|
+ >{{ row.productPriceChangeLog?.operatorName || '' }} {{ row.productPriceChangeLog?.createTime || '' }}</span
|
|
|
>
|
|
|
</div>
|
|
|
<div class="mb-1">
|
|
|
<span
|
|
|
- >(已回收数量: {{ row.recycledCount }} 当前库存:
|
|
|
- {{ row.currentStock }})</span
|
|
|
+ >(已回收数量: {{ row.recycleNum }} 当前库存:
|
|
|
+ {{ row.stockNum }})</span
|
|
|
>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
- <template #newPrice="{ row }">
|
|
|
- <div class="flex flex-col items-center">
|
|
|
- <div class="flex items-center text-xl font-bold">
|
|
|
- {{ row.newPrice }}
|
|
|
- <el-icon class="ml-2 cursor-pointer text-red-500">
|
|
|
- <Edit />
|
|
|
- </el-icon>
|
|
|
- </div>
|
|
|
- <el-button size="small" type="info" plain class="mt-1"
|
|
|
- >填入原售价</el-button
|
|
|
- >
|
|
|
+ <template #priceHandler="{ row }">
|
|
|
+ <div class="price-handler-cell text-sm">
|
|
|
+ <div><span class="label">当前售价:</span>{{ row.oldPrice ?? row.productPrice ?? '-' }}</div>
|
|
|
+ <div><span class="label">处理人:</span>{{ row.handlerName || '-' }}</div>
|
|
|
+ <div><span class="label">分配时间:</span>{{ row.assignTime || '-' }}</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
- <template #action="{ row }">
|
|
|
- <div class="flex flex-col items-center gap-2">
|
|
|
- <el-button
|
|
|
- color="#951d1d"
|
|
|
- size="small"
|
|
|
- @click="handleViewUrl(row, 'kw')"
|
|
|
- >查看孔网</el-button
|
|
|
- >
|
|
|
+ <template #newPrice="{ row }">
|
|
|
+ <div class="new-price-cell">
|
|
|
+ <el-input-number
|
|
|
+ v-model="row._finalPrice"
|
|
|
+ :min="0"
|
|
|
+ :precision="2"
|
|
|
+ :step="0.01"
|
|
|
+ :controls="false"
|
|
|
+ class="new-price-input"
|
|
|
+ />
|
|
|
<el-button
|
|
|
- color="#f37607"
|
|
|
+ type="info"
|
|
|
+ plain
|
|
|
size="small"
|
|
|
- @click="handleViewUrl(row, 'tb')"
|
|
|
- >查看淘宝</el-button
|
|
|
- >
|
|
|
- <el-button color="#4095e5" size="small"
|
|
|
- >设置独立参数</el-button
|
|
|
- >
|
|
|
- <el-button type="success" size="small">同意</el-button>
|
|
|
+ class="fill-old-btn"
|
|
|
+ @click="fillOldPrice(row)"
|
|
|
+ >填入原售价</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #action="{ row }">
|
|
|
+ <div class="action-btns">
|
|
|
+ <el-button color="#951d1d" class="action-btn" @click="handleViewUrl(row, 'kw')">查看孔网</el-button>
|
|
|
+ <el-button color="#f37607" class="action-btn" @click="handleViewUrl(row, 'tb')">查看淘宝</el-button>
|
|
|
+ <el-button color="#4095e5" class="action-btn" @click="handleSetParams(row)">设置独立参数</el-button>
|
|
|
+ <template v-if="Number(searchType) !== 2">
|
|
|
+ <el-button type="success" class="action-btn" :loading="approvingId === row.itemId && actionType === 'approve'" @click="confirmApprove(row)">同意</el-button>
|
|
|
+ <el-button type="danger" class="action-btn" :loading="approvingId === row.itemId && actionType === 'reject'" @click="confirmReject(row)">拒绝</el-button>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</template>
|
|
|
</common-table>
|
|
|
+
|
|
|
+ <set-params ref="setParamsRef" @refresh="reload" />
|
|
|
</ele-page>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import { ref, reactive } from 'vue';
|
|
|
- import { Edit } from '@element-plus/icons-vue';
|
|
|
+ import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
import CommonTable from '@/components/CommonPage/CommonTable.vue';
|
|
|
import PageSearch from './components/page-search.vue';
|
|
|
+ import SetParams from '@/views/recycle/components/set-params.vue';
|
|
|
+ import request from '@/utils/request';
|
|
|
+ import {
|
|
|
+ actionMessage,
|
|
|
+ approveAudit,
|
|
|
+ cleanParams,
|
|
|
+ withOffsetLimit
|
|
|
+ } from '@/api/priceWorkbench';
|
|
|
|
|
|
defineOptions({ name: 'PriceAudit' });
|
|
|
|
|
|
// Component Refs
|
|
|
const pageRef = ref(null);
|
|
|
- const searchType = ref('0');
|
|
|
+ const setParamsRef = ref(null);
|
|
|
+ const searchType = ref(1);
|
|
|
+ const approvingId = ref(null);
|
|
|
+ const actionType = ref('');
|
|
|
|
|
|
const columns = ref([
|
|
|
{ type: 'selection', width: 50, align: 'center', fixed: 'left' },
|
|
|
@@ -144,33 +147,37 @@
|
|
|
{ label: '信息', prop: 'info', minWidth: 400, slot: 'info' },
|
|
|
{
|
|
|
label: '总回收量',
|
|
|
- prop: 'totalRecycled',
|
|
|
+ prop: 'recycleTotalNum',
|
|
|
width: 110,
|
|
|
sortable: true,
|
|
|
align: 'center'
|
|
|
},
|
|
|
- { label: '状态', prop: 'status', width: 100, align: 'center' },
|
|
|
- { label: '分配时间', prop: 'assignTime', width: 160, align: 'center' },
|
|
|
+ { label: '状态', prop: 'itemStatusName', width: 100, align: 'center' },
|
|
|
{
|
|
|
label: '当前库存',
|
|
|
- prop: 'currentStock',
|
|
|
+ prop: 'stockNum',
|
|
|
width: 110,
|
|
|
sortable: true,
|
|
|
align: 'center'
|
|
|
},
|
|
|
- { label: '当前售价', prop: 'salesPrice', width: 100, align: 'center' },
|
|
|
- { label: '处理人', prop: 'handler', width: 100, align: 'center' },
|
|
|
+ {
|
|
|
+ label: '售价/处理人',
|
|
|
+ prop: 'priceHandler',
|
|
|
+ width: 180,
|
|
|
+ slot: 'priceHandler',
|
|
|
+ align: 'left'
|
|
|
+ },
|
|
|
{
|
|
|
label: '新售价',
|
|
|
prop: 'newPrice',
|
|
|
- width: 150,
|
|
|
+ width: 130,
|
|
|
slot: 'newPrice',
|
|
|
align: 'center'
|
|
|
},
|
|
|
{
|
|
|
label: '操作',
|
|
|
prop: 'action',
|
|
|
- width: 120,
|
|
|
+ width: 150,
|
|
|
slot: 'action',
|
|
|
fixed: 'right',
|
|
|
align: 'center'
|
|
|
@@ -181,39 +188,35 @@
|
|
|
fileName: '价格审核',
|
|
|
cacheKey: 'priceAuditTable',
|
|
|
params: {
|
|
|
- searchType: '0'
|
|
|
+ tab: 1
|
|
|
},
|
|
|
- rowKey: 'id'
|
|
|
+ rowKey: 'itemId'
|
|
|
});
|
|
|
|
|
|
- // Mock datasource
|
|
|
- const datasource = ({ page, limit, where, orders }) => {
|
|
|
- return Promise.resolve({
|
|
|
- code: 0,
|
|
|
- msg: 'success',
|
|
|
- count: 10,
|
|
|
- data: Array.from({ length: 10 }).map((_, i) => ({
|
|
|
- id: i + 1,
|
|
|
- cover: 'https://img1.baidu.com/it/u=2356551695,3062334057&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=707',
|
|
|
- bookName: '马克思主义基本原理',
|
|
|
- author: '编写组',
|
|
|
- isbn: '9787056025415',
|
|
|
- publisher: '高等教育出版社',
|
|
|
- pubDate: '2018-06',
|
|
|
- type: '教材库',
|
|
|
- recycleStatus: '正在回收',
|
|
|
- price: 25,
|
|
|
- recycleDiscount: 0.2,
|
|
|
- recyclePrice: 0.5,
|
|
|
- salesPrice: 6.5,
|
|
|
- recycledCount: 200,
|
|
|
- currentStock: 75 + i,
|
|
|
- totalRecycled: 200,
|
|
|
- status: i % 2 === 0 ? '待审核' : '已审核',
|
|
|
- assignTime: '2024-06-15 15:06:11',
|
|
|
- handler: 'zzz',
|
|
|
- newPrice: 10.55
|
|
|
- }))
|
|
|
+ const datasource = ({ pages, where, orders, sorter }) => {
|
|
|
+ const params = withOffsetLimit(pages, {
|
|
|
+ ...(pageConfig.params || {}),
|
|
|
+ ...cleanParams(where || {})
|
|
|
+ });
|
|
|
+ if (orders && orders.orderByColumn) {
|
|
|
+ params.orderType = sorter?.column?.columnKey || orders.orderByColumn;
|
|
|
+ params.orderWay = orders.isAsc === 'ascending' ? 'asc' : 'desc';
|
|
|
+ }
|
|
|
+ return request.get('/price/audit/list', { params }).then((res) => {
|
|
|
+ if (res.data.code !== 200) {
|
|
|
+ return Promise.reject(new Error(res.data.msg));
|
|
|
+ }
|
|
|
+ const body = res.data;
|
|
|
+ body.rows = (body.rows || []).map((row) => {
|
|
|
+ const raw =
|
|
|
+ row.finalPrice ?? row.newPrice ?? row.oldPrice ?? row.productPrice;
|
|
|
+ const num = Number(raw);
|
|
|
+ return {
|
|
|
+ ...row,
|
|
|
+ _finalPrice: Number.isFinite(num) ? num : undefined
|
|
|
+ };
|
|
|
+ });
|
|
|
+ return body;
|
|
|
});
|
|
|
};
|
|
|
|
|
|
@@ -222,7 +225,68 @@
|
|
|
}
|
|
|
|
|
|
function handleStatusChange(value) {
|
|
|
- pageRef.value?.reload({ searchType: value });
|
|
|
+ pageConfig.params.tab = Number(value);
|
|
|
+ pageRef.value?.reload({ tab: Number(value), search: true });
|
|
|
+ }
|
|
|
+
|
|
|
+ function fillOldPrice(row) {
|
|
|
+ row._finalPrice = row.oldPrice ?? row.productPrice;
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleSetParams(row) {
|
|
|
+ setParamsRef.value?.handleOpen(row);
|
|
|
+ }
|
|
|
+
|
|
|
+ function confirmApprove(row) {
|
|
|
+ const price = row._finalPrice;
|
|
|
+ ElMessageBox.confirm(
|
|
|
+ `确认同意该书新售价为 ${price ?? '-'} 元吗?`,
|
|
|
+ '同意确认',
|
|
|
+ {
|
|
|
+ confirmButtonText: '同意',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }
|
|
|
+ )
|
|
|
+ .then(() => submitAudit(row, price, 'approve', '审核通过'))
|
|
|
+ .catch(() => {});
|
|
|
+ }
|
|
|
+
|
|
|
+ function confirmReject(row) {
|
|
|
+ const oldPrice = row.oldPrice ?? row.productPrice;
|
|
|
+ ElMessageBox.confirm(
|
|
|
+ `确认拒绝改价吗?将按原售价 ${oldPrice ?? '-'} 元回退完成。`,
|
|
|
+ '拒绝确认',
|
|
|
+ {
|
|
|
+ confirmButtonText: '拒绝',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning',
|
|
|
+ confirmButtonClass: 'el-button--danger'
|
|
|
+ }
|
|
|
+ )
|
|
|
+ .then(() => {
|
|
|
+ row._finalPrice = oldPrice;
|
|
|
+ return submitAudit(row, oldPrice, 'reject', '已拒绝改价');
|
|
|
+ })
|
|
|
+ .catch(() => {});
|
|
|
+ }
|
|
|
+
|
|
|
+ async function submitAudit(row, finalPrice, type, successText) {
|
|
|
+ approvingId.value = row.itemId;
|
|
|
+ actionType.value = type;
|
|
|
+ try {
|
|
|
+ const res = await approveAudit({
|
|
|
+ itemId: row.itemId,
|
|
|
+ finalPrice
|
|
|
+ });
|
|
|
+ ElMessage.success(actionMessage(res, successText));
|
|
|
+ reload();
|
|
|
+ } catch (e) {
|
|
|
+ ElMessage.error(e.message);
|
|
|
+ } finally {
|
|
|
+ approvingId.value = null;
|
|
|
+ actionType.value = '';
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
//查看淘宝和孔网
|
|
|
@@ -238,35 +302,101 @@
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
- /* 仿照截图中的Tabs样式 */
|
|
|
+ .audit-tabs {
|
|
|
+ display: inline-flex;
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-radius: 6px;
|
|
|
+ padding: 3px;
|
|
|
+ margin-bottom: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
:deep(.audit-tabs) .el-radio-button__inner {
|
|
|
- width: 200px;
|
|
|
- /* 增加宽度 */
|
|
|
- border-radius: 0;
|
|
|
- border: none;
|
|
|
- border-bottom: 2px solid transparent;
|
|
|
+ min-width: 88px;
|
|
|
+ height: 30px;
|
|
|
+ padding: 0 14px;
|
|
|
+ line-height: 30px;
|
|
|
+ border: none !important;
|
|
|
+ border-radius: 4px !important;
|
|
|
background: transparent;
|
|
|
- box-shadow: none;
|
|
|
- color: #666;
|
|
|
+ box-shadow: none !important;
|
|
|
+ color: var(--el-text-color-regular);
|
|
|
+ font-size: 13px;
|
|
|
}
|
|
|
|
|
|
:deep(.audit-tabs)
|
|
|
.el-radio-button__original-radio:checked
|
|
|
+ .el-radio-button__inner {
|
|
|
- background-color: #409eff;
|
|
|
- /* 蓝色背景 */
|
|
|
- color: white;
|
|
|
- border-radius: 0;
|
|
|
- /* 保持方形或自定义圆角 */
|
|
|
- box-shadow: none;
|
|
|
+ background: var(--el-color-primary);
|
|
|
+ color: #fff;
|
|
|
+ box-shadow: none !important;
|
|
|
}
|
|
|
|
|
|
- /* 整体背景可能需要调整,这里仅做基本样式覆盖 */
|
|
|
- .audit-tabs {
|
|
|
+ :deep(.audit-tabs) .el-radio-button:first-child .el-radio-button__inner,
|
|
|
+ :deep(.audit-tabs) .el-radio-button:last-child .el-radio-button__inner {
|
|
|
+ border-radius: 4px !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .new-price-cell {
|
|
|
display: flex;
|
|
|
- background-color: #fff;
|
|
|
- border-bottom: 1px solid #eee;
|
|
|
- margin-bottom: 10px;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .new-price-input {
|
|
|
+ width: 96px !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.new-price-input.el-input-number) {
|
|
|
+ width: 96px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.new-price-input .el-input__wrapper) {
|
|
|
+ padding-left: 8px;
|
|
|
+ padding-right: 8px;
|
|
|
width: 100%;
|
|
|
}
|
|
|
+
|
|
|
+ :deep(.new-price-input .el-input__inner) {
|
|
|
+ text-align: center;
|
|
|
+ height: 32px;
|
|
|
+ line-height: 32px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .fill-old-btn {
|
|
|
+ padding: 4px 8px !important;
|
|
|
+ min-height: 24px;
|
|
|
+ height: 24px;
|
|
|
+ font-size: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .action-btns {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: stretch;
|
|
|
+ gap: 8px;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .action-btn {
|
|
|
+ margin: 0 !important;
|
|
|
+ width: 100%;
|
|
|
+ min-height: 34px;
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .info-basic-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: 1fr 1fr;
|
|
|
+ column-gap: 16px;
|
|
|
+ row-gap: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .price-handler-cell {
|
|
|
+ line-height: 1.7;
|
|
|
+ }
|
|
|
+
|
|
|
+ .price-handler-cell .label {
|
|
|
+ color: var(--el-text-color-secondary);
|
|
|
+ }
|
|
|
</style>
|