增加订单推送日志、分账日志
Some checks failed
Some checks failed
This commit is contained in:
parent
fac91a81e2
commit
02373f243e
22
src/api/orderQueue.js
Normal file
22
src/api/orderQueue.js
Normal file
@ -0,0 +1,22 @@
|
||||
import axios from 'axios'
|
||||
|
||||
/**
|
||||
* 订单队列 API 基础地址
|
||||
* 开发环境使用内网地址,生产环境可切换为 https://print.buzhiyushu.cn
|
||||
*/
|
||||
//const ORDER_QUEUE_API_BASE = 'http://192.168.101.127:8075'
|
||||
const ORDER_QUEUE_API_BASE = 'https://print.buzhiyushu.cn'
|
||||
|
||||
/**
|
||||
* 获取订单推送列表
|
||||
* @param {Object} params - 查询参数
|
||||
* @param {number} params.pageNum - 页码
|
||||
* @param {number} params.pageSize - 每页条数
|
||||
* @param {string|number} params.createdBy - 创建人ID (about_id)
|
||||
* @param {string} [params.orderSn] - 订单编号(可选搜索条件)
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export const fetchOrderQueueList = async (params) => {
|
||||
const res = await axios.get(`${ORDER_QUEUE_API_BASE}/api/erpGoodsOrderQueue/getList`, { params })
|
||||
return res.data
|
||||
}
|
||||
36
src/api/splitAccountLog.js
Normal file
36
src/api/splitAccountLog.js
Normal file
@ -0,0 +1,36 @@
|
||||
import request from '@/utils/request'
|
||||
import axios from 'axios'
|
||||
|
||||
/**
|
||||
* 获取分账日志汇总列表
|
||||
* @param {Object} params - { page, page_size, about_id }
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export const fetchSplitAccountLogSummary = (params) => {
|
||||
return request.get('/split-account-deduction-log/summary', { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分账日志明细列表(不同服务器,传递完整URL使request忽略baseURL)
|
||||
* @param {string} businessNo - 业务单号
|
||||
* @param {string|number} aboutId - 登录用户 about_id
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export const fetchSplitAccountLogDetail = (businessNo, aboutId) => {
|
||||
return request.get('https://psi.api.buzhiyushu.cn/api/split-account-deduction-log/detail-list', {
|
||||
params: { business_no: businessNo, about_id: aboutId }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询订单详情(印刷系统,独立 axios 实例,不走拦截器)
|
||||
* @param {string} ids - 逗号分隔的 erpOrderId 列表
|
||||
* @returns {Promise<Array>}
|
||||
*/
|
||||
export const fetchOrdersByIds = async (ids) => {
|
||||
const instance = axios.create({ timeout: 15000 })
|
||||
const res = await instance.get('https://print.buzhiyushu.cn/api/erpGoodsOrder/getListByIds', {
|
||||
params: { ids }
|
||||
})
|
||||
return res.data
|
||||
}
|
||||
@ -48,6 +48,7 @@
|
||||
</template>
|
||||
<el-menu-item index="/split-account-config" @click="goTo('/split-account-config')">分账配置</el-menu-item>
|
||||
<el-menu-item index="/split-account-employee" @click="goTo('/split-account-employee')">分账设置</el-menu-item>
|
||||
|
||||
</el-sub-menu>
|
||||
|
||||
<!-- 以下菜单 - 所有登录用户可见 -->
|
||||
@ -173,6 +174,16 @@
|
||||
<span>销毁记录</span>
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-sub-menu index="order-log">
|
||||
<template #title>
|
||||
<el-icon>
|
||||
<List />
|
||||
</el-icon>
|
||||
<span>订单日志</span>
|
||||
</template>
|
||||
<el-menu-item index="/order-push" @click="goTo('/order-push')">订单推送</el-menu-item>
|
||||
<el-menu-item index="/split-account-log" @click="goTo('/split-account-log')">分账日志</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-sub-menu index="sales-order">
|
||||
<template #title>
|
||||
<el-icon>
|
||||
|
||||
@ -196,6 +196,15 @@ const routes = [
|
||||
// 普通用户也可访问
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'order-push',
|
||||
name: 'OrderPush',
|
||||
component: () => import('@/views/orderLog/orderPush.vue'),
|
||||
meta: {
|
||||
title: '订单推送',
|
||||
requiresAuth: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'sales-order',
|
||||
name: 'sales-order',
|
||||
@ -369,6 +378,16 @@ const routes = [
|
||||
requiresAuth: true,
|
||||
requiresAdmin: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'split-account-log',
|
||||
name: 'SplitAccountLog',
|
||||
component: () => import('@/views/splitAccount/SplitAccountLog.vue'),
|
||||
meta: {
|
||||
title: '分账日志',
|
||||
requiresAuth: true,
|
||||
requiresAdmin: true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
320
src/views/orderLog/orderPush.vue
Normal file
320
src/views/orderLog/orderPush.vue
Normal file
@ -0,0 +1,320 @@
|
||||
<template>
|
||||
<el-card class="order-push-manager">
|
||||
<template #header>
|
||||
<div class="card-header">订单推送</div>
|
||||
</template>
|
||||
<div class="filter-bar">
|
||||
<el-input v-model="searchForm.orderSn" placeholder="订单编号" clearable style="width: 220px"
|
||||
@keyup.enter="handleSearch">
|
||||
<template #prefix>
|
||||
<el-icon><Search /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-select v-model="searchForm.shopType" placeholder="店铺类型" clearable style="width: 130px" @change="handleSearch">
|
||||
<el-option label="拼多多" value="1" />
|
||||
<el-option label="孔夫子" value="2" />
|
||||
<el-option label="闲鱼" value="5" />
|
||||
</el-select>
|
||||
<el-input v-model="searchForm.shopErpName" placeholder="店铺名称" clearable style="width: 180px"
|
||||
@keyup.enter="handleSearch" />
|
||||
|
||||
<el-select v-model="searchForm.orderType" placeholder="订单类型" clearable style="width: 140px" @change="handleSearch">
|
||||
<el-option label="订单创建" value="0" />
|
||||
<el-option label="订单完成" value="1" />
|
||||
<el-option label="订单退款" value="2" />
|
||||
</el-select>
|
||||
|
||||
<el-select v-model="searchForm.status" placeholder="推送状态" clearable style="width: 140px" @change="handleSearch">
|
||||
<el-option label="未推送" value="0" />
|
||||
<el-option label="成功" value="1" />
|
||||
<el-option label="失败" value="2" />
|
||||
<el-option label="异常" value="3" />
|
||||
</el-select>
|
||||
<el-date-picker
|
||||
v-model="searchForm.createTimeRange"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="创建开始"
|
||||
end-placeholder="创建结束"
|
||||
value-format="x"
|
||||
style="width: 340px"
|
||||
@change="handleSearch"
|
||||
/>
|
||||
<el-date-picker
|
||||
v-model="searchForm.useTimeRange"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="修改开始"
|
||||
end-placeholder="修改结束"
|
||||
value-format="x"
|
||||
style="width: 340px"
|
||||
@change="handleSearch"
|
||||
/>
|
||||
<el-button type="primary" :icon="Search" @click="handleSearch">搜索</el-button>
|
||||
<el-button :icon="Refresh" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="tableData" v-loading="loading" border stripe style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" v-if="false"/>
|
||||
|
||||
<el-table-column label="商品图片" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-image
|
||||
v-if="parseItemList(row.itemList)?.goodsImgs?.[0]"
|
||||
:src="parseItemList(row.itemList).goodsImgs[0]"
|
||||
style="width: 50px; height: 50px"
|
||||
fit="cover"
|
||||
:preview-src-list="[parseItemList(row.itemList).goodsImgs[0]]"
|
||||
preview-teleported
|
||||
>
|
||||
<template #error>
|
||||
<div class="image-placeholder">📖</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<span v-else class="image-placeholder">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="订单类型" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ orderTypeLabel(row.orderType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="orderSn" label="订单编号" min-width="120" show-overflow-tooltip align="center" />
|
||||
<el-table-column prop="shopErpName" label="店铺名称" width="140" show-overflow-tooltip align="center" />
|
||||
<el-table-column label="店铺类型" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ shopTypeLabel(row.shopType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="商品名称" min-width="160" show-overflow-tooltip align="center">
|
||||
<template #default="{ row }">
|
||||
{{ parseItemList(row.itemList)?.goodsName || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="收货地址" min-width="200" show-overflow-tooltip align="center">
|
||||
<template #default="{ row }">
|
||||
{{ formatAddress(row) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="receiverName" label="联系人" width="100" show-overflow-tooltip align="center" />
|
||||
<el-table-column prop="mobile" label="联系电话" width="130" align="center" />
|
||||
<el-table-column label="创建时间" width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ formatTime(row.queueCreateTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="statusType(row.status)" size="small">
|
||||
{{ statusLabel(row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="修改时间" width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ formatTime(row.useTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="日志" min-width="180" show-overflow-tooltip align="center">
|
||||
<template #default="{ row }">
|
||||
<span style="font-size: 12px; color: #909399">{{ row.msg || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="pagination-wrapper">
|
||||
<el-pagination
|
||||
v-model:current-page="pagination.pageNum"
|
||||
v-model:page-size="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="fetchData"
|
||||
@size-change="fetchData"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { Search, Refresh } from '@element-plus/icons-vue'
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { fetchOrderQueueList } from '@/api/orderQueue'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const loading = ref(false)
|
||||
const tableData = ref([])
|
||||
|
||||
const searchForm = reactive({
|
||||
orderSn: '',
|
||||
status: '',
|
||||
orderType: '',
|
||||
shopErpName: '',
|
||||
shopType: '',
|
||||
createTimeRange: null,
|
||||
useTimeRange: null
|
||||
})
|
||||
|
||||
const pagination = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 状态映射
|
||||
const STATUS_MAP = {
|
||||
'0': { label: '未推送', type: 'info' },
|
||||
'1': { label: '成功', type: 'success' },
|
||||
'2': { label: '失败', type: 'danger' },
|
||||
'3': { label: '异常', type: 'warning' }
|
||||
}
|
||||
|
||||
const statusLabel = (status) => STATUS_MAP[status]?.label || status
|
||||
const statusType = (status) => STATUS_MAP[status]?.type || ''
|
||||
|
||||
// 订单类型映射
|
||||
const ORDER_TYPE_MAP = {
|
||||
'0': '订单创建',
|
||||
'1': '订单完成',
|
||||
'2': '订单退款'
|
||||
}
|
||||
const orderTypeLabel = (type) => ORDER_TYPE_MAP[type] || type
|
||||
|
||||
// 店铺类型映射
|
||||
const SHOP_TYPE_MAP = {
|
||||
'1': '拼多多',
|
||||
'2': '孔夫子',
|
||||
'5': '闲鱼'
|
||||
}
|
||||
const shopTypeLabel = (type) => SHOP_TYPE_MAP[type] || type
|
||||
|
||||
// 解析 itemList JSON 字符串
|
||||
const parseItemList = (itemListStr) => {
|
||||
if (!itemListStr) return null
|
||||
try {
|
||||
return typeof itemListStr === 'string' ? JSON.parse(itemListStr) : itemListStr
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// Unix 时间戳转 年-月-日 时:分:秒
|
||||
const formatTime = (timestamp) => {
|
||||
if (!timestamp) return '-'
|
||||
const numTs = Number(timestamp)
|
||||
if (isNaN(numTs)) return '-'
|
||||
// 秒级时间戳转毫秒
|
||||
const d = new Date(numTs > 1e12 ? numTs : numTs * 1000)
|
||||
const pad = (n) => String(n).padStart(2, '0')
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
|
||||
}
|
||||
|
||||
// 格式化省市区详细地址
|
||||
const formatAddress = (row) => {
|
||||
const parts = [row.province, row.city, row.country, row.town].filter(Boolean)
|
||||
return parts.join(' ') || '-'
|
||||
}
|
||||
|
||||
const fetchData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = {
|
||||
pageNum: pagination.pageNum,
|
||||
pageSize: pagination.pageSize,
|
||||
createdBy: userStore.adminUserInfo?.about_id
|
||||
}
|
||||
if (searchForm.orderSn) {
|
||||
params.orderSn = searchForm.orderSn
|
||||
}
|
||||
if (searchForm.status !== '') {
|
||||
params.status = searchForm.status
|
||||
}
|
||||
if (searchForm.orderType !== '') {
|
||||
params.orderType = searchForm.orderType
|
||||
}
|
||||
if (searchForm.shopErpName) {
|
||||
params.shopErpName = searchForm.shopErpName
|
||||
}
|
||||
if (searchForm.shopType !== '') {
|
||||
params.shopType = searchForm.shopType
|
||||
}
|
||||
if (searchForm.createTimeRange) {
|
||||
params.startCreateTime = Math.floor(searchForm.createTimeRange[0] / 1000)
|
||||
params.endCreateTime = Math.floor(searchForm.createTimeRange[1] / 1000)
|
||||
}
|
||||
if (searchForm.useTimeRange) {
|
||||
params.startUseTime = Math.floor(searchForm.useTimeRange[0] / 1000)
|
||||
params.endUseTime = Math.floor(searchForm.useTimeRange[1] / 1000)
|
||||
}
|
||||
const res = await fetchOrderQueueList(params)
|
||||
if (res.code === '200') {
|
||||
tableData.value = res.list || []
|
||||
pagination.total = res.total || 0
|
||||
}
|
||||
} catch {
|
||||
// 错误已在拦截器中处理
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleSearch = () => {
|
||||
pagination.pageNum = 1
|
||||
fetchData()
|
||||
}
|
||||
|
||||
const resetSearch = () => {
|
||||
searchForm.orderSn = ''
|
||||
searchForm.status = ''
|
||||
searchForm.orderType = ''
|
||||
searchForm.shopErpName = ''
|
||||
searchForm.shopType = ''
|
||||
searchForm.createTimeRange = null
|
||||
searchForm.useTimeRange = null
|
||||
pagination.pageNum = 1
|
||||
fetchData()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.filter-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.pagination-wrapper {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.image-placeholder {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 20px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
514
src/views/splitAccount/SplitAccountLog.vue
Normal file
514
src/views/splitAccount/SplitAccountLog.vue
Normal file
@ -0,0 +1,514 @@
|
||||
<template>
|
||||
<el-card class="split-account-log-manager">
|
||||
<template #header>
|
||||
<div class="card-header">分账日志</div>
|
||||
</template>
|
||||
|
||||
<el-table
|
||||
:data="tableData"
|
||||
v-loading="loading"
|
||||
border
|
||||
stripe
|
||||
style="width: 100%"
|
||||
row-key="business_no"
|
||||
@expand-change="onExpandChange"
|
||||
>
|
||||
<el-table-column type="expand" width="50">
|
||||
<template #default="{ row }">
|
||||
<div
|
||||
v-if="expandedMap[row.business_no]?.loading"
|
||||
style="text-align: center; padding: 20px"
|
||||
>
|
||||
<el-icon class="is-loading"><Loading /></el-icon> 加载中...
|
||||
</div>
|
||||
<el-table
|
||||
v-else-if="expandedMap[row.business_no]?.detailList"
|
||||
:data="expandedMap[row.business_no].detailList"
|
||||
border
|
||||
stripe
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column label="消息" width="300">
|
||||
<template #default="{ row: d }">
|
||||
{{ d.deduction_details?.msg || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="金额来自" width="150" align="center">
|
||||
<template #default="{ row: d }">
|
||||
{{ d.deduction_details?.fromUser || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="手续费" width="100" align="right">
|
||||
<template #default="{ row: d }">
|
||||
{{ fmtYuan(d.deduction_details?.handlingFee) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="扣款前余额" width="140" align="right">
|
||||
<template #default="{ row: d }">
|
||||
{{ d.total_amount }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="扣款金额" width="120" align="right">
|
||||
<template #default="{ row: d }">
|
||||
<span
|
||||
:style="{
|
||||
color: d.deduction_amount < 0 ? '#67c23a' : '#f56c6c',
|
||||
}"
|
||||
>
|
||||
{{ d.deduction_amount >= 0 ? "+" : ""
|
||||
}}{{ d.deduction_amount }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="扣款后余额" width="140" align="right">
|
||||
<template #default="{ row: d }">
|
||||
{{ d.remaining_amount }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="用户" width="120" align="center">
|
||||
<template #default="{ row: d }">
|
||||
{{
|
||||
d.deduction_details?.usePhone === "18904056805"
|
||||
? "0"
|
||||
: d.deduction_details?.usePhone || "-"
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="时间" width="160" align="center">
|
||||
<template #default="{ row: d }">
|
||||
{{ formatTime(d.created_at) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-else style="text-align: center; padding: 20px; color: #999">
|
||||
暂无明细数据
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 订单号 -->
|
||||
<el-table-column
|
||||
label="平台订单号"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ row._order?.orderSn || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="商品ID"
|
||||
width="120"
|
||||
show-overflow-tooltip
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ getItemList(row._order)?.goodsId || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 商品信息 -->
|
||||
<el-table-column label="商品图片" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-image
|
||||
v-if="getItemList(row._order)?.goodsImgs?.[0]"
|
||||
:src="getItemList(row._order)?.goodsImgs[0]"
|
||||
style="width: 50px; height: 50px"
|
||||
fit="cover"
|
||||
:preview-src-list="[getItemList(row._order)?.goodsImgs[0]]"
|
||||
preview-teleported
|
||||
>
|
||||
<template #error><span style="font-size: 18px">📖</span></template>
|
||||
</el-image>
|
||||
<span v-else style="font-size: 18px">📖</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 物流 -->
|
||||
<el-table-column
|
||||
label="快递单号"
|
||||
width="150"
|
||||
show-overflow-tooltip
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ row._order?.trackingNumber || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 状态 -->
|
||||
<el-table-column label="订单状态" width="105" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="orderStatusTag(row._order?.orderStatus)" size="small">
|
||||
{{
|
||||
orderStatusMap[row._order?.orderStatus] ||
|
||||
row._order?.orderStatus ||
|
||||
"-"
|
||||
}}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="售后状态" width="110" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
:type="afterSalesTag(row._order?.afterSalesStatus)"
|
||||
size="small"
|
||||
>
|
||||
{{
|
||||
afterSalesMap[row._order?.afterSalesStatus] ||
|
||||
row._order?.afterSalesStatus ||
|
||||
"-"
|
||||
}}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="店铺类型" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="shopTypeTag(row._order?.shopType)" size="small">
|
||||
{{
|
||||
shopTypeMap[row._order?.shopType] || row._order?.shopType || "-"
|
||||
}}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 店铺信息 -->
|
||||
<el-table-column
|
||||
label="店铺名称"
|
||||
min-width="150"
|
||||
show-overflow-tooltip
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ row._order?.shopErpName || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="商品名称" min-width="200" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ getItemList(row._order)?.goodsName || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" width="60" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ getItemList(row._order)?.goodsCount || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 金额 -->
|
||||
<el-table-column label="订单金额" width="100" align="right">
|
||||
<template #default="{ row }">
|
||||
{{
|
||||
row._order?.orderTotal
|
||||
? (row._order.orderTotal / 100).toFixed(2)
|
||||
: "-"
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 仓库价格(summary 返回) -->
|
||||
<el-table-column label="仓库价格" width="100" align="right">
|
||||
<template #default="{ row }">
|
||||
{{ fmtYuan(row.deduction_details?.product?.sale_price) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 运费(summary 返回) -->
|
||||
<el-table-column label="运费" width="90" align="right">
|
||||
<template #default="{ row }">
|
||||
{{ fmtYuan(row.deduction_details?.product?.cost) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 支付时间 -->
|
||||
<el-table-column label="支付时间" width="150" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ formatTime(row._order?.payAt) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 收货信息 -->
|
||||
<el-table-column label="收货地址" min-width="200" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ formatAddress(row._order) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="联系人" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row._order?.receiverName || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="联系电话" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row._order?.mobile || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 仓库信息(summary 返回) -->
|
||||
<el-table-column label="仓库编码" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ getWh(row)?.warehouse_code || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="仓库名称" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ getWh(row)?.warehouse_name || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库位名称" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ getWh(row)?.location_name || "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="pagination-wrapper">
|
||||
<el-pagination
|
||||
v-model:current-page="pagination.page"
|
||||
v-model:page-size="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="fetchData"
|
||||
@size-change="fetchData"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
import { Loading } from "@element-plus/icons-vue";
|
||||
import { useUserStore } from "@/store/user";
|
||||
import {
|
||||
fetchSplitAccountLogSummary,
|
||||
fetchSplitAccountLogDetail,
|
||||
fetchOrdersByIds,
|
||||
} from "@/api/splitAccountLog";
|
||||
|
||||
console.log("[分账日志] 组件加载");
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const loading = ref(false);
|
||||
const tableData = ref([]);
|
||||
const expandedMap = reactive({});
|
||||
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
const shopTypeMap = { 1: "拼多多", 2: "孔夫子", 5: "闲鱼" };
|
||||
|
||||
const orderStatusMap = {
|
||||
1: "待付款",
|
||||
2: "待发货",
|
||||
3: "已发货待签收",
|
||||
4: "交易成功",
|
||||
5: "已退款",
|
||||
6: "交易关闭",
|
||||
7: "售后处理中",
|
||||
};
|
||||
|
||||
const afterSalesMap = {
|
||||
0: "无售后",
|
||||
2: "买家申请退款,待商家处理",
|
||||
3: "退货退款,待商家处理",
|
||||
4: "商家同意退款,退款中",
|
||||
5: "平台同意退款,退款中",
|
||||
6: "驳回退款,待买家处理",
|
||||
7: "已同意退货退款,待用户发货",
|
||||
8: "平台处理中",
|
||||
9: "平台拒绝退款,退款关闭",
|
||||
10: "退款成功",
|
||||
11: "买家撤销",
|
||||
12: "买家逾期未处理,退款失败",
|
||||
13: "买家逾期,超过有效期",
|
||||
14: "换货补寄待商家处理",
|
||||
15: "换货补寄待用户处理",
|
||||
16: "换货补寄成功",
|
||||
17: "换货补寄失败",
|
||||
18: "换货补寄待用户确认完成",
|
||||
21: "待商家同意维修",
|
||||
22: "待用户确认发货",
|
||||
24: "维修关闭",
|
||||
25: "维修成功",
|
||||
27: "待用户确认收货",
|
||||
31: "已同意拒收退款,待用户拒收",
|
||||
32: "补寄待商家发货",
|
||||
33: "同意召回后退款,待商家召回",
|
||||
600: "申请退货中",
|
||||
601: "拒绝退货中",
|
||||
602: "待买家退货",
|
||||
603: "待卖家确认收货并退款",
|
||||
604: "等待卖家确认退货地址",
|
||||
605: "拒绝退款中",
|
||||
606: "卖家已取消",
|
||||
};
|
||||
|
||||
const shopTypeTag = (type) => {
|
||||
const m = { 1: "danger", 2: "warning", 5: "info" };
|
||||
return m[type] || "";
|
||||
};
|
||||
|
||||
const orderStatusTag = (status) => {
|
||||
const m = {
|
||||
1: "info",
|
||||
2: "warning",
|
||||
3: "primary",
|
||||
4: "success",
|
||||
5: "danger",
|
||||
6: "info",
|
||||
7: "danger",
|
||||
};
|
||||
return m[status] || "";
|
||||
};
|
||||
|
||||
const afterSalesTag = (status) => {
|
||||
if (status === 0 || status === undefined || status === null) return "success";
|
||||
if ([9, 10, 11, 12, 13, 16, 17, 24, 25, 606].includes(status)) return "info";
|
||||
if (
|
||||
[
|
||||
2, 3, 4, 5, 6, 7, 8, 14, 15, 18, 21, 22, 27, 31, 32, 33, 600, 601, 602,
|
||||
603, 604, 605,
|
||||
].includes(status)
|
||||
)
|
||||
return "warning";
|
||||
return "danger";
|
||||
};
|
||||
|
||||
const getItemList = (order) => {
|
||||
if (!order?.itemList) return null;
|
||||
if (typeof order.itemList === "string") {
|
||||
try {
|
||||
return JSON.parse(order.itemList);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return order.itemList;
|
||||
};
|
||||
|
||||
const getWh = (row) => row.deduction_details?.warehouses?.[0] || null
|
||||
|
||||
const formatAddress = (order) => {
|
||||
if (!order) return "-";
|
||||
const parts = [order.province, order.city, order.country, order.town].filter(
|
||||
Boolean
|
||||
);
|
||||
return parts.length ? parts.join(" ") : "-";
|
||||
};
|
||||
|
||||
const fmtYuan = (fen) => {
|
||||
if (fen === null || fen === undefined) return "-";
|
||||
const n = Number(fen);
|
||||
if (isNaN(n)) return "-";
|
||||
return (n / 100).toFixed(2);
|
||||
};
|
||||
|
||||
const getQueryAboutId = () => {
|
||||
const rawId = userStore.adminUserInfo?.about_id;
|
||||
return String(rawId) === "1965254774327533570" ? 0 : rawId;
|
||||
};
|
||||
|
||||
const formatTime = (timestamp) => {
|
||||
if (!timestamp) return "-";
|
||||
const numTs = Number(timestamp);
|
||||
if (isNaN(numTs)) return "-";
|
||||
const d = new Date(numTs > 1e12 ? numTs : numTs * 1000);
|
||||
const pad = (n) => String(n).padStart(2, "0");
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(
|
||||
d.getHours()
|
||||
)}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
||||
};
|
||||
|
||||
const onExpandChange = async (row, expandedRows) => {
|
||||
const isExpanded = expandedRows.some(
|
||||
(r) => r.business_no === row.business_no
|
||||
);
|
||||
if (!isExpanded) return;
|
||||
if (expandedMap[row.business_no]?.detailList) return;
|
||||
|
||||
expandedMap[row.business_no] = { loading: true, detailList: null };
|
||||
|
||||
try {
|
||||
const res = await fetchSplitAccountLogDetail(
|
||||
row.business_no,
|
||||
'0' // 默认先查看全部
|
||||
);
|
||||
if (res.code === 200) {
|
||||
expandedMap[row.business_no].detailList = res.data || [];
|
||||
}
|
||||
} catch {
|
||||
// 拦截器已处理
|
||||
} finally {
|
||||
expandedMap[row.business_no].loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
const fetchData = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const params = {
|
||||
page: pagination.page,
|
||||
page_size: pagination.pageSize,
|
||||
about_id: getQueryAboutId(),
|
||||
};
|
||||
const res = await fetchSplitAccountLogSummary(params);
|
||||
if (res.code === 200) {
|
||||
const list = res.data?.list || [];
|
||||
tableData.value = list;
|
||||
pagination.total = res.data?.total || 0;
|
||||
|
||||
// ⭐ 从 deduction_details 取 erpOrderId
|
||||
const ids = list
|
||||
.map((r) => r.deduction_details?.erpOrderId)
|
||||
.filter(Boolean);
|
||||
if (ids.length > 0) {
|
||||
try {
|
||||
const orderRes = await fetchOrdersByIds(ids.join(","));
|
||||
const orderArr = Array.isArray(orderRes)
|
||||
? orderRes
|
||||
: orderRes?.data || [];
|
||||
const orderMap = {};
|
||||
orderArr.forEach((o) => {
|
||||
orderMap[o.id] = o;
|
||||
});
|
||||
tableData.value = list.map((r) => {
|
||||
const eid = r.deduction_details?.erpOrderId;
|
||||
return { ...r, _order: orderMap[eid] || null };
|
||||
});
|
||||
} catch {
|
||||
// 订单查询失败不影响主列表
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// 拦截器已处理
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.card-header {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.pagination-wrapper {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user