统计买家。买入总金额平均每单的金额

This commit is contained in:
zhonghua.li
2026-06-06 22:28:55 +08:00
parent b94f733e47
commit 92d37655b0
2 changed files with 221 additions and 13 deletions

View File

@@ -30,3 +30,19 @@ export function deleteLbBuyerShopping(id) {
method: 'delete'
})
}
export function pullLbBuyerShoppingFromThird(data) {
return request({
url: '/lbBuyerShopping/pull-order-from-third',
method: 'post',
data
})
}
export function generateLbBuyerShoppingStat(data) {
return request({
url: '/lbBuyerShopping/generate-stat',
method: 'post',
data
})
}

View File

@@ -90,29 +90,40 @@
<el-card class="action-container" shadow="never">
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
<el-button
type="success"
icon="el-icon-download"
:loading="pullLoading"
style="margin-left: 12px"
@click="openPullOrderDialog"
>
拉取订单
</el-button>
<el-button
type="warning"
icon="el-icon-data-analysis"
:loading="statLoading"
style="margin-left: 12px"
@click="openStatDialog"
>
数据统计
</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="110" show-overflow-tooltip />
<el-table-column label="订单号" prop="orderSn" min-width="140" 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="买家ID" prop="buyerId" min-width="100" show-overflow-tooltip />
<el-table-column label="订单金额" prop="totalMoney" min-width="100" align="right">
<template slot-scope="scope">
{{ formatAmount(scope.row.totalMoney) }}
</template>
</el-table-column>
<el-table-column label="买家昵称" prop="buyerNickname" min-width="110" show-overflow-tooltip />
<el-table-column label="买家手机" prop="buyerMobile" min-width="120" show-overflow-tooltip />
<el-table-column label="商品ID" prop="merchandiseId" min-width="100" show-overflow-tooltip />
<el-table-column label="卖家ID" prop="sellerId" min-width="100" show-overflow-tooltip />
<el-table-column label="卖家昵称" prop="sellerNickname" min-width="110" show-overflow-tooltip />
<el-table-column label="卖家手机" prop="sellerMobile" min-width="120" show-overflow-tooltip />
<el-table-column label="更新后金额" prop="newTotal" min-width="110" align="right">
<template slot-scope="scope">
{{ formatAmount(scope.row.newTotal) }}
</template>
</el-table-column>
<el-table-column label="卖家昵称" prop="sellerNickname" min-width="110" show-overflow-tooltip />
<el-table-column label="卖家手机" prop="sellerMobile" min-width="120" show-overflow-tooltip />
<el-table-column label="买家昵称" prop="buyerNickname" min-width="110" show-overflow-tooltip />
<el-table-column label="买家手机" prop="buyerMobile" min-width="120" show-overflow-tooltip />
<el-table-column label="创建时间" prop="createdAt" min-width="160">
<template slot-scope="scope">
{{ formatDateTime(scope.row.createdAt) }}
@@ -147,6 +158,54 @@
/>
</el-card>
<el-dialog title="数据统计" :visible.sync="statDialogVisible" width="520px" @close="resetStatForm">
<el-form ref="statFormRef" :model="statForm" :rules="statFormRules" label-width="100px">
<el-form-item label="租户ID">
<el-input :value="tenantIdDisplay" disabled placeholder="未获取到租户ID" />
</el-form-item>
<el-form-item label="买家ID" prop="buyerId">
<el-input v-model="statForm.buyerId" clearable placeholder="请输入买家ID" />
</el-form-item>
<el-form-item label="统计类型" prop="statType">
<el-radio-group v-model="statForm.statType">
<el-radio label="day_stat">按天统计</el-radio>
<el-radio label="sum_data">总和统计</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="statDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="statLoading" @click="handleGenerateStat">确定</el-button>
</div>
</el-dialog>
<el-dialog title="拉取订单" :visible.sync="pullDialogVisible" width="560px" @close="resetPullForm">
<el-form ref="pullFormRef" :model="pullForm" :rules="pullFormRules" label-width="100px">
<el-form-item label="租户ID">
<el-input :value="tenantIdDisplay" disabled placeholder="未获取到租户ID" />
</el-form-item>
<el-form-item label="手机号" prop="mobileListText">
<el-input
v-model="pullForm.mobileListText"
type="textarea"
:rows="6"
placeholder="每行一个手机号,或用逗号、空格分隔"
/>
</el-form-item>
<el-form-item label="密码">
<el-input
v-model="pullForm.password"
clearable
placeholder="选填,未填默认 123456"
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="pullDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="pullLoading" @click="handlePullOrder">确定</el-button>
</div>
</el-dialog>
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="760px" @close="resetForm">
<el-form ref="dataForm" :model="form" :rules="formRules" label-width="110px">
<el-form-item label="订单ID" prop="id">
@@ -262,9 +321,12 @@
import {
addLbBuyerShopping,
deleteLbBuyerShopping,
generateLbBuyerShoppingStat,
getLbBuyerShoppingList,
pullLbBuyerShoppingFromThird,
updateLbBuyerShopping
} from '@/api/lb-buyer-shopping'
import { getBusinessHeaders } from '@/utils/business-headers'
function parseOptionalLong(value) {
if (value === undefined || value === null || value === '') return undefined
@@ -297,6 +359,25 @@ export default {
return {
loading: false,
submitLoading: false,
pullLoading: false,
statLoading: false,
pullDialogVisible: false,
statDialogVisible: false,
pullForm: {
mobileListText: '',
password: ''
},
statForm: {
buyerId: '',
statType: 'day_stat'
},
pullFormRules: {
mobileListText: [{ required: true, message: '请输入手机号', trigger: 'blur' }]
},
statFormRules: {
buyerId: [{ required: true, message: '请输入买家ID', trigger: 'blur' }],
statType: [{ required: true, message: '请选择统计类型', trigger: 'change' }]
},
list: [],
total: 0,
createdAtRange: [],
@@ -325,10 +406,121 @@ export default {
}
}
},
computed: {
tenantIdDisplay() {
return this.getTenantIdFromBusinessHeaders()
}
},
created() {
this.fetchList()
},
methods: {
getTenantIdFromBusinessHeaders() {
const headers = getBusinessHeaders()
const value = headers && headers['X-Tenant-Id']
return value ? String(value).trim() : ''
},
openPullOrderDialog() {
this.pullDialogVisible = true
this.$nextTick(() => {
this.$refs.pullFormRef && this.$refs.pullFormRef.clearValidate()
})
},
openStatDialog() {
this.statForm.buyerId = this.queryParams.buyerId || ''
this.statDialogVisible = true
this.$nextTick(() => {
this.$refs.statFormRef && this.$refs.statFormRef.clearValidate()
})
},
resetStatForm() {
this.statForm = {
buyerId: '',
statType: 'day_stat'
}
this.$refs.statFormRef && this.$refs.statFormRef.resetFields()
},
handleGenerateStat() {
this.$refs.statFormRef.validate((valid) => {
if (!valid) return
const tenantId = this.getTenantIdFromBusinessHeaders()
if (!tenantId) {
this.$message.error('未获取到租户ID请先登录或配置业务请求头中的租户')
return
}
const buyerId = parseOptionalLong(this.statForm.buyerId)
if (buyerId == null) {
this.$message.warning('请输入有效的买家ID')
return
}
this.statLoading = true
generateLbBuyerShoppingStat({
buyerId,
statType: this.statForm.statType
})
.then((res) => {
const isSuccess = res && (res.success === true || res.code === 200 || res.code === 20000)
if (!isSuccess) {
this.$message.error((res && (res.message || res.msg)) || '数据统计失败')
return
}
this.$message.success((res && (res.message || res.msg)) || '数据统计完成')
this.statDialogVisible = false
})
.finally(() => {
this.statLoading = false
})
})
},
resetPullForm() {
this.pullForm = {
mobileListText: '',
password: ''
}
this.$refs.pullFormRef && this.$refs.pullFormRef.resetFields()
},
parseMobileList(text) {
const raw = (text || '').trim()
if (!raw) return []
return Array.from(new Set(
raw.split(/[\s,;]+/)
.map((item) => item.trim())
.filter(Boolean)
))
},
handlePullOrder() {
this.$refs.pullFormRef.validate((valid) => {
if (!valid) return
const tenantId = this.getTenantIdFromBusinessHeaders()
if (!tenantId) {
this.$message.error('未获取到租户ID请先登录或配置业务请求头中的租户')
return
}
const mobiles = this.parseMobileList(this.pullForm.mobileListText)
if (!mobiles.length) {
this.$message.warning('请输入至少一个有效手机号')
return
}
const payload = { tenantId, mobiles }
const password = (this.pullForm.password || '').trim()
if (password) payload.password = password
this.pullLoading = true
pullLbBuyerShoppingFromThird(payload)
.then((res) => {
const isSuccess = res && (res.success === true || res.code === 200 || res.code === 20000)
if (!isSuccess) {
this.$message.error((res && (res.message || res.msg)) || '拉取订单失败')
return
}
this.$message.success((res && res.message) || '拉取订单完成')
this.pullDialogVisible = false
this.fetchList()
})
.finally(() => {
this.pullLoading = false
})
})
},
fetchList() {
this.loading = true
getLbBuyerShoppingList(this.buildListParams())