调整树形

This commit is contained in:
zhonghua.li
2026-04-30 20:23:59 +08:00
parent f10de286cc
commit 3ba39d0f64
3 changed files with 432 additions and 13 deletions

View File

@@ -97,3 +97,21 @@ export function statsUserTradeWithTeamByDateRangeAndTenant(startDate, endDate, t
timeout: 120000
})
}
/** 按用户ID和日期范围分页查询父节点交易明细 */
export function listDailyUserTradeByParentIdOfUserAndDateRange(params) {
return request({
url: '/lbDailyUserTradeReport/list/daily-user-trade/by-parent-id-of-user-and-date-range',
method: 'get',
params
})
}
/** 按用户ID和日期范围分页查询本人交易明细 */
export function listDailyUserTradeByUserIdAndDateRange(params) {
return request({
url: '/lbDailyUserTradeReport/list/daily-user-trade/by-user-id-and-date-range',
method: 'get',
params
})
}

View File

@@ -63,6 +63,7 @@
</template>
</el-table-column>
<el-table-column label="昵称" prop="nickname" min-width="120" />
<el-table-column label="用户ID" prop="userId" min-width="120" />
<el-table-column label="昨日买入金额" prop="yestodayBuyAmt" min-width="130" />
<el-table-column label="当日卖出金额" prop="dailySellAmt" min-width="130" />
<el-table-column label="当日买入金额" prop="dailyBuyAmt" min-width="130" />
@@ -142,12 +143,30 @@
class="dept-stats-tree-table"
style="width: 100%"
>
<el-table-column label="姓名 / 用户ID" prop="name" min-width="240" fixed show-overflow-tooltip>
<el-table-column label="姓名 / 用户ID" prop="name" min-width="360" fixed show-overflow-tooltip>
<template slot-scope="scope">
<span class="dept-stats-name-wrap">
<i :class="['dept-stats-level-icon', deptStatsLevelIconClass(scope.row)]" />
<span class="dept-stats-name-text">{{ scope.row.name || '-' }}</span>
<span class="dept-stats-user-id">{{ scope.row.userId }}</span>
<el-button
type="text"
size="mini"
class="dept-stats-parent-trade-btn"
:loading="myTradeLoadingByUserId[scope.row.userId]"
@click.stop="handleQueryMyTrade(scope.row)"
>
我的交易
</el-button>
<el-button
type="text"
size="mini"
class="dept-stats-parent-trade-btn"
:loading="parentTradeLoadingByUserId[scope.row.userId]"
@click.stop="handleQueryParentTrade(scope.row)"
>
查父交易
</el-button>
</span>
</template>
</el-table-column>
@@ -196,11 +215,6 @@
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="760px" @close="resetForm">
<el-form ref="dataForm" :model="form" :rules="formRules" label-width="120px">
<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="用户ID" prop="userId">
<el-input v-model="form.userId" placeholder="请输入用户ID" />
@@ -326,6 +340,168 @@
<el-button type="success" :loading="exportLoading" @click="submitExport">确定导出</el-button>
</div>
</el-dialog>
<el-dialog
title="我的交易明细"
:visible.sync="myTradeDialogVisible"
width="1200px"
@close="resetMyTradeDialog"
>
<el-form :inline="true" label-width="72px" class="parent-trade-filter">
<el-form-item label="开始日期">
<el-date-picker
v-model="myTradeQuery.startDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="开始日期"
style="width: 160px"
/>
</el-form-item>
<el-form-item label="结束日期">
<el-date-picker
v-model="myTradeQuery.endDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="结束日期"
style="width: 160px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" :loading="myTradeLoading" @click="handleMyTradeSearch">
查询
</el-button>
</el-form-item>
</el-form>
<div class="parent-trade-dialog-tip">
查询用户{{ myTradeQueryUserLabel || '-' }}区间{{ myTradeQueryRangeLabel || '-' }}
</div>
<el-table v-loading="myTradeLoading" :data="myTradeList" border stripe style="width: 100%">
<el-table-column label="报表日期" prop="reportDate" min-width="140">
<template slot-scope="scope">
{{ formatDate(scope.row.reportDate) }}
</template>
</el-table-column>
<el-table-column label="昵称" prop="nickname" min-width="120" />
<el-table-column label="用户ID" prop="userId" min-width="120" />
<el-table-column label="昨日买入金额" prop="yestodayBuyAmt" min-width="120" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.yestodayBuyAmt) }}</template>
</el-table-column>
<el-table-column label="当日卖出金额" prop="dailySellAmt" min-width="120" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.dailySellAmt) }}</template>
</el-table-column>
<el-table-column label="当日买入金额" prop="dailyBuyAmt" min-width="120" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.dailyBuyAmt) }}</template>
</el-table-column>
<el-table-column label="服务费" prop="serviceAmt" min-width="100" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.serviceAmt) }}</template>
</el-table-column>
<el-table-column label="差额" prop="diffAmt" min-width="100" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.diffAmt) }}</template>
</el-table-column>
<el-table-column label="抵扣金额" prop="dikouAmt" min-width="100" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.dikouAmt) }}</template>
</el-table-column>
<el-table-column label="数据类型" prop="dataType" min-width="100" />
<el-table-column label="创建时间" prop="createdAt" min-width="170">
<template slot-scope="scope">
{{ formatDateTime(scope.row.createdAt) }}
</template>
</el-table-column>
</el-table>
<el-pagination
class="parent-trade-pagination"
:current-page="myTradeQuery.current"
:page-size="myTradeQuery.size"
:page-sizes="[10, 20, 50, 100]"
:total="myTradeTotal"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleMyTradeSizeChange"
@current-change="handleMyTradeCurrentChange"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="myTradeDialogVisible = false">关闭</el-button>
</div>
</el-dialog>
<el-dialog
title="引荐人交易明细"
:visible.sync="parentTradeDialogVisible"
width="1200px"
@close="resetParentTradeDialog"
>
<el-form :inline="true" label-width="72px" class="parent-trade-filter">
<el-form-item label="开始日期">
<el-date-picker
v-model="parentTradeQuery.startDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="开始日期"
style="width: 160px"
/>
</el-form-item>
<el-form-item label="结束日期">
<el-date-picker
v-model="parentTradeQuery.endDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="结束日期"
style="width: 160px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" :loading="parentTradeLoading" @click="handleParentTradeSearch">
查询
</el-button>
</el-form-item>
</el-form>
<div class="parent-trade-dialog-tip">
查询用户{{ parentTradeQueryUserLabel || '-' }}区间{{ parentTradeQueryRangeLabel || '-' }}
</div>
<el-table v-loading="parentTradeLoading" :data="parentTradeList" border stripe style="width: 100%">
<el-table-column label="报表日期" prop="reportDate" min-width="140">
<template slot-scope="scope">
{{ formatDate(scope.row.reportDate) }}
</template>
</el-table-column>
<el-table-column label="昵称" prop="nickname" min-width="120" />
<el-table-column label="用户ID" prop="userId" min-width="120" />
<el-table-column label="昨日买入金额" prop="yestodayBuyAmt" min-width="120" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.yestodayBuyAmt) }}</template>
</el-table-column>
<el-table-column label="当日卖出金额" prop="dailySellAmt" min-width="120" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.dailySellAmt) }}</template>
</el-table-column>
<el-table-column label="当日买入金额" prop="dailyBuyAmt" min-width="120" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.dailyBuyAmt) }}</template>
</el-table-column>
<el-table-column label="服务费" prop="serviceAmt" min-width="100" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.serviceAmt) }}</template>
</el-table-column>
<el-table-column label="差额" prop="diffAmt" min-width="100" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.diffAmt) }}</template>
</el-table-column>
<el-table-column label="抵扣金额" prop="dikouAmt" min-width="100" align="right">
<template slot-scope="scope">{{ formatDeptAmt(scope.row.dikouAmt) }}</template>
</el-table-column>
<el-table-column label="数据类型" prop="dataType" min-width="100" />
<el-table-column label="创建时间" prop="createdAt" min-width="170">
<template slot-scope="scope">
{{ formatDateTime(scope.row.createdAt) }}
</template>
</el-table-column>
</el-table>
<el-pagination
class="parent-trade-pagination"
:current-page="parentTradeQuery.current"
:page-size="parentTradeQuery.size"
:page-sizes="[10, 20, 50, 100]"
:total="parentTradeTotal"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleParentTradeSizeChange"
@current-change="handleParentTradeCurrentChange"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="parentTradeDialogVisible = false">关闭</el-button>
</div>
</el-dialog>
</div>
</template>
@@ -337,6 +513,8 @@ import {
deleteLbDailyUserTradeReport,
exportLbDailyUserTradeReportByDateAndTenant,
getLbDailyUserTradeReportList,
listDailyUserTradeByParentIdOfUserAndDateRange,
listDailyUserTradeByUserIdAndDateRange,
listYestodayBuyPositiveAndDailySellZero,
statsUserTradeWithTeamByDateRangeAndTenant,
updateLbDailyUserTradeReport
@@ -443,6 +621,8 @@ export default {
exportLoading: false,
checkUnsoldLoading: false,
deptStatsLoading: false,
parentTradeLoading: false,
myTradeLoading: false,
activeTab: 'list',
deptStatsForm: {
startDate: '',
@@ -450,6 +630,32 @@ export default {
},
deptStatsTreeData: [],
deptStatsSummaryText: '',
parentTradeDialogVisible: false,
myTradeDialogVisible: false,
parentTradeList: [],
myTradeList: [],
parentTradeTotal: 0,
myTradeTotal: 0,
parentTradeQueryUserLabel: '',
myTradeQueryUserLabel: '',
parentTradeQueryRangeLabel: '',
myTradeQueryRangeLabel: '',
parentTradeQuery: {
userId: '',
startDate: '',
endDate: '',
current: 1,
size: 10
},
myTradeQuery: {
userId: '',
startDate: '',
endDate: '',
current: 1,
size: 10
},
parentTradeLoadingByUserId: {},
myTradeLoadingByUserId: {},
list: [],
total: 0,
dialogVisible: false,
@@ -467,7 +673,6 @@ export default {
},
form: {
id: '',
tenantId: '',
userId: '',
nickname: '',
yestodayBuyAmt: '',
@@ -481,7 +686,6 @@ export default {
descContent: ''
},
formRules: {
tenantId: [{ required: true, message: '请输入租户ID', trigger: 'blur' }],
userId: [{ required: true, message: '请输入用户ID', trigger: 'blur' }]
},
deleteByDateForm: {
@@ -656,7 +860,6 @@ export default {
this.isEdit = true
this.form = {
id: row.id,
tenantId: row.tenantId || '',
userId: row.userId || '',
nickname: row.nickname || '',
yestodayBuyAmt: this.toInputString(row.yestodayBuyAmt),
@@ -753,7 +956,7 @@ export default {
this.deptStatsTreeData = buildDeptTradeStatsTree(rows, deptList)
const rangeLabel = `${startDate} ~ ${endDate}`
this.deptStatsSummaryText =
`统计区间:${rangeLabel}租户:${tenantId}${total} 人(树按部门上下级展示,同级按合计差额降序)`
`统计区间:${rangeLabel};共 ${total} 人(树按部门上下级展示,同级按合计差额降序)`
if (!rows.length) {
this.$message.success((statsRes && statsRes.message) || '暂无数据')
}
@@ -765,6 +968,184 @@ export default {
this.deptStatsLoading = false
})
},
handleQueryParentTrade(row) {
const userId = row && row.userId ? String(row.userId).trim() : ''
const startDate = this.deptStatsForm.startDate
const endDate = this.deptStatsForm.endDate
if (!userId) {
this.$message.warning('当前行缺少用户ID无法查询父交易')
return
}
if (!startDate || !endDate) {
this.$message.warning('请先选择统计开始日期和结束日期')
return
}
this.$set(this.parentTradeLoadingByUserId, userId, true)
this.parentTradeQuery = {
userId,
startDate,
endDate,
current: 1,
size: 10
}
this.parentTradeQueryUserLabel = `${row.name || '-'} (${userId})`
this.parentTradeQueryRangeLabel = `${startDate} ~ ${endDate}`
this.parentTradeDialogVisible = true
this.fetchParentTradeList()
.finally(() => {
this.$set(this.parentTradeLoadingByUserId, userId, false)
})
},
handleQueryMyTrade(row) {
const userId = row && row.userId ? String(row.userId).trim() : ''
const startDate = this.deptStatsForm.startDate
const endDate = this.deptStatsForm.endDate
if (!userId) {
this.$message.warning('当前行缺少用户ID无法查询我的交易')
return
}
if (!startDate || !endDate) {
this.$message.warning('请先选择统计开始日期和结束日期')
return
}
this.$set(this.myTradeLoadingByUserId, userId, true)
this.myTradeQuery = {
userId,
startDate,
endDate,
current: 1,
size: 10
}
this.myTradeQueryUserLabel = `${row.name || '-'} (${userId})`
this.myTradeQueryRangeLabel = `${startDate} ~ ${endDate}`
this.myTradeDialogVisible = true
this.fetchMyTradeList()
.finally(() => {
this.$set(this.myTradeLoadingByUserId, userId, false)
})
},
handleParentTradeSearch() {
const { startDate, endDate } = this.parentTradeQuery
if (!startDate || !endDate) {
this.$message.warning('请选择开始日期和结束日期')
return
}
this.parentTradeQuery.current = 1
this.parentTradeQueryRangeLabel = `${startDate} ~ ${endDate}`
this.fetchParentTradeList()
},
handleMyTradeSearch() {
const { startDate, endDate } = this.myTradeQuery
if (!startDate || !endDate) {
this.$message.warning('请选择开始日期和结束日期')
return
}
this.myTradeQuery.current = 1
this.myTradeQueryRangeLabel = `${startDate} ~ ${endDate}`
this.fetchMyTradeList()
},
fetchParentTradeList() {
const { userId, startDate, endDate, current, size } = this.parentTradeQuery
this.parentTradeLoading = true
return listDailyUserTradeByParentIdOfUserAndDateRange({
userId,
startDate,
endDate,
current,
size
})
.then((res) => {
const ok = res && (res.success === true || res.code === 200 || res.code === 20000)
if (!ok) {
this.parentTradeList = []
this.parentTradeTotal = 0
this.$message.error((res && res.message) || '查询父交易失败')
return
}
this.parentTradeList = Array.isArray(res.data) ? res.data : []
this.parentTradeTotal = typeof res.total === 'number' ? res.total : this.parentTradeList.length
})
.catch(() => {
this.parentTradeList = []
this.parentTradeTotal = 0
})
.finally(() => {
this.parentTradeLoading = false
})
},
fetchMyTradeList() {
const { userId, startDate, endDate, current, size } = this.myTradeQuery
this.myTradeLoading = true
return listDailyUserTradeByUserIdAndDateRange({
userId,
startDate,
endDate,
current,
size
})
.then((res) => {
const ok = res && (res.success === true || res.code === 200 || res.code === 20000)
if (!ok) {
this.myTradeList = []
this.myTradeTotal = 0
this.$message.error((res && res.message) || '查询我的交易失败')
return
}
this.myTradeList = Array.isArray(res.data) ? res.data : []
this.myTradeTotal = typeof res.total === 'number' ? res.total : this.myTradeList.length
})
.catch(() => {
this.myTradeList = []
this.myTradeTotal = 0
})
.finally(() => {
this.myTradeLoading = false
})
},
handleParentTradeSizeChange(size) {
this.parentTradeQuery.size = size
this.parentTradeQuery.current = 1
this.fetchParentTradeList()
},
handleParentTradeCurrentChange(current) {
this.parentTradeQuery.current = current
this.fetchParentTradeList()
},
handleMyTradeSizeChange(size) {
this.myTradeQuery.size = size
this.myTradeQuery.current = 1
this.fetchMyTradeList()
},
handleMyTradeCurrentChange(current) {
this.myTradeQuery.current = current
this.fetchMyTradeList()
},
resetParentTradeDialog() {
this.parentTradeList = []
this.parentTradeTotal = 0
this.parentTradeQueryUserLabel = ''
this.parentTradeQueryRangeLabel = ''
this.parentTradeQuery = {
userId: '',
startDate: '',
endDate: '',
current: 1,
size: 10
}
},
resetMyTradeDialog() {
this.myTradeList = []
this.myTradeTotal = 0
this.myTradeQueryUserLabel = ''
this.myTradeQueryRangeLabel = ''
this.myTradeQuery = {
userId: '',
startDate: '',
endDate: '',
current: 1,
size: 10
}
},
formatDeptAmt(val) {
if (val === null || val === undefined || val === '') return '-'
const n = Number(val)
@@ -884,8 +1265,9 @@ export default {
})
},
buildPayload() {
const tenantId = this.getTenantIdFromBusinessHeaders()
const payload = {
tenantId: this.form.tenantId,
tenantId: tenantId || undefined,
userId: this.form.userId,
nickname: this.form.nickname || undefined,
yestodayBuyAmt: this.parseDecimal(this.form.yestodayBuyAmt),
@@ -929,7 +1311,6 @@ export default {
resetFormData() {
this.form = {
id: '',
tenantId: '',
userId: '',
nickname: '',
yestodayBuyAmt: '',
@@ -1060,6 +1441,12 @@ export default {
text-overflow: ellipsis;
}
.dept-stats-parent-trade-btn {
flex: 0 0 auto;
margin-left: 2px;
padding: 0;
}
.dept-stats-tree-table ::v-deep td:first-child .cell {
white-space: nowrap;
}
@@ -1180,5 +1567,20 @@ export default {
font-weight: 400;
}
}
.parent-trade-dialog-tip {
margin-bottom: 12px;
color: #606266;
font-size: 13px;
}
.parent-trade-filter {
margin-bottom: 8px;
}
.parent-trade-pagination {
margin-top: 16px;
text-align: right;
}
}
</style>

View File

@@ -38,7 +38,6 @@
<el-card class="table-container" shadow="never">
<el-table v-loading="loading" :data="list" style="width: 100%">
<el-table-column label="导入日期" prop="reportDate" min-width="120" />
<el-table-column label="租户ID" prop="tenantId" min-width="140" show-overflow-tooltip />
<el-table-column label="用户ID" prop="userId" min-width="140" show-overflow-tooltip />
<el-table-column label="昵称" prop="nickname" min-width="120" />
<el-table-column label="卖出金额" prop="dailySellAmt" min-width="110" />