1
This commit is contained in:
@@ -61,9 +61,8 @@ server {
|
|||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header X-Forwarded-Host $server_name;
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
|
||||||
# 请求体相关配置(重要:支持POST请求)
|
# 勿手动设置 Content-Type / Content-Length:multipart 上传必须原样转发(含 boundary),
|
||||||
proxy_set_header Content-Type $content_type;
|
# 且分块请求时 $content_length 可能为空,会导致后端报「not a multipart request」。
|
||||||
proxy_set_header Content-Length $content_length;
|
|
||||||
proxy_pass_request_headers on;
|
proxy_pass_request_headers on;
|
||||||
proxy_pass_request_body on;
|
proxy_pass_request_body on;
|
||||||
|
|
||||||
@@ -96,9 +95,6 @@ server {
|
|||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header X-Forwarded-Host $server_name;
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
|
||||||
# POST请求支持
|
|
||||||
proxy_set_header Content-Type $content_type;
|
|
||||||
proxy_set_header Content-Length $content_length;
|
|
||||||
proxy_pass_request_headers on;
|
proxy_pass_request_headers on;
|
||||||
proxy_pass_request_body on;
|
proxy_pass_request_body on;
|
||||||
|
|
||||||
@@ -124,8 +120,6 @@ server {
|
|||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header X-Forwarded-Host $server_name;
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
|
||||||
proxy_set_header Content-Type $content_type;
|
|
||||||
proxy_set_header Content-Length $content_length;
|
|
||||||
proxy_pass_request_headers on;
|
proxy_pass_request_headers on;
|
||||||
proxy_pass_request_body on;
|
proxy_pass_request_body on;
|
||||||
|
|
||||||
@@ -147,9 +141,6 @@ server {
|
|||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header X-Forwarded-Host $server_name;
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
|
||||||
# POST请求支持
|
|
||||||
proxy_set_header Content-Type $content_type;
|
|
||||||
proxy_set_header Content-Length $content_length;
|
|
||||||
proxy_pass_request_headers on;
|
proxy_pass_request_headers on;
|
||||||
proxy_pass_request_body on;
|
proxy_pass_request_body on;
|
||||||
|
|
||||||
|
|||||||
@@ -178,12 +178,18 @@ export function listGroupRebateExcelUploads(query) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导入跟团返现 Excel(multipart) */
|
/** 删除后返表上传记录,并回滚对应订单后返备注(新导入数据) */
|
||||||
export function importGroupRebateExcel(formData) {
|
export function deleteGroupRebateUpload(id) {
|
||||||
|
return request({
|
||||||
|
url: '/system/jdorder/groupRebateUpload/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function postGroupRebateMultipart(url, formData) {
|
||||||
return axios
|
return axios
|
||||||
.post(process.env.VUE_APP_BASE_API + '/system/jdorder/importGroupRebateExcel', formData, {
|
.post(process.env.VUE_APP_BASE_API + url, formData, {
|
||||||
headers: { Authorization: 'Bearer ' + getToken() },
|
headers: { Authorization: 'Bearer ' + getToken() },
|
||||||
// 全局 axios.defaults 为 application/json,会覆盖 multipart;必须去掉由浏览器自动带 boundary
|
|
||||||
transformRequest: [
|
transformRequest: [
|
||||||
(data, headers) => {
|
(data, headers) => {
|
||||||
if (data instanceof FormData) {
|
if (data instanceof FormData) {
|
||||||
@@ -200,12 +206,22 @@ export function importGroupRebateExcel(formData) {
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
const d = res.data
|
const d = res.data
|
||||||
if (!d || d.code !== 200) {
|
if (!d || d.code !== 200) {
|
||||||
return Promise.reject(new Error((d && d.msg) || '导入失败'))
|
return Promise.reject(new Error((d && d.msg) || '请求失败'))
|
||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 导入跟团返现 Excel(multipart,单文件) */
|
||||||
|
export function importGroupRebateExcel(formData) {
|
||||||
|
return postGroupRebateMultipart('/system/jdorder/importGroupRebateExcel', formData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量导入后返表(multipart,多个 files 字段) */
|
||||||
|
export function importGroupRebateExcelBatch(formData) {
|
||||||
|
return postGroupRebateMultipart('/system/jdorder/importGroupRebateExcelBatch', formData)
|
||||||
|
}
|
||||||
|
|
||||||
// 手动获取物流信息(用于调试)
|
// 手动获取物流信息(用于调试)
|
||||||
export function fetchLogisticsManually(data) {
|
export function fetchLogisticsManually(data) {
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
@@ -130,7 +130,7 @@
|
|||||||
<el-button type="success" size="small" icon="el-icon-check" @click="handleBatchMarkRebateReceived" :loading="batchMarkLoading" title="批量将赔付金额大于0的订单标记为后返到账(仅执行一次)">批量标记后返到账</el-button>
|
<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 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-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="primary" size="small" icon="el-icon-upload2" @click="rebateImportDialogVisible = true" title="可一次选多个 Excel,提交后由后台依次导入;详情见后返上传记录">导入后返表</el-button>
|
||||||
<el-button v-if="!isMobile" type="info" size="small" icon="el-icon-folder-opened" @click="openRebateUploadRecordDialog" title="查看历史上传的后返表原件并可重新下载">后返上传记录</el-button>
|
<el-button v-if="!isMobile" type="info" size="small" icon="el-icon-folder-opened" @click="openRebateUploadRecordDialog" title="查看历史上传的后返表原件并可重新下载">后返上传记录</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="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>
|
<el-button v-if="!isMobile" type="info" size="small" icon="el-icon-document-copy" @click="handleBatchCopySichuanCommerceText" :disabled="selectedRows.length === 0" title="批量复制选中订单的四川商贸录表格式(日期 型号 数量 地址 价格 备注 是否安排 物流)">四川商贸录表</el-button>
|
||||||
@@ -880,38 +880,48 @@
|
|||||||
<!-- 分销标识接收人配置 -->
|
<!-- 分销标识接收人配置 -->
|
||||||
<distribution-mark-touser-config v-model="showTouserConfig" @config-updated="handleTouserConfigUpdated" />
|
<distribution-mark-touser-config v-model="showTouserConfig" @config-updated="handleTouserConfigUpdated" />
|
||||||
|
|
||||||
<!-- 导入跟团返现 / 后返 Excel -->
|
<!-- 导入跟团返现 / 后返 Excel(支持多文件,一次提交后台依次处理) -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
title="导入后返表(跟团返现等)"
|
title="导入后返表(跟团返现等)"
|
||||||
:visible.sync="rebateImportDialogVisible"
|
:visible.sync="rebateImportDialogVisible"
|
||||||
width="520px"
|
width="520px"
|
||||||
append-to-body
|
append-to-body
|
||||||
@closed="rebateImportTitle = ''"
|
@closed="onRebateImportDialogClosed"
|
||||||
>
|
>
|
||||||
<p style="color: #909399; font-size: 13px; margin: 0 0 12px;">
|
<p style="color: #909399; font-size: 13px; margin: 0 0 12px;">
|
||||||
表头需包含「单号」或「订单号」、「是否返现」、返现金额列(优先「总共返现」)。按单号匹配系统订单并<strong>追加</strong>一条备注记录,同一订单多次上传会保留历史。
|
表头需包含「单号」或「订单号」、「是否返现」、返现金额列(优先「总共返现」)。可选<strong>多个</strong> Excel,点「提交后台处理」后由服务端依次导入;不弹逐条结果,请到「后返上传记录」查看。
|
||||||
</p>
|
</p>
|
||||||
<el-form label-width="88px" size="small">
|
<el-form label-width="88px" size="small">
|
||||||
<el-form-item label="文档标题">
|
<el-form-item label="文档标题">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="rebateImportTitle"
|
v-model="rebateImportTitle"
|
||||||
placeholder="如:跟团+返现 260316(留空则用文件名)"
|
placeholder="仅选 1 个文件时可用;多文件时各文件用各自文件名"
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Excel">
|
<el-form-item label="Excel">
|
||||||
<el-upload
|
<el-upload
|
||||||
|
ref="rebateExcelUploader"
|
||||||
drag
|
drag
|
||||||
|
multiple
|
||||||
:show-file-list="true"
|
:show-file-list="true"
|
||||||
:limit="1"
|
:limit="30"
|
||||||
|
:auto-upload="false"
|
||||||
accept=".xlsx,.xls"
|
accept=".xlsx,.xls"
|
||||||
:disabled="rebateImportLoading"
|
:disabled="rebateImportLoading"
|
||||||
:http-request="handleRebateExcelUpload"
|
:on-exceed="onRebateExcelExceed"
|
||||||
>
|
>
|
||||||
<i class="el-icon-upload" />
|
<i class="el-icon-upload" />
|
||||||
<div class="el-upload__text">拖到此处,或<em>点击上传</em></div>
|
<div class="el-upload__text">拖到此处,或<em>点击选择</em>(可多选)</div>
|
||||||
<div slot="tip" class="el-upload__tip">仅解析第一个工作表;未匹配到的单号会在结果中列出</div>
|
<div slot="tip" class="el-upload__tip">单次最多 30 个文件;仅解析每个文件的第一个工作表</div>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
:loading="rebateImportLoading"
|
||||||
|
style="margin-top: 10px"
|
||||||
|
@click="submitRebateExcelBatch"
|
||||||
|
>提交后台处理</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -942,7 +952,7 @@
|
|||||||
<el-table-column label="未匹配" prop="notFoundCount" width="72" align="center" />
|
<el-table-column label="未匹配" prop="notFoundCount" width="72" align="center" />
|
||||||
<el-table-column label="上传人" prop="createBy" width="100" show-overflow-tooltip />
|
<el-table-column label="上传人" prop="createBy" width="100" show-overflow-tooltip />
|
||||||
<el-table-column label="时间" prop="createTime" width="155" />
|
<el-table-column label="时间" prop="createTime" width="155" />
|
||||||
<el-table-column label="操作" width="100" align="center" fixed="right">
|
<el-table-column label="操作" width="148" align="center" fixed="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button
|
||||||
type="text"
|
type="text"
|
||||||
@@ -950,6 +960,11 @@
|
|||||||
:disabled="!scope.row.filePath"
|
:disabled="!scope.row.filePath"
|
||||||
@click="downloadRebateUploadFile(scope.row)"
|
@click="downloadRebateUploadFile(scope.row)"
|
||||||
>下载</el-button>
|
>下载</el-button>
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
@click="confirmDeleteRebateUpload(scope.row)"
|
||||||
|
>删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -965,7 +980,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listJDOrders, updateJDOrder, delJDOrder, fetchLogisticsManually, batchMarkRebateReceived, generateExcelText, importGroupRebateExcel, listGroupRebateExcelUploads } from '@/api/system/jdorder'
|
import { listJDOrders, updateJDOrder, delJDOrder, fetchLogisticsManually, batchMarkRebateReceived, generateExcelText, importGroupRebateExcelBatch, listGroupRebateExcelUploads, deleteGroupRebateUpload } from '@/api/system/jdorder'
|
||||||
import { fillLogisticsByOrderNo, getTokenStatus, getTencentDocAuthUrl, testUserInfo, getAutoWriteConfig, reverseSyncThirdPartyOrderNo } from '@/api/jarvis/tendoc'
|
import { fillLogisticsByOrderNo, getTokenStatus, getTencentDocAuthUrl, testUserInfo, getAutoWriteConfig, reverseSyncThirdPartyOrderNo } from '@/api/jarvis/tendoc'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import ListLayout from '@/components/ListLayout'
|
import ListLayout from '@/components/ListLayout'
|
||||||
@@ -1311,38 +1326,51 @@ export default {
|
|||||||
const min = String(d.getMinutes()).padStart(2, '0')
|
const min = String(d.getMinutes()).padStart(2, '0')
|
||||||
return `${y}-${m}-${day} ${h}:${min}`
|
return `${y}-${m}-${day} ${h}:${min}`
|
||||||
},
|
},
|
||||||
handleRebateExcelUpload(req) {
|
clearRebateExcelUploaderFiles() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const u = this.$refs.rebateExcelUploader
|
||||||
|
if (u && typeof u.clearFiles === 'function') {
|
||||||
|
u.clearFiles()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onRebateImportDialogClosed() {
|
||||||
|
this.rebateImportTitle = ''
|
||||||
|
this.clearRebateExcelUploaderFiles()
|
||||||
|
},
|
||||||
|
onRebateExcelExceed() {
|
||||||
|
this.$message.warning('单次最多选择 30 个文件')
|
||||||
|
},
|
||||||
|
submitRebateExcelBatch() {
|
||||||
|
const u = this.$refs.rebateExcelUploader
|
||||||
|
const uploadFiles = (u && u.uploadFiles) ? u.uploadFiles : []
|
||||||
|
const files = uploadFiles.map((f) => f.raw).filter(Boolean)
|
||||||
|
if (!files.length) {
|
||||||
|
this.$message.warning('请先选择 Excel 文件')
|
||||||
|
return
|
||||||
|
}
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', req.file)
|
files.forEach((file) => formData.append('files', file))
|
||||||
const title = (this.rebateImportTitle || '').trim()
|
const title = (this.rebateImportTitle || '').trim()
|
||||||
if (title) {
|
if (files.length === 1 && title) {
|
||||||
formData.append('documentTitle', title)
|
formData.append('documentTitle', title)
|
||||||
}
|
}
|
||||||
this.rebateImportLoading = true
|
this.rebateImportLoading = true
|
||||||
importGroupRebateExcel(formData)
|
importGroupRebateExcelBatch(formData)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
const data = res.data || {}
|
const data = res.data || {}
|
||||||
const msg = data.message || res.msg || (data.success === false ? '导入未完成' : '导入完成')
|
const msg = data.message || res.msg || '已处理'
|
||||||
if (data.success === false) {
|
if (data.failCount > 0) {
|
||||||
this.$message.warning(msg)
|
this.$message.warning(msg)
|
||||||
} else {
|
} else {
|
||||||
this.$message.success(msg)
|
this.$message.success(msg)
|
||||||
}
|
}
|
||||||
const nf = data.notFoundOrderNos
|
this.clearRebateExcelUploaderFiles()
|
||||||
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.rebateImportDialogVisible = false
|
||||||
this.getList()
|
this.getList()
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
this.$message.error(e.message || '导入失败')
|
this.$message.error(e.message || '提交失败')
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.rebateImportLoading = false
|
this.rebateImportLoading = false
|
||||||
@@ -1373,6 +1401,26 @@ export default {
|
|||||||
const name = row.originalFilename || `rebate_upload_${row.id}.xlsx`
|
const name = row.originalFilename || `rebate_upload_${row.id}.xlsx`
|
||||||
this.download(`/system/jdorder/groupRebateUpload/download/${row.id}`, {}, name)
|
this.download(`/system/jdorder/groupRebateUpload/download/${row.id}`, {}, name)
|
||||||
},
|
},
|
||||||
|
confirmDeleteRebateUpload(row) {
|
||||||
|
const title = row.documentTitle || row.originalFilename || ('ID ' + row.id)
|
||||||
|
this.$confirm(
|
||||||
|
`将删除上传记录「${title}」,并尝试从订单中移除本次导入写入的后返备注。历史导入(无上传批次标记)可能无法自动清除订单备注,是否继续?`,
|
||||||
|
'删除后返上传记录',
|
||||||
|
{ type: 'warning', confirmButtonText: '删除', cancelButtonText: '取消' }
|
||||||
|
).then(() => {
|
||||||
|
return deleteGroupRebateUpload(row.id)
|
||||||
|
}).then((res) => {
|
||||||
|
const data = res.data || {}
|
||||||
|
const msg = data.message || res.msg || '已删除'
|
||||||
|
this.$message.success(msg)
|
||||||
|
this.fetchRebateUploadList()
|
||||||
|
this.getList()
|
||||||
|
}).catch((e) => {
|
||||||
|
if (e !== 'cancel') {
|
||||||
|
this.$message.error((e && e.message) || '删除失败')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.queryParams = {
|
this.queryParams = {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user