订单同步代码框架

This commit is contained in:
zhonghua.li
2026-05-15 23:36:59 +08:00
parent e980376297
commit 928887b389
4 changed files with 699 additions and 1 deletions

View File

@@ -684,7 +684,12 @@ export default {
handleSubmit() {
this.$refs.dataForm.validate((valid) => {
if (!valid) return
const payload = this.buildPayload()
const tenantId = this.getTenantIdFromBusinessHeaders()
if (!tenantId) {
this.$message.error('未获取到租户ID请先登录或配置业务请求头中的租户')
return
}
const payload = { ...this.buildPayload(), tenantId }
this.submitLoading = true
const req = this.isEdit ? updateLbAssessmentApply(payload) : addLbAssessmentApply(payload)
req.then((res) => {

View File

@@ -0,0 +1,646 @@
<template>
<div class="app-container">
<el-card class="filter-container" shadow="never">
<el-form :model="queryParams" :inline="true" label-width="100px">
<el-form-item label="订单号">
<el-input v-model="queryParams.orderSn" clearable placeholder="订单号" style="width: 180px" />
</el-form-item>
<el-form-item label="买家ID">
<el-input v-model="queryParams.buyerId" clearable placeholder="买家 id" style="width: 140px" />
</el-form-item>
<el-form-item label="卖家ID">
<el-input v-model="queryParams.sellerId" clearable placeholder="卖家 id" style="width: 140px" />
</el-form-item>
<el-form-item label="状态">
<el-input v-model="queryParams.status" clearable placeholder="状态" style="width: 100px" />
</el-form-item>
<el-form-item label="寄卖状态">
<el-select v-model="queryParams.isResell" clearable placeholder="不限" style="width: 140px">
<el-option label="未寄卖" :value="0" />
<el-option label="寄卖" :value="1" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
<el-button icon="el-icon-delete" @click="resetQuery">清空</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="action-container" shadow="never">
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
<el-button type="default" icon="el-icon-refresh" style="margin-left: 10px" @click="openSyncDialog">同步订单</el-button>
</el-card>
<el-card class="table-container" shadow="never">
<el-table v-loading="loading" :data="list" style="width: 100%">
<el-table-column label="订单ID" prop="id" min-width="120" show-overflow-tooltip />
<el-table-column label="订单号" prop="orderSn" min-width="140" show-overflow-tooltip />
<el-table-column label="租户ID" prop="tenantId" min-width="100" show-overflow-tooltip />
<el-table-column label="买家ID" prop="buyerId" min-width="100" show-overflow-tooltip />
<el-table-column label="卖家ID" prop="sellerId" min-width="100" show-overflow-tooltip />
<el-table-column label="商品ID" prop="merchandiseId" min-width="100" show-overflow-tooltip />
<el-table-column label="状态" prop="status" width="72" />
<el-table-column label="总金额" prop="totalMoney" min-width="100" show-overflow-tooltip />
<el-table-column label="收货人" prop="consignee" min-width="90" show-overflow-tooltip />
<el-table-column label="电话" prop="phone" min-width="110" show-overflow-tooltip />
<el-table-column label="下单时间" prop="buyTime" min-width="150" show-overflow-tooltip />
<el-table-column label="支付时间" prop="payTime" min-width="150" show-overflow-tooltip />
<el-table-column label="操作" fixed="right" width="140">
<template slot-scope="scope">
<el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="text" style="color:#F56C6C;" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
:current-page="queryParams.current"
:page-size="queryParams.size"
:page-sizes="[10, 20, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="920px" top="6vh" @close="resetForm">
<el-form ref="dataForm" :model="form" :rules="formRules" label-width="120px" class="order-form">
<el-divider content-position="left">主键与归属</el-divider>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="订单ID" prop="id">
<el-input v-model="form.id" :disabled="isEdit" placeholder="业务主键,新增时需指定" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="旧订单ID" prop="oldId">
<el-input v-model="form.oldId" placeholder="可选" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="租户ID" prop="tenantId">
<el-input v-model="form.tenantId" placeholder="租户ID" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="订单号" prop="orderSn">
<el-input v-model="form.orderSn" placeholder="订单号" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="卖家ID" prop="sellerId">
<el-input v-model="form.sellerId" placeholder="卖家 id" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="买家ID" prop="buyerId">
<el-input v-model="form.buyerId" placeholder="买家 id" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="商品ID" prop="merchandiseId">
<el-input v-model="form.merchandiseId" placeholder="商品 id" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="总金额" prop="totalMoney">
<el-input v-model="form.totalMoney" placeholder="字符串金额" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">状态与展示</el-divider>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="状态" prop="status">
<el-input v-model="form.status" placeholder="整数" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="是否寄卖" prop="isResell">
<el-input v-model="form.isResell" placeholder="0 未寄卖 / 1 寄卖" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="是否展示" prop="isShow">
<el-input v-model="form.isShow" placeholder="0/1 等" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">收货信息</el-divider>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="收货人" prop="consignee">
<el-input v-model="form.consignee" placeholder="收货人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="电话" prop="phone">
<el-input v-model="form.phone" placeholder="电话" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="省" prop="province">
<el-input v-model="form.province" placeholder="省" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="市" prop="city">
<el-input v-model="form.city" placeholder="市" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="区" prop="area">
<el-input v-model="form.area" placeholder="区" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="详细地址" prop="address">
<el-input v-model="form.address" type="textarea" :rows="2" placeholder="详细地址" />
</el-form-item>
<el-divider content-position="left">时间与凭证</el-divider>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="支付时间" prop="payTime">
<el-input v-model="form.payTime" placeholder="原样字符串" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="确认时间" prop="confirmTime">
<el-input v-model="form.confirmTime" placeholder="确认时间" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="下单时间" prop="buyTime">
<el-input v-model="form.buyTime" placeholder="下单时间" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="支付凭证图" prop="payImg">
<el-input v-model="form.payImg" placeholder="URL 或路径" />
</el-form-item>
</el-col>
</el-row>
<el-row v-if="isEdit" :gutter="16">
<el-col :span="12">
<el-form-item label="创建时间">
<el-input v-model="form.createdAt" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="更新时间">
<el-input v-model="form.updatedAt" disabled />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">确定</el-button>
</div>
</el-dialog>
<el-dialog title="同步订单" :visible.sync="syncDialogVisible" width="520px" @close="resetSyncForm">
<el-form ref="syncFormRef" :model="syncForm" :rules="syncFormRules" label-width="110px">
<el-form-item label="购买时间" prop="buyTimeRange">
<el-date-picker
v-model="syncForm.buyTimeRange"
type="datetimerange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']"
style="width: 100%"
clearable
@change="handleSyncBuyTimeRangeChange"
/>
</el-form-item>
<el-form-item label="租户ID">
<el-input :value="currentLoginTenantIdDisplay" disabled placeholder="未获取到租户ID" />
</el-form-item>
<el-form-item label="寄卖状态" prop="isResell">
<el-select v-model="syncForm.isResell" clearable placeholder="不限(不传寄卖条件)" style="width: 100%">
<el-option label="寄卖" :value="1" />
<el-option label="未寄卖" :value="0" />
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="syncDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="syncSubmitLoading" @click="handleSyncSubmit">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
addLbOrderRow,
deleteLbOrderRow,
getLbOrderRowList,
syncLbOrderRowFromThird,
updateLbOrderRow
} from '@/api/lb-order-row'
import { getBusinessHeaders } from '@/utils/business-headers'
function parseOptionalLong(str) {
if (str === '' || str == null) return undefined
const n = Number(String(str).trim())
return Number.isFinite(n) ? n : undefined
}
function parseOptionalInt(str) {
if (str === '' || str == null) return undefined
const n = parseInt(String(str).trim(), 10)
return Number.isFinite(n) ? n : undefined
}
function emptyForm() {
return {
id: '',
oldId: '',
tenantId: '',
sellerId: '',
buyerId: '',
orderSn: '',
totalMoney: '',
payTime: '',
payImg: '',
status: '',
isResell: '',
isShow: '',
consignee: '',
phone: '',
province: '',
city: '',
area: '',
address: '',
merchandiseId: '',
confirmTime: '',
buyTime: '',
createdAt: '',
updatedAt: ''
}
}
export default {
name: 'LbOrderManage',
data() {
const requireId = (rule, value, callback) => {
if (this.isEdit) {
callback()
return
}
if (value === '' || value == null || String(value).trim() === '') {
callback(new Error('新增时必须填写订单 ID'))
return
}
const n = Number(String(value).trim())
if (!Number.isFinite(n)) {
callback(new Error('订单 ID 需为数字'))
return
}
callback()
}
return {
loading: false,
submitLoading: false,
syncDialogVisible: false,
syncSubmitLoading: false,
syncForm: {
buyTimeRange: null,
isResell: undefined
},
syncFormRules: {
buyTimeRange: [
{ required: true, message: '请选择购买时间区间', trigger: 'change' }
]
},
list: [],
total: 0,
dialogVisible: false,
dialogTitle: '',
isEdit: false,
queryParams: {
current: 1,
size: 10,
orderSn: '',
buyerId: '',
sellerId: '',
status: '',
isResell: undefined
},
form: emptyForm(),
formRules: {
id: [{ validator: requireId, trigger: 'blur' }]
}
}
},
created() {
this.fetchList()
},
computed: {
currentLoginTenantIdDisplay() {
return this.getTenantIdFromBusinessHeaders()
}
},
methods: {
getTenantIdFromBusinessHeaders() {
const headers = getBusinessHeaders()
const value = headers && headers['X-Tenant-Id']
return value ? String(value).trim() : ''
},
fetchList() {
this.loading = true
getLbOrderRowList(this.buildListParams())
.then((res) => {
if (res && (res.code === 20000 || res.code === 200 || res.success === true)) {
this.list = Array.isArray(res.data) ? res.data : []
this.total = typeof res.total === 'number'
? res.total
: (res.page && typeof res.page.total === 'number' ? res.page.total : this.list.length)
} else {
this.list = []
this.total = 0
}
})
.catch(() => {
this.list = []
this.total = 0
})
.finally(() => {
this.loading = false
})
},
buildListParams() {
const params = {
current: this.queryParams.current,
size: this.queryParams.size,
orderSn: this.queryParams.orderSn || undefined,
buyerId: parseOptionalLong(this.queryParams.buyerId),
sellerId: parseOptionalLong(this.queryParams.sellerId),
status: parseOptionalInt(this.queryParams.status),
isResell: this.queryParams.isResell === 0 || this.queryParams.isResell === 1
? this.queryParams.isResell
: undefined
}
Object.keys(params).forEach((key) => {
if (params[key] === undefined || params[key] === '') delete params[key]
})
return params
},
handleQuery() {
this.queryParams.current = 1
this.fetchList()
},
resetQuery() {
this.queryParams = {
current: 1,
size: 10,
orderSn: '',
buyerId: '',
sellerId: '',
status: '',
isResell: undefined
}
this.fetchList()
},
handleSizeChange(size) {
this.queryParams.size = size
this.fetchList()
},
handleCurrentChange(current) {
this.queryParams.current = current
this.fetchList()
},
rowToForm(row) {
const pick = (k) => (row[k] !== undefined && row[k] !== null ? String(row[k]) : '')
return {
id: pick('id'),
oldId: pick('oldId'),
tenantId: row.tenantId || '',
sellerId: pick('sellerId'),
buyerId: pick('buyerId'),
orderSn: row.orderSn || '',
totalMoney: row.totalMoney || '',
payTime: row.payTime || '',
payImg: row.payImg || '',
status: pick('status'),
isResell: pick('isResell'),
isShow: pick('isShow'),
consignee: row.consignee || '',
phone: row.phone || '',
province: row.province || '',
city: row.city || '',
area: row.area || '',
address: row.address || '',
merchandiseId: pick('merchandiseId'),
confirmTime: row.confirmTime || '',
buyTime: row.buyTime || '',
createdAt: row.createdAt || '',
updatedAt: row.updatedAt || ''
}
},
handleAdd() {
this.dialogTitle = '新增订单行'
this.isEdit = false
this.form = emptyForm()
this.dialogVisible = true
this.$nextTick(() => {
this.$refs.dataForm && this.$refs.dataForm.clearValidate()
})
},
handleEdit(row) {
this.dialogTitle = '编辑订单行'
this.isEdit = true
this.form = this.rowToForm(row)
this.dialogVisible = true
this.$nextTick(() => {
this.$refs.dataForm && this.$refs.dataForm.clearValidate()
})
},
handleDelete(row) {
this.$confirm('确定删除该订单行吗?(主键为订单 id', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => deleteLbOrderRow(row.id))
.then((res) => {
this.$message.success((res && res.message) || '删除成功')
this.fetchList()
})
.catch(() => {})
},
buildPayload() {
const o = {
id: parseOptionalLong(this.form.id),
oldId: parseOptionalLong(this.form.oldId),
tenantId: this.form.tenantId || undefined,
sellerId: parseOptionalLong(this.form.sellerId),
buyerId: parseOptionalLong(this.form.buyerId),
orderSn: this.form.orderSn || undefined,
totalMoney: this.form.totalMoney || undefined,
payTime: this.form.payTime || undefined,
payImg: this.form.payImg || undefined,
status: parseOptionalInt(this.form.status),
isResell: parseOptionalInt(this.form.isResell),
isShow: parseOptionalInt(this.form.isShow),
consignee: this.form.consignee || undefined,
phone: this.form.phone || undefined,
province: this.form.province || undefined,
city: this.form.city || undefined,
area: this.form.area || undefined,
address: this.form.address || undefined,
merchandiseId: parseOptionalLong(this.form.merchandiseId),
confirmTime: this.form.confirmTime || undefined,
buyTime: this.form.buyTime || undefined
}
if (this.isEdit) {
o.createdAt = this.form.createdAt || undefined
o.updatedAt = this.form.updatedAt || undefined
}
Object.keys(o).forEach((key) => {
if (o[key] === undefined || o[key] === '') delete o[key]
})
return o
},
handleSubmit() {
this.$refs.dataForm.validate((valid) => {
if (!valid) return
const payload = this.buildPayload()
if (!payload.id && payload.id !== 0) {
this.$message.error('订单 ID 无效')
return
}
this.submitLoading = true
const req = this.isEdit ? updateLbOrderRow(payload) : addLbOrderRow(payload)
req.then((res) => {
this.$message.success((res && res.message) || (this.isEdit ? '更新成功' : '新增成功'))
this.dialogVisible = false
this.fetchList()
}).finally(() => {
this.submitLoading = false
})
})
},
resetForm() {
this.$refs.dataForm && this.$refs.dataForm.resetFields()
this.form = emptyForm()
},
normalizeSyncBuyTimeRange(range) {
if (!Array.isArray(range) || range.length !== 2 || !range[0] || !range[1]) {
return range
}
const endDate = String(range[1]).slice(0, 10)
const normalizedEnd = `${endDate} 23:59:59`
if (range[1] === normalizedEnd) {
return range
}
return [range[0], normalizedEnd]
},
handleSyncBuyTimeRangeChange(range) {
const normalized = this.normalizeSyncBuyTimeRange(range)
if (normalized !== range) {
this.syncForm.buyTimeRange = normalized
}
},
openSyncDialog() {
this.syncForm = {
buyTimeRange: null,
isResell: undefined
}
this.syncDialogVisible = true
this.$nextTick(() => {
this.$refs.syncFormRef && this.$refs.syncFormRef.clearValidate()
})
},
resetSyncForm() {
this.syncForm = {
buyTimeRange: null,
isResell: undefined
}
this.$refs.syncFormRef && this.$refs.syncFormRef.resetFields()
},
handleSyncSubmit() {
this.$refs.syncFormRef.validate((valid) => {
if (!valid) return
const range = this.normalizeSyncBuyTimeRange(this.syncForm.buyTimeRange)
if (!Array.isArray(range) || range.length !== 2 || !range[0] || !range[1]) {
this.$message.warning('请选择完整的购买时间区间')
return
}
const tenantId = this.getTenantIdFromBusinessHeaders()
if (!tenantId) {
this.$message.error('未获取到租户ID请先登录或配置业务请求头中的租户')
return
}
const payload = {
buyTimeStart: range[0],
buyTimeEnd: range[1],
tenantId
}
if (this.syncForm.isResell === 0 || this.syncForm.isResell === 1) {
payload.isResell = this.syncForm.isResell
}
this.syncSubmitLoading = true
syncLbOrderRowFromThird(payload)
.then((res) => {
const ok = res && (res.code === 20000 || res.code === 200 || res.success === true)
if (ok) {
this.$message.success((res && res.message) || '同步成功')
this.syncDialogVisible = false
this.fetchList()
} else {
this.$message.error((res && res.message) || '同步失败')
}
})
.catch(() => {})
.finally(() => {
this.syncSubmitLoading = false
})
})
}
}
}
</script>
<style lang="scss" scoped>
.app-container {
.filter-container {
margin-bottom: 20px;
}
.action-container {
margin-bottom: 20px;
}
.table-container {
.el-pagination {
margin-top: 20px;
text-align: right;
}
}
}
.order-form {
max-height: 70vh;
overflow-y: auto;
padding-right: 8px;
}
</style>