| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753 |
- <template>
- <ele-data-table
- row-key="userId"
- :columns="columns"
- :data="dataList"
- border
- class="order-books"
- :span-method="handleSpanMethod"
- >
- <template #baseInfo="{ row }">
- <div class="base-info flex justify-between">
- <div class="base-info-left flex flex-1">
- <el-image
- style="min-width: 80px; width: 80px; height: 100px"
- fit="cover"
- :src="row.cover"
- :preview-src-list="[row.cover]"
- :initial-index="0"
- preview-teleported
- />
- <div
- class="base-info-left-con flex flex-col items-start ml-3"
- >
- <div style="text-align: left;"
- ><el-text
- type="primary"
- style="cursor: pointer"
- @click="handleBooksEdit(row)"
- >{{ row.bookName }}</el-text
- ></div
- >
- <div
- ><el-text>ISBN:{{ row.isbn }}</el-text></div
- >
- <div class="base-info-btns flex">
- <el-button
- size="small"
- color="#4f4f4f"
- v-if="row.bookStatus != 3"
- @click="handleBlackList([row.isbn])"
- >加入黑名单</el-button
- >
- <el-button
- size="small"
- color="#4f4f4f"
- v-if="row.bookStatus == 3"
- >已在黑名单</el-button
- >
- <el-button
- size="small"
- type="success"
- v-if="row.bookStatus == 1"
- @click="handleAddBookList(row)"
- >加入回收书单</el-button
- >
- <el-button
- size="small"
- color="#2d430a"
- v-if="row.bookStatus == 2"
- >已在回收书单</el-button
- >
- <el-button
- size="small"
- type="warning"
- v-if="row.settingStatus == 0"
- @click="handleSpecifiedDiscount(row)"
- >指定回收折扣</el-button
- >
- <el-button
- size="small"
- color="#7728f5"
- v-if="row.settingStatus == 1"
- @click="handleModifyDiscount(row)"
- >修改回收折扣</el-button
- >
- </div>
- <div
- ><el-text type="danger"
- >(已回收数量:{{ row.recycleNum }}当前库存:{{
- row.stockNum
- }})</el-text
- ></div
- >
- </div>
- </div>
- <div class="base-info-right shrink-0" style="width: 210px">
- <div class="common-text flex">
- <el-text>定 价:</el-text>
- <el-text>¥ {{ row.bookPrice }}</el-text>
- </div>
- <div class="common-text flex">
- <el-text>回收折扣:</el-text>
- <el-text>{{ row.recycleDiscount }}折</el-text>
- <el-text
- v-if="row.sugDiscountStr"
- style="color: #f56c6c; margin-left: 10px"
- >{{ row.sugDiscountStr }}</el-text
- >
- </div>
- <div class="common-text flex" v-if="row.discountChangeLog">
- <el-text style="color: #3ab54b"
- >{{ row.discountChangeLog.userName }}:</el-text
- >
- <el-text style="color: #3ab54b">{{
- row.discountChangeLog.changeTime
- }}</el-text>
- </div>
- <div class="common-text flex">
- <el-text>回收单价:</el-text>
- <el-text>¥ {{ row.recyclePrice }}</el-text>
- <el-text
- v-if="row.isupSell"
- style="
- color: #f56c6c;
- font-weight: 500;
- margin-left: 2px;
- "
- >
- +{{
- isExpand
- ? row.upsellPrice
- : `${row.upsellPrice}×${row.upsellNum}`
- }}</el-text
- >
- </div>
- <div class="common-text flex">
- <el-text>销售价格:</el-text>
- <el-text>¥ {{ row.productPrice }}</el-text>
- <el-icon
- :size="14"
- color="#f56c6c"
- @click="handleEditProductPrice(row)"
- style="
- margin-left: 6px;
- position: relative;
- top: 5px;
- "
- >
- <EditPen />
- </el-icon>
- </div>
- <div
- class="common-text flex"
- v-if="row.productPriceChangeLog"
- >
- <el-text style="color: #3ab54b"
- >{{ row.productPriceChangeLog.userName }}:</el-text
- >
- <el-text style="color: #3ab54b">{{
- row.productPriceChangeLog.changeTime
- }}</el-text>
- </div>
- </div>
- </div>
- </template>
- <template #action="{ row }">
- <div class="action-btns">
- <el-button
- class="mb-10"
- color="#4f4f4f"
- @click="handleAuditPic(row)"
- >审核图片</el-button
- >
- <el-button
- class="mb-10"
- color="#a4adb3"
- @click="handleViewUrl(row, 'dd')"
- >查看当当</el-button
- >
- <el-button
- class="mb-10"
- color="#e99d42"
- @click="handleRecycleLog(row)"
- >回收日志</el-button
- >
- <el-button
- class="mb-10"
- color="#f27606"
- @click="handleViewUrl(row, 'tb')"
- >查看淘宝</el-button
- >
- <el-button color="#0f7dc7" @click="handleSalesLog(row)"
- >售价日志</el-button
- >
- <el-button color="#399420" @click="handleViewUrl(row, 'kw')"
- >查看孔网</el-button
- >
- </div>
- </template>
- <template #auditInfo="{ row }">
- <div class="audit-info flex justify-center">
- <el-radio-group
- v-model="row.sts"
- style="width: 120px"
- :disabled="!(detail.status == 8 || detail.status == 9)"
- @change="(value) => handleAuditInfo(value, row)"
- :class="row.sts == 1 ? 'class-green' : 'class-red'"
- >
- <el-radio :value="1">品相良好</el-radio>
- <el-radio :value="2" disabled>品相一般</el-radio>
- <el-radio :value="3">品相极差</el-radio>
- </el-radio-group>
- <el-select
- v-model="row.com"
- style="width: 180px"
- placeholder="请选择品相极差的原因"
- multiple
- :disabled="
- !(detail.status == 8 || detail.status == 9) ||
- row.sts !== 3
- "
- class="reason-select"
- @change="(value) => handleSelectReason(value, row)"
- >
- <el-option
- v-for="item in auditReason"
- :key="item.dictValue"
- :label="item.dictValue"
- :value="item.dictValue"
- />
- </el-select>
- </div>
- </template>
- </ele-data-table>
- <orderModifyDiscount
- ref="specifiedRef"
- @refresh="(value) => handleRefresh('specified', value)"
- />
- <setParams
- ref="modifyRef"
- @refresh="(value) => handleRefresh('modify', value)"
- />
- <orderBlacklist ref="blacklistRef" @refresh="handleRefresh('blacklist')" />
- <orderRecycleLog ref="recycleLogRef" />
- <orderSalesLog ref="salesLogRef" />
- <booksEdit ref="booksEditRef" />
- <auditScreenshotIsbn ref="auditScreenshotIsbnRef" />
- <ModifyProductPrice
- ref="productPriceDialogRef"
- @refresh="(value) => handleRefresh('productPrice', value)"
- />
- </template>
- <script setup>
- import { ref, reactive, watch, nextTick, onMounted, computed } from 'vue';
- import orderModifyDiscount from '@/views/recycle/components/modify-discount.vue';
- import orderBlacklist from '@/views/recycleOrder/detail/order-blacklist.vue';
- import orderRecycleLog from '@/views/recycleOrder/detail/order-recycle-log.vue';
- import orderSalesLog from '@/views/recycleOrder/detail/order-sales-log.vue';
- import setParams from '@/views/recycle/components/set-params.vue';
- import BooksEdit from '@/views/data/books/components/books-edit.vue';
- import auditScreenshotIsbn from '@/views/recycleOrder/components/audit-screenshot-isbn.vue';
- import request from '@/utils/request';
- import { EditPen } from '@element-plus/icons-vue';
- import ModifyProductPrice from '@/views/recycle/components/modify-product-price.vue';
- const props = defineProps({
- detail: {
- type: Object,
- default: () => ({
- detailVoList: []
- })
- },
- isExpand: {
- type: Boolean,
- default: false
- }
- });
- const dataList = ref([]);
- const booksEditRef = ref();
- function handleBooksEdit(row) {
- row.id = row.bookId;
- booksEditRef.value?.handleOpen(row);
- }
- // 处理detailVoList数据
- const processDetailList = (list) => {
- if (!list) return [];
- const result = [];
- let currentIndex = 0;
- list.forEach((item) => {
- let auditInfo = item.auditCommentList;
- // 根据num拆分对象
- for (let i = 0; i < item.num; i++) {
- let audit = auditInfo
- ? auditInfo[i]
- ? auditInfo[i]
- : { sts: 0, com: [] }
- : { sts: 0, com: [] };
- // 如果com存在且包含逗号,则分割为数组
- if (audit.com && typeof audit.com === 'string') {
- audit.com = audit.com.split(',').filter(Boolean);
- } else if (!Array.isArray(audit.com)) {
- audit.com = [];
- }
- result.push({
- ...item,
- ...audit,
- _index: i,
- _groupIndex: currentIndex,
- _isFirstRow: i === 0,
- isupSell: item.upsellNum > i
- });
- }
- currentIndex++;
- });
- console.log(result, 'result');
- return result;
- };
- // 初始化数据
- const initData = () => {
- const list = props.detail.detailVoList || [];
- console.log('Initializing data with list:', list);
- if (props.isExpand) {
- dataList.value = processDetailList(list);
- } else {
- const processedList = [];
- list.forEach((item) => {
- processedList.push({
- ...item,
- isupSell: item.upsellNum && item.upsellNum > 0,
- _index: 0,
- _groupIndex: processedList.length,
- _isFirstRow: true,
- sts:
- item.auditCommentList && item.auditCommentList[0]
- ? item.auditCommentList[0].sts
- : 0,
- com:
- item.auditCommentList &&
- item.auditCommentList[0] &&
- item.auditCommentList[0].com
- ? typeof item.auditCommentList[0].com === 'string'
- ? item.auditCommentList[0].com
- .split(',')
- .filter(Boolean)
- : item.auditCommentList[0].com
- : []
- });
- });
- dataList.value = processedList;
- }
- console.log('Initialized dataList:', dataList.value);
- };
- // 组件挂载时初始化数据
- onMounted(() => {
- initData();
- });
- // 添加对detail.detailVoList的监听,确保弹窗打开时数据能正确显示
- watch(
- () => props.detail.detailVoList,
- (newVal) => {
- if (!newVal) return;
- console.log('detail.detailVoList changed:', newVal);
- initData();
- },
- { immediate: true, deep: true }
- );
- watch(
- () => props.isExpand,
- (newVal) => {
- console.log('isExpand changed:', newVal);
- initData();
- },
- { deep: true, immediate: true }
- );
- // 处理单元格合并
- const handleSpanMethod = ({ row, column, rowIndex }) => {
- if (column.property === 'num') {
- // 确保行有必要的属性
- if (!row._groupIndex && row._groupIndex !== 0) {
- return {
- rowspan: 1,
- colspan: 1
- };
- }
- // 找到当前行所在组的所有行
- const currentGroup = dataList.value.filter(
- (item) => item._groupIndex === row._groupIndex
- );
- if (row._isFirstRow) {
- // 如果是组内第一行,设置合并行数
- return {
- rowspan: currentGroup.length,
- colspan: 1
- };
- } else {
- // 组内其他行不显示
- return {
- rowspan: 0,
- colspan: 0
- };
- }
- }
- return {
- rowspan: 1,
- colspan: 1
- };
- };
- //审核书籍
- function handleAudit(row) {
- const payload = {
- orderId: props.detail.orderId,
- isbn: row.isbn,
- inx: row._index,
- sts: row.sts,
- com: Array.isArray(row.com) ? row.com.join(',') : ''
- };
- request
- .post('/order/orderInfo/adminCheckOrder', payload)
- .then((res) => {
- if (res.data.code == 200) {
- ElMessage.success('操作成功');
- } else {
- ElMessage.error(res.data.msg);
- }
- });
- }
- //其余审核良好 列表中sts为0的设置为1,并提交
- function handleOtherAuditGood() {
- let stsList = [];
- dataList.value.forEach((item) => {
- if (item.sts == 0) {
- item.sts = 1;
- stsList.push({
- orderId: props.detail.orderId,
- isbn: item.isbn,
- sts: 1,
- com: '',
- inx: item._index
- });
- }
- });
- let data = {
- orderIds: [props.detail.orderId],
- checkType: 2
- };
- //后端接口批量审核
- request.post('/order/orderInfo/adminCheckBatch', data).then((res) => {
- if (res.data.code == 200) {
- ElMessage.success('操作成功');
- emit('close');
- } else {
- ElMessage.error(res.data.msg);
- }
- });
- }
- //单选框选择变化
- function handleAuditInfo(value, row) {
- if (value == 1) {
- row.com = [];
- nextTick(() => {
- handleAudit(row);
- });
- } else if (value == 3 && row.com.length > 0) {
- nextTick(() => {
- handleAudit(row);
- });
- }
- }
- //选择审核原因
- function handleSelectReason(value, row) {
- if (row.sts == 3) {
- row.com = value;
- nextTick(() => {
- handleAudit(row);
- });
- }
- }
- const emit = defineEmits(['update:detail', 'refresh', 'close']);
- const columns = ref([
- {
- type: 'index',
- columnKey: 'index',
- width: 60,
- align: 'center'
- },
- {
- label: '信息',
- prop: 'baseInfo',
- slot: 'baseInfo',
- minWidth: 620,
- align: 'center'
- },
- {
- label: '操作',
- prop: 'action',
- slot: 'action',
- width: 220,
- align: 'center'
- },
- {
- label: '数量',
- prop: 'num',
- minWidth: 90,
- align: 'center',
- formatter: (row) => {
- return `× ${row.num}`;
- }
- },
- {
- label: '审核信息',
- prop: 'auditInfo',
- slot: 'auditInfo',
- columnKey: 'auditInfo',
- align: 'center',
- minWidth: 317,
- renderHeader: (row) => {
- let data = auditStats();
- return `审核信息(总数:${data.total},加价数量${data.upsell},良好:${data.good},一般:${data.normal},极差:${data.bad})`;
- }
- },
- {
- label: '审核金额',
- prop: 'recyclePrice',
- align: 'center',
- minWidth: 100,
- formatter: (row) => {
- return row.sts == 1
- ? `¥ ${(row.recyclePrice + (row.isupSell ? row.upsellPrice : 0)).toFixed(2)}`
- : '0';
- }
- }
- ]);
- //获取审核原因的字典 book_audit_reason
- const auditReason = ref([]);
- const getAuditReason = async () => {
- const res = await request.get(
- '/system/dict/data/type/book_audit_reason'
- );
- auditReason.value = res.data.data;
- console.log(res, 'xxxx');
- };
- getAuditReason();
- //查看当当、淘宝、豆瓣链接
- const handleViewUrl = (row, type) => {
- let url = '';
- if (type == 'dd') {
- url = `https://search.dangdang.com/?key=${row.isbn}&act=input`;
- } else if (type == 'tb') {
- url = `https://s.taobao.com/search?page=1&q=${row.isbn}&sort=sale-desc&tab=all`;
- } else if (type == 'db') {
- url = `https://search.douban.com/book/subject_search?search_text=${row.isbn}`;
- } else if (type == 'kw') {
- url = `https://search.kongfz.com/product_result/?key=${row.isbn}&status=0&_stpmt=eyJzZWFyY2hfdHlwZSI6ImFjdGl2ZSJ9`;
- }
- window.open(url, '_blank');
- };
- //加入回收书单
- const handleAddBookList = (row) => {
- ElMessageBox.confirm('确认加入回收书单?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '关闭',
- type: 'warning'
- }).then(() => {
- request
- .post('/book/bookRecycleInfo/addIn', {
- isbnList: [row.isbn]
- })
- .then(() => {
- ElMessage.success('操作成功');
- // 更新列表数据
- const index = props.detail.detailVoList.findIndex(
- (item) => item.isbn === row.isbn
- );
- if (index > -1) {
- const newList = [...props.detail.detailVoList];
- newList[index] = { ...newList[index], bookStatus: 2 };
- dataList.value = newList;
- }
- });
- });
- };
- const currentRow = ref(null);
- //修改回收折扣
- const modifyRef = ref();
- const handleModifyDiscount = (row) => {
- currentRow.value = row;
- modifyRef.value?.handleOpen(row);
- };
- //指定回收折扣
- const specifiedRef = ref();
- const handleSpecifiedDiscount = (row) => {
- currentRow.value = row;
- specifiedRef.value?.handleOpen(row);
- };
- //加入黑名单
- const blacklistRef = ref();
- const handleBlackList = (row) => {
- currentRow.value = row;
- blacklistRef.value?.handleOpen(row);
- };
- //查看回收日志
- const recycleLogRef = ref();
- const handleRecycleLog = (row) => {
- recycleLogRef.value?.handleOpen(row);
- };
- //查看售价日志
- const salesLogRef = ref();
- const handleSalesLog = (row) => {
- salesLogRef.value?.handleOpen(row);
- };
- //审核图片
- const auditScreenshotIsbnRef = ref();
- const handleAuditPic = (row) => {
- row.orderId = props.detail.orderId;
- auditScreenshotIsbnRef.value?.handleOpen(row);
- };
- const handleRefresh = (type, value) => {
- console.log(type, value, 'type, value');
- if (!currentRow.value) return;
- const newList = [...dataList.value];
- // 更新所有具有相同ISBN的项目
- newList.forEach((item, idx) => {
- if (item.isbn === currentRow.value.isbn) {
- if (type === 'specified' || type === 'modify') {
- newList[idx] = {
- ...newList[idx],
- settingStatus: 1,
- recycleDiscount: value
- };
- } else if (type === 'blacklist') {
- newList[idx] = { ...newList[idx], bookStatus: 3 };
- } else if (type === 'productPrice') {
- newList[idx] = { ...newList[idx], productPrice: value };
- }
- }
- });
- dataList.value = newList;
- };
- // 手动刷新数据
- const refreshData = () => {
- initData();
- };
- const auditStats = function () {
- console.log(dataList.value, 'dataList.value');
- const total = props.detail.totalNum;
- let upsell = 0,
- good = 0,
- normal = 0,
- bad = 0;
- dataList.value.forEach((item) => {
- if (item.isupSell) upsell++;
- if (item.sts == 1) good++;
- if (item.sts == 2) normal++;
- if (item.sts == 3) bad++;
- });
- return {
- total,
- upsell,
- good,
- normal,
- bad
- };
- };
- // 修改销售价格
- const productPriceDialogRef = ref(null);
- const handleEditProductPrice = (row) => {
- currentRow.value = row;
- productPriceDialogRef.value?.handleOpen(row);
- };
- defineExpose({
- handleOtherAuditGood,
- refreshData
- });
- </script>
- <style lang="scss" scoped>
- .mb-10 {
- margin-bottom: 7px;
- }
- .reason-select {
- :deep(.el-select__wrapper) {
- height: 120px !important;
- }
- :deep(.el-select__placeholder) {
- top: 0;
- text-wrap: wrap;
- white-space: normal;
- text-overflow: initial;
- }
- }
- .class-green {
- :deep(.el-radio.is-checked .el-radio__inner) {
- background: #399420;
- border-color: #399420;
- }
- :deep(.el-radio__input.is-checked + .el-radio__label) {
- color: #399420;
- }
- }
- .class-red {
- :deep(.el-radio.is-checked .el-radio__inner) {
- background: #f56c6c;
- border-color: #f56c6c;
- }
- :deep(.el-radio__input.is-checked + .el-radio__label) {
- color: #f56c6c;
- }
- }
- .order-books {
- .action-btns {
- display: flex;
- flex-wrap: wrap;
- gap: 10px;
- .el-button {
- margin: 0;
- color: #fff;
- }
- }
- // 处理合并单元格效果
- .el-table {
- td.el-table__cell {
- &.first-row {
- border-bottom: none;
- }
- }
- }
- }
- </style>
|