Files
ruoyi-vue/src/views/system/jdorder/orderList.vue
2025-11-06 16:34:26 +08:00

879 lines
32 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>
<list-layout>
<!-- 搜索区域 -->
<template #search>
<el-form :inline="true" :model="queryParams" label-width="80px">
<el-form-item label="备注">
<el-input v-model="queryParams.remark" placeholder="单据备注" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="分销标记">
<el-input v-model="queryParams.distributionMark" placeholder="分销标记" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="型号">
<el-input v-model="queryParams.modelNumber" placeholder="型号" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="订单号">
<el-input v-model="queryParams.orderId" placeholder="订单号" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="下单人">
<el-input v-model="queryParams.buyer" placeholder="下单人" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="地址">
<el-input v-model="queryParams.address" placeholder="收货地址" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="状态">
<el-input v-model="queryParams.status" placeholder="备注/状态" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="下单时间">
<el-date-picker
v-model="dateRange"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
size="small"
range-separator=""
@change="handleDateRangeChange"
/>
</el-form-item>
<el-form-item label="完成日期">
<el-checkbox v-model="queryParams.hasFinishTime" @change="handleQuery">仅显示已完成订单</el-checkbox>
</el-form-item>
<el-form-item>
<el-button type="primary" size="small" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button size="small" icon="el-icon-refresh" @click="resetQuery">重置</el-button>
<el-button type="warning" size="small" icon="el-icon-download" @click="handleExport" v-hasPermi="['system:jdorder:export']">导出</el-button>
<el-button type="success" size="small" icon="el-icon-setting" @click="showAutoWriteConfig = true" title="配置H-TF订单自动写入腾讯文档">H-TF自动写入配置</el-button>
<el-button type="info" size="small" icon="el-icon-user" @click="handleTestUserInfo" title="测试腾讯文档用户信息接口">测试用户信息</el-button>
</el-form-item>
</el-form>
</template>
<!-- 表格区域 -->
<template #table>
<el-table :data="list" v-loading="loading" border stripe :default-sort="{prop: 'createTime', order: 'descending'}" @sort-change="handleSortChange" style="width: 100%;">
<el-table-column label="ID" prop="id" width="80" />
<el-table-column label="内部单号" prop="remark" width="160" sortable/>
<el-table-column label="订单号" prop="orderId" width="200">
<template slot-scope="scope">
<div>
<span style="margin-right: 8px;">{{ scope.row.orderId }}</span>
<el-button
type="text"
size="mini"
icon="el-icon-copy-document"
@click="copyToClipboard(scope.row.orderId)"
title="复制订单号"
>
复制
</el-button>
</div>
</template>
</el-table-column>
<el-table-column label="第三方单号" prop="thirdPartyOrderNo" width="180">
<template slot-scope="scope">
<div v-if="scope.row.thirdPartyOrderNo">
<span style="margin-right: 8px;">{{ scope.row.thirdPartyOrderNo }}</span>
<el-button
type="text"
size="mini"
icon="el-icon-copy-document"
@click="copyToClipboard(scope.row.thirdPartyOrderNo)"
title="复制第三方单号"
>
复制
</el-button>
</div>
</template>
</el-table-column>
<el-table-column label="标记" prop="distributionMark" width="80"/>
<el-table-column label="型号" prop="modelNumber" width="180"/>
<el-table-column label="地址" prop="address" min-width="320">
<template slot-scope="scope">
<div style="display: flex; align-items: center;">
<span class="ellipsis" style="flex:1; margin-right: 8px;" :title="scope.row.address">{{ scope.row.address }}</span>
<el-button
type="text"
size="mini"
icon="el-icon-copy-document"
@click="copyToClipboard(scope.row.address)"
title="复制地址"
>
复制
</el-button>
</div>
</template>
</el-table-column>
<el-table-column label="付款金额" prop="paymentAmount" width="120">
<template slot-scope="scope">{{ toYuan(scope.row.paymentAmount) }}</template>
</el-table-column>
<el-table-column label="后返金额" prop="rebateAmount" width="120">
<template slot-scope="scope">{{ toYuan(scope.row.rebateAmount) }}</template>
</el-table-column>
<el-table-column label="京粉实际价格" prop="jingfenActualPrice" width="140">
<template slot-scope="scope">{{ toYuan(scope.row.jingfenActualPrice) }}</template>
</el-table-column>
<el-table-column label="下单人" prop="buyer" width="140"/>
<el-table-column label="备注/状态" prop="status" min-width="160"/>
<el-table-column label="参与统计" prop="isCountEnabled" width="100">
<template slot-scope="scope">
<el-switch
v-model="scope.row.isCountEnabled"
:active-value="1"
:inactive-value="0"
@change="handleCountEnabledChange(scope.row)"
active-text=""
inactive-text="">
</el-switch>
</template>
</el-table-column>
<el-table-column label="物流链接" prop="logisticsLink" width="200">
<template slot-scope="scope">
<div v-if="scope.row.logisticsLink">
<a :href="scope.row.logisticsLink" target="_blank" style="margin-right: 8px;">查看物流</a>
<el-button
type="text"
size="mini"
icon="el-icon-copy-document"
@click="copyToClipboard(scope.row.logisticsLink)"
title="复制链接"
>
复制
</el-button>
</div>
</template>
</el-table-column>
<el-table-column label="赔付金额" prop="proPriceAmount" width="140"/>
<el-table-column label="创建时间" prop="createTime" width="160" sortable="custom">
<template slot-scope="scope">{{ parseTime(scope.row.createTime) }}</template>
</el-table-column>
<el-table-column label="完成时间" prop="finishTime" width="160">
<template slot-scope="scope">{{ parseTime(scope.row.finishTime) }}</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="240">
<template slot-scope="scope">
<el-button type="text" size="mini" style="color: #409EFF;" @click="handleSyncLogistics(scope.row)">
同步物流
</el-button>
<el-button
type="text"
size="mini"
style="color: #67C23A;"
@click="handleFetchLogistics(scope.row)"
:disabled="scope.row.distributionMark !== 'F' && scope.row.distributionMark !== 'PDD'"
:title="(scope.row.distributionMark !== 'F' && scope.row.distributionMark !== 'PDD') ? '仅支持F或PDD分销标识' : '获取物流信息'"
>
获取物流
</el-button>
<el-button type="text" size="mini" style="color: #f56c6c;" @click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</template>
<!-- 分页区域 -->
<template #pagination>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</template>
</list-layout>
<!-- 获取物流信息对话框 -->
<el-dialog
title="获取物流信息(调试)"
:visible.sync="fetchLogisticsDialogVisible"
width="800px"
:close-on-click-modal="false"
>
<div v-loading="fetchLogisticsLoading">
<el-alert
v-if="fetchLogisticsResult"
:title="fetchLogisticsResult.success ? '获取成功' : '获取失败'"
:type="fetchLogisticsResult.success ? 'success' : 'error'"
:closable="false"
style="margin-bottom: 20px;"
/>
<el-form label-width="120px" v-if="fetchLogisticsResult">
<el-form-item label="错误信息" v-if="fetchLogisticsResult.error">
<el-alert
:title="fetchLogisticsResult.error"
type="error"
:closable="false"
/>
</el-form-item>
<el-form-item label="订单ID" v-if="fetchLogisticsResult.orderId">
<span>{{ fetchLogisticsResult.orderId }}</span>
</el-form-item>
<el-form-item label="订单号" v-if="fetchLogisticsResult.orderNo">
<span>{{ fetchLogisticsResult.orderNo }}</span>
</el-form-item>
<el-form-item label="分销标识" v-if="fetchLogisticsResult.distributionMark">
<span>{{ fetchLogisticsResult.distributionMark }}</span>
</el-form-item>
<el-form-item label="物流链接" v-if="fetchLogisticsResult.logisticsLink">
<el-input
:value="fetchLogisticsResult.logisticsLink"
readonly
type="textarea"
:rows="2"
/>
</el-form-item>
<el-form-item label="请求URL" v-if="fetchLogisticsResult.requestUrl">
<el-input
:value="fetchLogisticsResult.requestUrl"
readonly
type="textarea"
:rows="2"
/>
</el-form-item>
<el-form-item label="返回数据(原始)" v-if="fetchLogisticsResult.responseRaw || fetchLogisticsResult.responseData">
<el-input
:value="fetchLogisticsResult.responseRaw || JSON.stringify(fetchLogisticsResult.responseData, null, 2)"
readonly
type="textarea"
:rows="10"
style="font-family: monospace; font-size: 12px;"
/>
</el-form-item>
<el-form-item label="返回数据(解析后)" v-if="fetchLogisticsResult.responseData">
<el-input
:value="JSON.stringify(fetchLogisticsResult.responseData, null, 2)"
readonly
type="textarea"
:rows="10"
style="font-family: monospace; font-size: 12px;"
/>
</el-form-item>
</el-form>
<div v-else style="text-align: center; padding: 40px;">
<span style="color: #999;">正在获取物流信息...</span>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="fetchLogisticsDialogVisible = false">关闭</el-button>
<el-button
type="primary"
@click="copyFetchLogisticsResult"
v-if="fetchLogisticsResult"
>
复制结果
</el-button>
</div>
</el-dialog>
<!-- 同步物流对话框 -->
<el-dialog
title="同步物流到腾讯文档"
:visible.sync="syncLogisticsDialogVisible"
width="600px"
:close-on-click-modal="false"
>
<el-form :model="syncLogisticsForm" label-width="140px">
<el-form-item label="文件ID" required>
<el-input
v-model="syncLogisticsForm.fileId"
placeholder="从腾讯文档URL中获取例如Dxxxxxxxxxxxxx"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="工作表ID" required>
<el-input
v-model="syncLogisticsForm.sheetId"
placeholder="从腾讯文档URL中获取例如BB08J2"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="表头行号">
<el-input-number
v-model="syncLogisticsForm.headerRow"
:min="1"
style="width: 100%"
/>
<div style="font-size: 12px; color: #999; margin-top: 4px;">
表头所在行号默认第1行
</div>
</el-form-item>
<el-form-item label="单号列索引(可选)">
<el-input-number
v-model="syncLogisticsForm.orderNoColumn"
:min="0"
style="width: 100%"
placeholder="不填写则自动识别"
/>
<div style="font-size: 12px; color: #999; margin-top: 4px;">
单号列的索引从0开始不填写则自动识别
</div>
</el-form-item>
<el-form-item label="物流链接列索引(可选)">
<el-input-number
v-model="syncLogisticsForm.logisticsLinkColumn"
:min="0"
style="width: 100%"
placeholder="不填写则自动识别"
/>
<div style="font-size: 12px; color: #999; margin-top: 4px;">
物流链接列的索引从0开始不填写则自动识别
</div>
</el-form-item>
<el-form-item label="说明">
<div style="font-size: 12px; color: #666; line-height: 1.6;">
<p>1. 点击"同步物流"如果没有token会自动打开授权页面</p>
<p>2. 完成授权后点击"开始同步"即可自动刷新token并同步数据</p>
<p>3. 文件ID和工作表ID可以从腾讯文档URL中获取</p>
<p>4. 系统会自动从上次处理的最大行数-100开始读取避免重复处理历史数据</p>
<p>5. 配置会自动保存下次使用时无需重新填写</p>
</div>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="syncLogisticsDialogVisible = false">取消</el-button>
<el-button
type="primary"
:loading="syncLogisticsLoading"
@click="handleSyncLogisticsSubmit"
>
开始同步
</el-button>
</div>
</el-dialog>
<!-- H-TF订单自动写入配置 -->
<tencent-doc-auto-write-config v-model="showAutoWriteConfig" @config-updated="handleAutoConfigUpdated" />
</div>
</template>
<script>
import { listJDOrders, updateJDOrder, delJDOrder, fetchLogisticsManually } from '@/api/system/jdorder'
import { fillLogisticsByOrderNo, getTokenStatus, getTencentDocAuthUrl, testUserInfo } from '@/api/jarvis/tendoc'
import ListLayout from '@/components/ListLayout'
import TencentDocAutoWriteConfig from './components/TencentDocAutoWriteConfig'
export default {
name: 'JDOrderList',
components: {
ListLayout,
TencentDocAutoWriteConfig
},
data() {
return {
loading: false,
list: [],
total: 0,
dateRange: [],
queryParams: {
pageNum: 1,
pageSize: 50,
remark: undefined,
distributionMark: undefined,
modelNumber: undefined,
link: undefined,
orderId: undefined,
buyer: undefined,
address: undefined,
status: undefined,
beginTime: null,
endTime: null,
orderBy: 'create_time',
isAsc: 'desc',
hasFinishTime: false
},
// 同步物流对话框
syncLogisticsDialogVisible: false,
syncLogisticsLoading: false,
syncLogisticsForm: {
fileId: '',
sheetId: '',
headerRow: 1,
orderNoColumn: null,
logisticsLinkColumn: null
},
currentOrder: null,
tokenValid: false,
tokenStatusChecked: false,
// H-TF订单自动写入配置
showAutoWriteConfig: false,
// 获取物流信息对话框
fetchLogisticsDialogVisible: false,
fetchLogisticsLoading: false,
fetchLogisticsResult: null
}
},
created() {
// 设置默认日期为今天
this.setDefaultDateRange()
this.getListWithFallback()
// 监听腾讯文档授权回调消息
this.handleOAuthMessage = (event) => {
if (event.data && event.data.type === 'tendoc_oauth_callback') {
if (event.data.success) {
this.$message.success(event.data.message || '授权成功!')
// 刷新token状态
this.checkTokenStatus()
} else {
this.$message.error(event.data.message || '授权失败')
}
}
}
window.addEventListener('message', this.handleOAuthMessage)
},
beforeDestroy() {
// 移除消息监听器
if (this.handleOAuthMessage) {
window.removeEventListener('message', this.handleOAuthMessage)
}
},
methods: {
/** 设置默认日期范围为今天 */
setDefaultDateRange() {
const today = new Date()
const todayStr = this.formatDate(today)
this.dateRange = [todayStr, todayStr]
this.queryParams.beginTime = todayStr
this.queryParams.endTime = todayStr
},
/** 格式化日期为 yyyy-MM-dd 格式 */
formatDate(date) {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
},
getList() {
this.loading = true
listJDOrders(this.queryParams).then(res => {
this.list = (res.rows || res.data || [])
this.total = res.total || 0
this.loading = false
}).catch(() => { this.loading = false })
},
/** 智能查询列表,如果今天数据为空则查询昨天 */
async getListWithFallback() {
this.loading = true
try {
const res = await listJDOrders(this.queryParams)
this.list = (res.rows || res.data || [])
this.total = res.total || 0
// 如果今天的数据为空,且是默认查询(没有手动选择日期),则尝试查询昨天
if (this.list.length === 0 && this.isDefaultQuery()) {
this.$message.info('今天暂无慢单数据,正在查询昨天的数据...')
// 获取昨天的日期
const yesterday = new Date()
yesterday.setDate(yesterday.getDate() - 1)
const yesterdayStr = this.formatDate(yesterday)
// 更新查询参数为昨天
this.queryParams.beginTime = yesterdayStr
this.queryParams.endTime = yesterdayStr
this.dateRange = [yesterdayStr, yesterdayStr]
// 查询昨天的数据
const yesterdayRes = await listJDOrders(this.queryParams)
this.list = (yesterdayRes.rows || yesterdayRes.data || [])
this.total = yesterdayRes.total || 0
if (this.list.length > 0) {
this.$message.success(`已查询到昨天(${yesterdayStr})的慢单数据`)
} else {
this.$message.warning('昨天也没有慢单数据')
}
}
this.loading = false
} catch (error) {
this.loading = false
this.$message.error('查询失败,请稍后重试')
}
},
/** 判断是否为默认查询(今天的数据) */
isDefaultQuery() {
const today = new Date()
const todayStr = this.formatDate(today)
return this.queryParams.beginTime === todayStr && this.queryParams.endTime === todayStr
},
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 50,
remark: undefined,
distributionMark: undefined,
modelNumber: undefined,
link: undefined,
orderId: undefined,
buyer: undefined,
address: undefined,
status: undefined,
beginTime: null,
endTime: null,
orderBy: 'create_time',
isAsc: 'desc',
hasFinishTime: false
}
// 重置排序为默认降序
this.queryParams.orderBy = 'create_time'
this.queryParams.isAsc = 'desc'
// 重置后重新设置默认日期为今天
this.setDefaultDateRange()
this.getListWithFallback()
},
/** 日期范围变化处理 */
handleDateRangeChange(dates) {
if (dates && dates.length === 2) {
this.queryParams.beginTime = dates[0]
this.queryParams.endTime = dates[1]
} else {
this.queryParams.beginTime = null
this.queryParams.endTime = null
}
},
/** 表格排序变化处理 */
handleSortChange(sortInfo) {
if (sortInfo && sortInfo.prop === 'createTime') {
if (sortInfo.order === 'ascending') {
this.queryParams.orderBy = 'create_time'
this.queryParams.isAsc = 'asc'
} else if (sortInfo.order === 'descending') {
this.queryParams.orderBy = 'create_time'
this.queryParams.isAsc = 'desc'
} else {
// 取消排序,恢复默认
this.queryParams.orderBy = 'create_time'
this.queryParams.isAsc = 'desc'
}
// 重新查询数据
this.queryParams.pageNum = 1
this.getList()
}
},
toYuan(n) {
if (n == null || n === '') return ''
const num = Number(n)
if (Number.isNaN(num)) return n
return num.toFixed(2)
},
/** 导出按钮操作 */
handleExport() {
this.download('/system/jdorder/export', this.queryParams, `京东订单数据_${new Date().getTime()}.xlsx`)
},
/** 复制到剪贴板 */
copyToClipboard(text) {
if (navigator.clipboard && window.isSecureContext) {
// 使用现代 Clipboard API
navigator.clipboard.writeText(text).then(() => {
this.$message.success('已复制到剪贴板')
}).catch(() => {
this.fallbackCopyTextToClipboard(text)
})
} else {
// 降级方案
this.fallbackCopyTextToClipboard(text)
}
},
/** 降级复制方案 */
fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea')
textArea.value = text
textArea.style.position = 'fixed'
textArea.style.left = '-999999px'
textArea.style.top = '-999999px'
document.body.appendChild(textArea)
textArea.focus()
textArea.select()
try {
const successful = document.execCommand('copy')
if (successful) {
this.$message.success('已复制到剪贴板')
} else {
this.$message.error('复制失败,请手动复制')
}
} catch (err) {
this.$message.error('复制失败,请手动复制')
}
document.body.removeChild(textArea)
},
/** 处理统计开关变化 */
handleCountEnabledChange(row) {
// 调用后端API更新数据库
updateJDOrder(row).then(() => {
this.$message.success(`订单 ${row.remark} 的统计状态已更新为:${row.isCountEnabled ? '参与统计' : '不参与统计'}`)
}).catch(() => {
this.$message.error('更新失败,请稍后重试')
// 恢复原状态
row.isCountEnabled = row.isCountEnabled ? 0 : 1
})
},
/** 删除单条记录(需输入随机确认码) */
async handleDelete(row) {
const code = String(Math.floor(100000 + Math.random() * 900000))
try {
await this.$prompt(`请输入确认码以删除该订单:${code}`, '删除确认', {
confirmButtonText: '删除',
cancelButtonText: '取消',
inputPlaceholder: '请输入上方确认码',
inputValidator: (value) => {
if (value === code) return true
return '确认码不匹配,请重新输入'
},
inputErrorMessage: '确认码不匹配',
type: 'warning',
dangerouslyUseHTMLString: false
})
} catch (e) {
return
}
this.loading = true
try {
await delJDOrder(row.id)
this.$message.success('删除成功')
this.getList()
} catch (e) {
this.$message.error('删除失败,请稍后重试')
} finally {
this.loading = false
}
},
/** 同步物流到腾讯文档 */
async handleSyncLogistics(row) {
try {
// 先检查配置是否完整
const configRes = await this.$http.get('/jarvis/tencentDoc/config')
if (configRes.code !== 200 || !configRes.data || !configRes.data.isConfigured) {
this.$confirm('检测到尚未完成H-TF自动写入配置是否现在配置', '提示', {
type: 'warning'
}).then(() => {
this.showAutoWriteConfig = true
})
return
}
// 确认同步
await this.$confirm(
`将从配置的腾讯文档中搜索并填充物流链接,是否继续?\n\n` +
`文档: ${configRes.data.fileId}\n` +
`工作表: ${configRes.data.sheetId}\n` +
`数据起始行: ${configRes.data.startRow}`,
'同步物流确认',
{ type: 'info' }
)
this.syncLogisticsLoading = true
// 直接同步,不需要打开对话框
await this.handleSyncLogisticsSubmit()
} catch (e) {
if (e !== 'cancel') {
this.$message.error('操作失败:' + (e.message || '未知错误'))
}
} finally {
this.syncLogisticsLoading = false
}
},
/** 打开授权页面并等待授权完成 */
async openAuthAndWait() {
try {
// 获取授权URL
const authUrlRes = await getTencentDocAuthUrl()
if (authUrlRes.code !== 200 || !authUrlRes.data) {
this.$message.error('获取授权URL失败')
return
}
const authUrl = authUrlRes.data
// 打开授权页面
this.$message.info('正在打开授权页面,请完成授权后继续...')
const width = 600
const height = 700
const left = (window.screen.width - width) / 2
const top = (window.screen.height - height) / 2
const authWindow = window.open(
authUrl,
'腾讯文档授权',
`width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`
)
// 监听窗口关闭事件备用方案如果postMessage失效
const checkWindowClosed = setInterval(() => {
if (authWindow.closed) {
clearInterval(checkWindowClosed)
// 等待1秒后检查token状态作为备用验证
setTimeout(async () => {
try {
const tokenStatusRes = await getTokenStatus()
if (tokenStatusRes.data && tokenStatusRes.data.hasToken) {
// 如果已经通过postMessage收到成功消息这里不再重复提示
} else {
// 如果没有收到postMessage可能是授权失败
this.$message.warning('授权未完成,请重新尝试')
}
} catch (e) {
// 静默处理,避免重复提示
}
}, 1000)
}
}, 1000)
} catch (e) {
this.$message.error('打开授权页面失败: ' + (e.message || '未知错误'))
console.error('打开授权页面失败', e)
}
},
/** 检查后端token状态 */
async checkTokenStatus() {
try {
const res = await getTokenStatus()
if (res.code === 200 && res.data) {
this.tokenValid = res.data.hasToken === true
} else {
this.tokenValid = false
}
} catch (e) {
console.error('检查token状态失败', e)
this.tokenValid = false
} finally {
this.tokenStatusChecked = true
}
},
/** 测试获取用户信息接口 */
async handleTestUserInfo() {
try {
this.$message.info('正在测试用户信息接口...')
const res = await testUserInfo()
if (res.code === 200) {
this.$message.success('测试成功!用户信息:' + JSON.stringify(res.data, null, 2))
// 显示详细信息
this.$alert(
'<pre style="text-align: left; max-height: 400px; overflow: auto;">' +
JSON.stringify(res.data, null, 2) +
'</pre>',
'用户信息测试结果',
{
dangerouslyUseHTMLString: true,
confirmButtonText: '确定',
type: 'success'
}
)
} else {
this.$message.error('测试失败:' + (res.msg || '未知错误'))
}
} catch (e) {
this.$message.error('测试失败:' + (e.message || '未知错误'))
console.error('测试用户信息失败', e)
}
},
/** 同步物流链接 */
async handleSyncLogisticsSubmit() {
try {
// 后端会自动从配置中读取 fileId、sheetId、startRow 等参数
// 前端只需传递空对象即可
const res = await fillLogisticsByOrderNo({})
if (res.code === 200) {
const data = res.data || {}
this.$message.success(
`同步成功!成功填充 ${data.filledCount || 0} 条,跳过 ${data.skippedCount || 0} 条,错误 ${data.errorCount || 0}`
)
} else {
this.$message.error(res.msg || '同步失败')
}
} catch (e) {
this.$message.error('同步失败:' + (e.message || '未知错误'))
console.error('同步物流失败', e)
}
},
/** 手动获取物流信息 */
async handleFetchLogistics(row) {
// 检查分销标识
if (row.distributionMark !== 'F' && row.distributionMark !== 'PDD') {
this.$message.warning('该订单的分销标识不是F或PDD无需处理')
return
}
// 检查物流链接
if (!row.logisticsLink || !row.logisticsLink.trim()) {
this.$message.warning('该订单暂无物流链接')
return
}
this.fetchLogisticsDialogVisible = true
this.fetchLogisticsLoading = true
this.fetchLogisticsResult = null
try {
const res = await fetchLogisticsManually({ orderId: row.id })
if (res.code === 200) {
this.fetchLogisticsResult = {
success: true,
...res.data
}
this.$message.success('获取物流信息成功,数据已记录到日志文件')
} else {
this.fetchLogisticsResult = {
success: false,
error: res.msg || '获取失败'
}
this.$message.error(res.msg || '获取物流信息失败')
}
} catch (e) {
this.fetchLogisticsResult = {
success: false,
error: e.message || '请求异常'
}
this.$message.error('获取物流信息失败: ' + (e.message || '未知错误'))
console.error('获取物流信息失败', e)
} finally {
this.fetchLogisticsLoading = false
}
},
/** 复制获取物流信息的结果 */
copyFetchLogisticsResult() {
if (!this.fetchLogisticsResult) return
const resultText = JSON.stringify(this.fetchLogisticsResult, null, 2)
this.copyToClipboard(resultText)
},
/** H-TF订单自动写入配置更新后的回调 */
handleAutoConfigUpdated() {
this.$message.success('H-TF订单自动写入配置已更新')
}
}
}
</script>
<style scoped>
</style>