1
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import request from '@/utils/request'
|
||||
import axios from 'axios'
|
||||
import { getToken } from '@/utils/auth'
|
||||
|
||||
// JD订单列表
|
||||
export function listJDOrders(query) {
|
||||
@@ -166,7 +168,22 @@ export function delJDOrder(ids) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
1
|
||||
|
||||
/** 导入跟团返现 Excel(multipart,不用统一 request 以免 Content-Type 覆盖) */
|
||||
export function importGroupRebateExcel(formData) {
|
||||
return axios
|
||||
.post(process.env.VUE_APP_BASE_API + '/system/jdorder/importGroupRebateExcel', formData, {
|
||||
headers: { Authorization: 'Bearer ' + getToken() }
|
||||
})
|
||||
.then((res) => {
|
||||
const d = res.data
|
||||
if (!d || d.code !== 200) {
|
||||
return Promise.reject(new Error((d && d.msg) || '导入失败'))
|
||||
}
|
||||
return d
|
||||
})
|
||||
}
|
||||
|
||||
// 手动获取物流信息(用于调试)
|
||||
export function fetchLogisticsManually(data) {
|
||||
return request({
|
||||
|
||||
@@ -89,6 +89,20 @@
|
||||
<el-option label="未晒评价" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="后返备注">
|
||||
<el-select
|
||||
v-model="rebateRemarkScreen"
|
||||
placeholder="全部"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 160px;"
|
||||
@change="onRebateRemarkScreenChange"
|
||||
>
|
||||
<el-option label="有导入记录" value="any" />
|
||||
<el-option label="含异常项" value="abnormal" />
|
||||
<el-option label="无异常项" value="ok" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 搜索按钮:桌面端显示,移动端展开时在底部显示 -->
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="small" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
@@ -116,6 +130,7 @@
|
||||
<el-button type="success" size="small" icon="el-icon-check" @click="handleBatchMarkRebateReceived" :loading="batchMarkLoading" title="批量将赔付金额大于0的订单标记为后返到账(仅执行一次)">批量标记后返到账</el-button>
|
||||
<el-button type="warning" size="small" icon="el-icon-sort" @click="handleReverseSyncThirdPartyOrderNo" :loading="reverseSyncLoading" title="从腾讯文档第850行开始,通过物流链接反向匹配订单,将腾讯文档的单号列值写入到订单的第三方单号字段">反向同步第三方单号</el-button>
|
||||
<el-button v-if="!isMobile" type="primary" size="small" icon="el-icon-document-copy" @click="handleBatchCopyExcelText" :disabled="selectedRows.length === 0" title="批量复制选中订单的录单格式(Excel可粘贴)">批量复制录单格式</el-button>
|
||||
<el-button v-if="!isMobile" type="primary" size="small" icon="el-icon-upload2" @click="rebateImportDialogVisible = true" title="上传跟团返现等 Excel,按单号写入后返备注(可多次导入累加)">导入后返表</el-button>
|
||||
<el-button v-if="!isMobile" type="success" size="small" icon="el-icon-document-copy" @click="handleBatchCopyRebateText" :disabled="selectedRows.length === 0" title="批量复制选中订单的后返录表格式(Excel可粘贴)">批量复制后返录表</el-button>
|
||||
<el-button v-if="!isMobile" type="info" size="small" icon="el-icon-document-copy" @click="handleBatchCopySichuanCommerceText" :disabled="selectedRows.length === 0" title="批量复制选中订单的四川商贸录表格式(日期 型号 数量 地址 价格 备注 是否安排 物流)">四川商贸录表</el-button>
|
||||
</div>
|
||||
@@ -255,6 +270,14 @@
|
||||
<span class="field-label">后返金额</span>
|
||||
<span class="field-value amount">{{ toYuan(row.rebateAmount) }}</span>
|
||||
</div>
|
||||
<div class="field-row" v-if="row.rebateRemarkJson">
|
||||
<span class="field-label">后返备注</span>
|
||||
<span class="field-value">
|
||||
<el-tag v-if="row.rebateRemarkHasAbnormal === 1" type="danger" size="mini">异常</el-tag>
|
||||
<el-tag v-else-if="row.rebateRemarkHasAbnormal === 0" type="success" size="mini">正常</el-tag>
|
||||
<span style="margin-left: 6px;">{{ rebateRemarkCount(row) }} 条记录</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="field-row">
|
||||
<span class="field-label">下单人</span>
|
||||
<span class="field-value">{{ row.buyer || '-' }}</span>
|
||||
@@ -366,6 +389,37 @@
|
||||
<el-table-column label="后返金额" prop="rebateAmount" width="110" align="right">
|
||||
<template slot-scope="scope">{{ toYuan(scope.row.rebateAmount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="后返备注" prop="rebateRemarkJson" min-width="200" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<template v-if="!scope.row.rebateRemarkJson">
|
||||
<span style="color: #c0c4cc;">-</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-tag v-if="scope.row.rebateRemarkHasAbnormal === 1" type="danger" size="mini">异常</el-tag>
|
||||
<el-tag v-else-if="scope.row.rebateRemarkHasAbnormal === 0" type="success" size="mini">正常</el-tag>
|
||||
<el-popover trigger="click" placement="left" width="420">
|
||||
<div class="rebate-remark-popover">
|
||||
<div
|
||||
v-for="(it, idx) in parseRebateRemarks(scope.row)"
|
||||
:key="idx"
|
||||
class="rebate-remark-item"
|
||||
>
|
||||
<div class="rebate-remark-title">
|
||||
<b>{{ it.documentTitle || '(未命名)' }}</b>
|
||||
<span class="rebate-remark-time">{{ formatRebateRemarkTime(it.uploadTime) }}</span>
|
||||
</div>
|
||||
<div>是否返现:{{ it.whetherRebate !== undefined && it.whetherRebate !== '' ? it.whetherRebate : '(空)' }}
|
||||
<el-tag v-if="it.abnormal" type="danger" size="mini">异常</el-tag>
|
||||
<el-tag v-else type="success" size="mini">正常</el-tag>
|
||||
</div>
|
||||
<div>返现金额:{{ it.rebateAmount !== undefined && it.rebateAmount !== '' ? it.rebateAmount : '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-button slot="reference" type="text" size="small">明细({{ rebateRemarkCount(scope.row) }})</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="下单人" prop="buyer" width="100"/>
|
||||
|
||||
<!-- 退款状态标签列(多行显示) -->
|
||||
@@ -824,11 +878,47 @@
|
||||
|
||||
<!-- 分销标识接收人配置 -->
|
||||
<distribution-mark-touser-config v-model="showTouserConfig" @config-updated="handleTouserConfigUpdated" />
|
||||
|
||||
<!-- 导入跟团返现 / 后返 Excel -->
|
||||
<el-dialog
|
||||
title="导入后返表(跟团返现等)"
|
||||
:visible.sync="rebateImportDialogVisible"
|
||||
width="520px"
|
||||
append-to-body
|
||||
@closed="rebateImportTitle = ''"
|
||||
>
|
||||
<p style="color: #909399; font-size: 13px; margin: 0 0 12px;">
|
||||
表头需包含「单号」或「订单号」、「是否返现」、返现金额列(优先「总共返现」)。按单号匹配系统订单并<strong>追加</strong>一条备注记录,同一订单多次上传会保留历史。
|
||||
</p>
|
||||
<el-form label-width="88px" size="small">
|
||||
<el-form-item label="文档标题">
|
||||
<el-input
|
||||
v-model="rebateImportTitle"
|
||||
placeholder="如:跟团+返现 260316(留空则用文件名)"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Excel">
|
||||
<el-upload
|
||||
drag
|
||||
:show-file-list="true"
|
||||
:limit="1"
|
||||
accept=".xlsx,.xls"
|
||||
:disabled="rebateImportLoading"
|
||||
:http-request="handleRebateExcelUpload"
|
||||
>
|
||||
<i class="el-icon-upload" />
|
||||
<div class="el-upload__text">拖到此处,或<em>点击上传</em></div>
|
||||
<div slot="tip" class="el-upload__tip">仅解析第一个工作表;未匹配到的单号会在结果中列出</div>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listJDOrders, updateJDOrder, delJDOrder, fetchLogisticsManually, batchMarkRebateReceived, generateExcelText } from '@/api/system/jdorder'
|
||||
import { listJDOrders, updateJDOrder, delJDOrder, fetchLogisticsManually, batchMarkRebateReceived, generateExcelText, importGroupRebateExcel } from '@/api/system/jdorder'
|
||||
import { fillLogisticsByOrderNo, getTokenStatus, getTencentDocAuthUrl, testUserInfo, getAutoWriteConfig, reverseSyncThirdPartyOrderNo } from '@/api/jarvis/tendoc'
|
||||
import { mapGetters } from 'vuex'
|
||||
import ListLayout from '@/components/ListLayout'
|
||||
@@ -875,8 +965,14 @@ export default {
|
||||
isRebateReceived: undefined,
|
||||
isPriceProtected: undefined,
|
||||
isInvoiceOpened: undefined,
|
||||
isReviewPosted: undefined
|
||||
isReviewPosted: undefined,
|
||||
hasRebateRemark: undefined,
|
||||
rebateRemarkHasAbnormal: undefined
|
||||
},
|
||||
rebateRemarkScreen: undefined,
|
||||
rebateImportDialogVisible: false,
|
||||
rebateImportTitle: '',
|
||||
rebateImportLoading: false,
|
||||
// 同步物流对话框
|
||||
syncLogisticsDialogVisible: false,
|
||||
syncLogisticsLoading: false,
|
||||
@@ -1121,6 +1217,78 @@ export default {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 后返备注列表筛选 */
|
||||
onRebateRemarkScreenChange(v) {
|
||||
this.queryParams.hasRebateRemark = undefined
|
||||
this.queryParams.rebateRemarkHasAbnormal = undefined
|
||||
if (v === 'any') {
|
||||
this.queryParams.hasRebateRemark = true
|
||||
} else if (v === 'abnormal') {
|
||||
this.queryParams.rebateRemarkHasAbnormal = 1
|
||||
} else if (v === 'ok') {
|
||||
this.queryParams.hasRebateRemark = true
|
||||
this.queryParams.rebateRemarkHasAbnormal = 0
|
||||
}
|
||||
this.queryParams.pageNum = 1
|
||||
this.prepareQueryParams()
|
||||
this.getList()
|
||||
},
|
||||
parseRebateRemarks(row) {
|
||||
if (!row || !row.rebateRemarkJson) return []
|
||||
try {
|
||||
const arr = JSON.parse(row.rebateRemarkJson)
|
||||
return Array.isArray(arr) ? arr : []
|
||||
} catch (e) {
|
||||
return []
|
||||
}
|
||||
},
|
||||
rebateRemarkCount(row) {
|
||||
return this.parseRebateRemarks(row).length
|
||||
},
|
||||
formatRebateRemarkTime(ts) {
|
||||
if (ts == null || ts === '') return ''
|
||||
const d = new Date(typeof ts === 'number' ? ts : Number(ts))
|
||||
if (Number.isNaN(d.getTime())) return ''
|
||||
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 min = String(d.getMinutes()).padStart(2, '0')
|
||||
return `${y}-${m}-${day} ${h}:${min}`
|
||||
},
|
||||
handleRebateExcelUpload(req) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', req.file)
|
||||
const title = (this.rebateImportTitle || '').trim()
|
||||
if (title) {
|
||||
formData.append('documentTitle', title)
|
||||
}
|
||||
this.rebateImportLoading = true
|
||||
importGroupRebateExcel(formData)
|
||||
.then((res) => {
|
||||
const data = res.data || {}
|
||||
const msg = data.message || res.msg || '导入完成'
|
||||
this.$message.success(msg)
|
||||
const nf = data.notFoundOrderNos
|
||||
if (nf && nf.length) {
|
||||
const sample = nf.slice(0, 30).join(', ')
|
||||
const more = nf.length > 30 ? ` …共 ${nf.length} 个` : ''
|
||||
this.$alert(`以下单号在系统中未找到,未写入:${sample}${more}`, '未匹配单号', { type: 'warning' })
|
||||
}
|
||||
if (data.errors && data.errors.length) {
|
||||
this.$message.warning(`部分行写入失败 ${data.errors.length} 条,详情见控制台`)
|
||||
console.warn('后返表导入错误', data.errors)
|
||||
}
|
||||
this.rebateImportDialogVisible = false
|
||||
this.getList()
|
||||
})
|
||||
.catch((e) => {
|
||||
this.$message.error(e.message || '导入失败')
|
||||
})
|
||||
.finally(() => {
|
||||
this.rebateImportLoading = false
|
||||
})
|
||||
},
|
||||
resetQuery() {
|
||||
this.queryParams = {
|
||||
pageNum: 1,
|
||||
@@ -1143,8 +1311,11 @@ export default {
|
||||
isRebateReceived: undefined,
|
||||
isPriceProtected: undefined,
|
||||
isInvoiceOpened: undefined,
|
||||
isReviewPosted: undefined
|
||||
isReviewPosted: undefined,
|
||||
hasRebateRemark: undefined,
|
||||
rebateRemarkHasAbnormal: undefined
|
||||
}
|
||||
this.rebateRemarkScreen = undefined
|
||||
// 重置排序为默认降序
|
||||
this.queryParams.orderBy = 'create_time'
|
||||
this.queryParams.isAsc = 'desc'
|
||||
@@ -2535,6 +2706,32 @@ export default {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.rebate-remark-popover .rebate-remark-item {
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.rebate-remark-popover .rebate-remark-item:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.rebate-remark-popover .rebate-remark-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.rebate-remark-popover .rebate-remark-time {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 移动端操作按钮样式 - 只在移动端生效 */
|
||||
@media (max-width: 768px) {
|
||||
.mobile-action-wrapper {
|
||||
|
||||
Reference in New Issue
Block a user