Compare commits
2 Commits
3f34255d9c
...
b3f19b5ff9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3f19b5ff9 | ||
|
|
5943e69046 |
@@ -4,7 +4,8 @@ export function getLbBuyerShoppingList(params) {
|
||||
return request({
|
||||
url: '/lbBuyerShopping/list',
|
||||
method: 'get',
|
||||
params
|
||||
params,
|
||||
tenantId: params.tenantId
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -38,3 +38,20 @@ export function syncCoupons(params) {
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function monthlyStatistic(params) {
|
||||
return request({
|
||||
url: '/lbUserCoupon/monthlyStatistic',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function exportLbUserCoupon(params) {
|
||||
return request({
|
||||
url: '/lbUserCoupon/export',
|
||||
method: 'get',
|
||||
params,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'normalize.css/normalize.css' // A modern alternative to CSS resets
|
||||
|
||||
import ElementUI from 'element-ui'
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
import locale from 'element-ui/lib/locale/lang/en' // lang i18n
|
||||
import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n
|
||||
|
||||
import '@/styles/index.scss' // global css
|
||||
|
||||
@@ -31,10 +31,7 @@ if (process.env.NODE_ENV === 'production') {
|
||||
mockXHR()
|
||||
}
|
||||
|
||||
// set ElementUI lang to EN
|
||||
Vue.use(ElementUI, { locale })
|
||||
// 如果想要中文版 element-ui,按如下方式声明
|
||||
// Vue.use(ElementUI)
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ const actions = {
|
||||
commit('SET_TOKEN', data.token)
|
||||
setToken(data.token)
|
||||
// 登录接口已返回用户信息时直接写入 store,避免路由守卫再去调 getUserInfoByToken
|
||||
//(该接口若失败或未对接,会清除 token 并退回登录页,表现为「登录成功却进不了系统」)
|
||||
// (该接口若失败或未对接,会清除 token 并退回登录页,表现为「登录成功却进不了系统」)
|
||||
const profile = pickUserDisplayFields(data, username)
|
||||
commit('SET_NAME', profile.userName)
|
||||
commit('SET_AVATAR', profile.avatar || '')
|
||||
|
||||
@@ -251,7 +251,7 @@
|
||||
|
||||
<el-tab-pane label="扩展配置" name="extra">
|
||||
<el-form-item label="扩展 JSON">
|
||||
<el-input v-model="form.extraConfig" type="textarea" :rows="8" placeholder='{"key":"value"}' />
|
||||
<el-input v-model="form.extraConfig" type="textarea" :rows="8" placeholder="{"key":"value"}" />
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
@@ -14,6 +14,15 @@
|
||||
<el-form-item label="上级昵称">
|
||||
<el-input v-model="queryParams.parentNickname" clearable placeholder="请输入上级昵称" style="width: 160px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据类型">
|
||||
<el-select v-model="queryParams.dataType" clearable placeholder="请选择数据类型" style="width: 160px">
|
||||
<el-option label="明细数据" value="data_detail" />
|
||||
<el-option label="月度统计" value="data_month_static" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠金额大于">
|
||||
<el-input-number v-model="queryParams.couponAmount" :min="0" :precision="2" :controls-position="'right'" placeholder="请输入金额" style="width: 160px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠日期">
|
||||
<el-date-picker
|
||||
v-model="couponDateRange"
|
||||
@@ -35,6 +44,8 @@
|
||||
<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-refresh" :loading="syncLoading" style="margin-left: 10px" @click="openSyncDialog">同步优惠券</el-button>
|
||||
<el-button type="info" icon="el-icon-data-line" :loading="statLoading" style="margin-left: 10px" @click="openStatDialog">按月统计</el-button>
|
||||
<el-button type="warning" icon="el-icon-download" :loading="exportLoading" style="margin-left: 10px" @click="handleExport">导出</el-button>
|
||||
</el-card>
|
||||
|
||||
<el-card class="table-container" shadow="never">
|
||||
@@ -44,6 +55,11 @@
|
||||
<el-table-column label="用户昵称" prop="userNickname" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="上级手机号" prop="parentPhone" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="上级昵称" prop="parentNickname" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="数据类型" prop="dataType" min-width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.dataType === 'data_detail' ? '明细数据' : scope.row.dataType === 'data_month_static' ? '月度统计' : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="优惠券金额" prop="couponAmount" min-width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.couponAmount != null ? scope.row.couponAmount : '-' }}
|
||||
@@ -141,6 +157,46 @@
|
||||
<el-button type="primary" :loading="syncLoading" @click="handleSync">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="按月统计" :visible.sync="statDialogVisible" width="600px" @close="resetStatForm">
|
||||
<el-form ref="statFormRef" :model="statForm" label-width="100px">
|
||||
<el-form-item label="租户ID">
|
||||
<el-input :value="tenantIdDisplay" disabled placeholder="未获取到租户ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠日期范围">
|
||||
<el-date-picker
|
||||
v-model="statDateRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="yyyy-MM-dd"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div v-if="statResult && statResult.length" style="margin-top: 20px;">
|
||||
<el-divider content-position="left">统计结果</el-divider>
|
||||
<el-table :data="statResult" style="width: 100%" size="small">
|
||||
<el-table-column prop="month" label="月份" min-width="100" />
|
||||
<el-table-column prop="totalAmount" label="总金额" min-width="120" align="right">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.totalAmount != null ? scope.row.totalAmount.toFixed(2) : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="count" label="数量" min-width="100" align="right" />
|
||||
</el-table>
|
||||
<div v-if="statTotal" style="margin-top: 10px; text-align: right; font-weight: bold;">
|
||||
合计金额: {{ statTotal.toFixed(2) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="statDialogVisible = false">关闭</el-button>
|
||||
<el-button type="primary" :loading="statLoading" @click="handleStat">统计</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -148,7 +204,9 @@
|
||||
import {
|
||||
addLbUserCoupon,
|
||||
deleteLbUserCoupon,
|
||||
exportLbUserCoupon,
|
||||
getLbUserCouponList,
|
||||
monthlyStatistic,
|
||||
syncCoupons,
|
||||
updateLbUserCoupon
|
||||
} from '@/api/lb-user-coupon'
|
||||
@@ -161,6 +219,7 @@ export default {
|
||||
loading: false,
|
||||
submitLoading: false,
|
||||
syncLoading: false,
|
||||
exportLoading: false,
|
||||
list: [],
|
||||
total: 0,
|
||||
couponDateRange: [],
|
||||
@@ -174,13 +233,20 @@ export default {
|
||||
syncFormRules: {
|
||||
recentDays: [{ required: true, message: '请输入最近天数', trigger: 'blur' }]
|
||||
},
|
||||
statDialogVisible: false,
|
||||
statLoading: false,
|
||||
statDateRange: [],
|
||||
statResult: [],
|
||||
statTotal: null,
|
||||
queryParams: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
userPhone: '',
|
||||
userNickname: '',
|
||||
parentPhone: '',
|
||||
parentNickname: ''
|
||||
parentNickname: '',
|
||||
dataType: '',
|
||||
couponAmount: 3044
|
||||
},
|
||||
form: {
|
||||
id: '',
|
||||
@@ -197,14 +263,14 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchList()
|
||||
},
|
||||
computed: {
|
||||
tenantIdDisplay() {
|
||||
return this.getTenantIdFromBusinessHeaders()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
getTenantIdFromBusinessHeaders() {
|
||||
const headers = getBusinessHeaders()
|
||||
@@ -240,7 +306,9 @@ export default {
|
||||
userPhone: this.queryParams.userPhone || undefined,
|
||||
userNickname: this.queryParams.userNickname || undefined,
|
||||
parentPhone: this.queryParams.parentPhone || undefined,
|
||||
parentNickname: this.queryParams.parentNickname || undefined
|
||||
parentNickname: this.queryParams.parentNickname || undefined,
|
||||
dataType: this.queryParams.dataType || undefined,
|
||||
couponAmountMin: this.queryParams.couponAmount
|
||||
}
|
||||
const range = this.couponDateRange || []
|
||||
if (range[0]) params.couponDateStart = range[0]
|
||||
@@ -261,7 +329,9 @@ export default {
|
||||
userPhone: '',
|
||||
userNickname: '',
|
||||
parentPhone: '',
|
||||
parentNickname: ''
|
||||
parentNickname: '',
|
||||
dataType: '',
|
||||
couponAmount: undefined
|
||||
}
|
||||
this.couponDateRange = []
|
||||
this.fetchList()
|
||||
@@ -408,6 +478,89 @@ export default {
|
||||
})
|
||||
})
|
||||
},
|
||||
openStatDialog() {
|
||||
this.statDialogVisible = true
|
||||
},
|
||||
resetStatForm() {
|
||||
this.statDateRange = []
|
||||
this.statResult = []
|
||||
this.statTotal = null
|
||||
},
|
||||
handleStat() {
|
||||
const tenantId = this.getTenantIdFromBusinessHeaders()
|
||||
if (!tenantId) {
|
||||
this.$message.error('未获取到租户ID,请先登录或配置业务请求头中的租户')
|
||||
return
|
||||
}
|
||||
this.statLoading = true
|
||||
const params = { tenantId }
|
||||
const range = this.statDateRange || []
|
||||
if (range[0]) params.couponDateStart = range[0]
|
||||
if (range[1]) params.couponDateEnd = range[1]
|
||||
monthlyStatistic(params)
|
||||
.then((res) => {
|
||||
if (res && (res.success === true || res.code === 200 || res.code === 20000)) {
|
||||
this.statResult = Array.isArray(res.data) ? res.data : []
|
||||
this.statTotal = this.statResult.reduce((sum, item) => {
|
||||
const amount = typeof item.totalAmount === 'number' ? item.totalAmount : 0
|
||||
return sum + amount
|
||||
}, 0)
|
||||
if (!this.statResult.length) {
|
||||
this.$message.info('该时间段内暂无统计数据')
|
||||
}
|
||||
} else {
|
||||
this.$message.error((res && (res.message || res.msg)) || '统计失败')
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.error('统计失败')
|
||||
})
|
||||
.finally(() => {
|
||||
this.statLoading = false
|
||||
})
|
||||
},
|
||||
handleExport() {
|
||||
const tenantId = this.getTenantIdFromBusinessHeaders()
|
||||
if (!tenantId) {
|
||||
this.$message.error('未获取到租户ID,请先登录或配置业务请求头中的租户')
|
||||
return
|
||||
}
|
||||
this.exportLoading = true
|
||||
const params = {
|
||||
tenantId,
|
||||
userPhone: this.queryParams.userPhone || undefined,
|
||||
userNickname: this.queryParams.userNickname || undefined,
|
||||
parentPhone: this.queryParams.parentPhone || undefined,
|
||||
parentNickname: this.queryParams.parentNickname || undefined,
|
||||
dataType: this.queryParams.dataType || undefined,
|
||||
couponAmountMin: this.queryParams.couponAmount
|
||||
}
|
||||
const range = this.couponDateRange || []
|
||||
if (range[0]) params.couponDateStart = range[0]
|
||||
if (range[1]) params.couponDateEnd = range[1]
|
||||
Object.keys(params).forEach((key) => {
|
||||
if (params[key] === undefined || params[key] === '') delete params[key]
|
||||
})
|
||||
exportLbUserCoupon(params)
|
||||
.then((res) => {
|
||||
const blob = new Blob([res], { type: 'application/vnd.ms-excel' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = '用户优惠券.xlsx'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
window.URL.revokeObjectURL(url)
|
||||
this.$message.success('导出成功')
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.error('导出失败')
|
||||
})
|
||||
.finally(() => {
|
||||
this.exportLoading = false
|
||||
})
|
||||
},
|
||||
formatDateTime(dateTime) {
|
||||
if (!dateTime) return '-'
|
||||
const dateStr = String(dateTime).replace('T', ' ')
|
||||
|
||||
@@ -165,8 +165,8 @@
|
||||
type="date"
|
||||
placeholder="可选,格式 yyyy-MM-dd"
|
||||
value-format="yyyy-MM-dd"
|
||||
@change="handleImportDateChange"
|
||||
style="width: 100%"
|
||||
@change="handleImportDateChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
@@ -480,14 +480,14 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchList()
|
||||
},
|
||||
computed: {
|
||||
currentLoginTenantIdDisplay() {
|
||||
return this.getTenantIdFromBusinessHeaders()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
getTenantIdFromBusinessHeaders() {
|
||||
const headers = getBusinessHeaders()
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
<div class="app-container">
|
||||
<el-card class="filter-container" shadow="never">
|
||||
<el-form :model="queryParams" :inline="true" label-width="100px">
|
||||
<el-form-item label="租户ID">
|
||||
<el-select v-model="queryParams.tenantId" clearable placeholder="请选择租户" style="width: 140px">
|
||||
<el-option v-for="item in tenantOptions" :key="item.id" :label="item.tenantName" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="卖家ID">
|
||||
<el-input v-model="queryParams.sellerId" clearable placeholder="卖家ID" style="width: 140px" />
|
||||
</el-form-item>
|
||||
@@ -116,6 +121,7 @@
|
||||
|
||||
<el-card class="table-container" shadow="never">
|
||||
<el-table v-loading="loading" :data="list" style="width: 100%">
|
||||
<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="买家昵称" prop="buyerNickname" min-width="110" show-overflow-tooltip />
|
||||
<el-table-column label="买家手机" prop="buyerMobile" min-width="120" show-overflow-tooltip />
|
||||
@@ -351,6 +357,7 @@ import {
|
||||
updateLbBuyerShopping
|
||||
} from '@/api/lb-buyer-shopping'
|
||||
import { getBusinessHeaders } from '@/utils/business-headers'
|
||||
import { getAllTenantList } from '@/api/tenant'
|
||||
|
||||
function parseOptionalLong(value) {
|
||||
if (value === undefined || value === null || value === '') return undefined
|
||||
@@ -403,6 +410,7 @@ export default {
|
||||
},
|
||||
list: [],
|
||||
total: 0,
|
||||
tenantOptions: [],
|
||||
createdAtRange: [],
|
||||
buyTimeRange: [],
|
||||
confirmTimeRange: [],
|
||||
@@ -412,6 +420,7 @@ export default {
|
||||
queryParams: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
tenantId: '',
|
||||
sellerId: '',
|
||||
merchandiseId: '',
|
||||
buyerId: '',
|
||||
@@ -435,6 +444,7 @@ export default {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchTenantOptions()
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
@@ -443,6 +453,18 @@ export default {
|
||||
const value = headers && headers['X-Tenant-Id']
|
||||
return value ? String(value).trim() : ''
|
||||
},
|
||||
fetchTenantOptions() {
|
||||
getAllTenantList().then((res) => {
|
||||
if (res && (res.code === 20000 || res.code === 200 || res.success === true)) {
|
||||
const data = res.data || []
|
||||
this.tenantOptions = Array.isArray(data) ? data : (data.records || [])
|
||||
} else {
|
||||
this.tenantOptions = []
|
||||
}
|
||||
}).catch(() => {
|
||||
this.tenantOptions = []
|
||||
})
|
||||
},
|
||||
openPullOrderDialog() {
|
||||
this.pullDialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
@@ -570,6 +592,7 @@ export default {
|
||||
const params = {
|
||||
current: this.queryParams.current,
|
||||
size: this.queryParams.size,
|
||||
tenantId: parseOptionalLong(this.queryParams.tenantId),
|
||||
sellerId: parseOptionalLong(this.queryParams.sellerId),
|
||||
merchandiseId: parseOptionalLong(this.queryParams.merchandiseId),
|
||||
buyerId: parseOptionalLong(this.queryParams.buyerId),
|
||||
@@ -603,6 +626,7 @@ export default {
|
||||
this.queryParams = {
|
||||
current: 1,
|
||||
size: 10,
|
||||
tenantId: '',
|
||||
sellerId: '',
|
||||
merchandiseId: '',
|
||||
buyerId: '',
|
||||
|
||||
Reference in New Issue
Block a user