Compare commits
No commits in common. "d578280f8230548c8b92de985354728c67ed4ae8" and "24c6936dd0ecf50a173738f6890adb00db85d399" have entirely different histories.
d578280f82
...
24c6936dd0
|
|
@ -32,46 +32,12 @@
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
<el-button
|
|
||||||
type="warning"
|
|
||||||
plain
|
|
||||||
icon="el-icon-download"
|
|
||||||
size="mini"
|
|
||||||
@click="handleExport"
|
|
||||||
v-hasPermi="['ai:data:export']"
|
|
||||||
>导出</el-button>
|
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<p class="summary-line">
|
<el-row :gutter="10" class="mb8">
|
||||||
<template v-if="summaryState.mode === 'loading'">
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
<span> </span>
|
</el-row>
|
||||||
<span class="summary-prefix">汇总:</span><span class="summary-muted">加载中…</span>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="summaryState.mode === 'empty'">
|
|
||||||
<span> </span>
|
|
||||||
<span class="summary-prefix">汇总:</span><span class="summary-muted">—</span>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<span> </span>
|
|
||||||
<span class="summary-prefix">汇总:</span>
|
|
||||||
<span class="summary-label">总计</span>
|
|
||||||
<span class="summary-num">{{ summaryState.totalStr }}</span>
|
|
||||||
<span class="summary-label">条记录,实际充值积分</span>
|
|
||||||
<span class="summary-num">{{ summaryState.recharge }}</span>
|
|
||||||
<span class="summary-unit">分</span>
|
|
||||||
<span class="summary-label">,消耗积分</span>
|
|
||||||
<span class="summary-num">{{ summaryState.score }}</span>
|
|
||||||
<span class="summary-unit">分</span>
|
|
||||||
<span class="summary-label">,实际订单数量(成功)</span>
|
|
||||||
<span class="summary-num">{{ summaryState.orders }}</span>
|
|
||||||
<span class="summary-unit">单</span>
|
|
||||||
<span class="summary-label">,三方消耗tokens数量</span>
|
|
||||||
<span class="summary-num">{{ summaryState.tokens }}</span>
|
|
||||||
<span class="summary-unit">。</span>
|
|
||||||
</template>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="dataList">
|
<el-table v-loading="loading" :data="dataList">
|
||||||
<el-table-column label="日期" align="center" prop="dateKey" min-width="110" />
|
<el-table-column label="日期" align="center" prop="dateKey" min-width="110" />
|
||||||
|
|
@ -124,7 +90,6 @@ export default {
|
||||||
showSearch: true,
|
showSearch: true,
|
||||||
total: 0,
|
total: 0,
|
||||||
dataList: [],
|
dataList: [],
|
||||||
aggregate: null,
|
|
||||||
deptOptions: [],
|
deptOptions: [],
|
||||||
dateRange: [],
|
dateRange: [],
|
||||||
queryParams: {
|
queryParams: {
|
||||||
|
|
@ -142,30 +107,9 @@ export default {
|
||||||
this.syncDateRangeToQuery()
|
this.syncDateRangeToQuery()
|
||||||
this.getList()
|
this.getList()
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
summaryState() {
|
|
||||||
if (this.loading) {
|
|
||||||
return { mode: "loading" }
|
|
||||||
}
|
|
||||||
const a = this.aggregate
|
|
||||||
if (!a) {
|
|
||||||
return { mode: "empty" }
|
|
||||||
}
|
|
||||||
const fmt = (v) => this.formatWesternNumberValue(v)
|
|
||||||
const n = a.totalRows != null ? Number(a.totalRows) : 0
|
|
||||||
const totalStr = Number.isNaN(n) ? "0" : n.toLocaleString("en-US")
|
|
||||||
return {
|
|
||||||
mode: "ok",
|
|
||||||
totalStr,
|
|
||||||
recharge: fmt(a.sumRechargeScore),
|
|
||||||
score: fmt(a.sumScore),
|
|
||||||
orders: fmt(a.sumOrderCount),
|
|
||||||
tokens: fmt(a.sumUseTokens)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
formatWesternNumberValue(cellValue) {
|
/** null/空 显示 0;数字按 en-US 千分位(如 99,999,999) */
|
||||||
|
formatWesternNumber(row, column, cellValue) {
|
||||||
if (cellValue === null || cellValue === undefined || cellValue === "") {
|
if (cellValue === null || cellValue === undefined || cellValue === "") {
|
||||||
return (0).toLocaleString("en-US")
|
return (0).toLocaleString("en-US")
|
||||||
}
|
}
|
||||||
|
|
@ -175,10 +119,6 @@ export default {
|
||||||
}
|
}
|
||||||
return n.toLocaleString("en-US")
|
return n.toLocaleString("en-US")
|
||||||
},
|
},
|
||||||
/** null/空 显示 0;数字按 en-US 千分位(如 99,999,999) */
|
|
||||||
formatWesternNumber(row, column, cellValue) {
|
|
||||||
return this.formatWesternNumberValue(cellValue)
|
|
||||||
},
|
|
||||||
buildLastMonthDateRange() {
|
buildLastMonthDateRange() {
|
||||||
const end = new Date()
|
const end = new Date()
|
||||||
const start = new Date(end.getTime())
|
const start = new Date(end.getTime())
|
||||||
|
|
@ -220,10 +160,8 @@ export default {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
listData(this.queryParams)
|
listData(this.queryParams)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.dataList = response.rows || []
|
this.dataList = response.rows
|
||||||
this.total = response.total != null ? response.total : 0
|
this.total = response.total
|
||||||
this.aggregate =
|
|
||||||
response.param && response.param.aggregate != null ? response.param.aggregate : null
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
|
@ -239,57 +177,7 @@ export default {
|
||||||
this.queryParams.pageNum = 1
|
this.queryParams.pageNum = 1
|
||||||
this.syncDateRangeToQuery()
|
this.syncDateRangeToQuery()
|
||||||
this.getList()
|
this.getList()
|
||||||
},
|
|
||||||
handleExport() {
|
|
||||||
this.syncDateRangeToQuery()
|
|
||||||
this.download(
|
|
||||||
"ai/data/export",
|
|
||||||
{
|
|
||||||
startDate: this.queryParams.startDate,
|
|
||||||
endDate: this.queryParams.endDate,
|
|
||||||
deptId: this.queryParams.deptId
|
|
||||||
},
|
|
||||||
`team_consume_${new Date().getTime()}.xlsx`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.summary-line {
|
|
||||||
color: #606266;
|
|
||||||
font-size: 13px;
|
|
||||||
margin: 0 0 12px 0;
|
|
||||||
padding-left: 8px;
|
|
||||||
line-height: 1.75;
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-prefix {
|
|
||||||
color: #909399;
|
|
||||||
font-weight: 600;
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-muted {
|
|
||||||
color: #c0c4cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-label {
|
|
||||||
color: #606266;
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-unit {
|
|
||||||
color: #909399;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-left: 1px;
|
|
||||||
margin-right: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-num {
|
|
||||||
color: #409eff;
|
|
||||||
font-weight: 600;
|
|
||||||
font-variant-numeric: tabular-nums;
|
|
||||||
margin: 0 2px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,7 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="类型" prop="orderType">
|
<el-form-item label="类型" prop="orderType">
|
||||||
<el-select v-model="queryParams.orderType" placeholder="全部" clearable style="width: 110px">
|
<el-select v-model="queryParams.orderType" placeholder="全部" clearable style="width: 110px">
|
||||||
<el-option
|
<el-option v-for="item in orderTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
v-for="item in orderTypeQueryOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="创建时间">
|
<el-form-item label="创建时间">
|
||||||
|
|
@ -156,10 +151,6 @@ export default {
|
||||||
amount: [{ required: true, message: "请填写积分", trigger: "blur" }],
|
amount: [{ required: true, message: "请填写积分", trigger: "blur" }],
|
||||||
status: [{ required: true, message: "请选择状态", trigger: "change" }]
|
status: [{ required: true, message: "请选择状态", trigger: "change" }]
|
||||||
},
|
},
|
||||||
orderTypeQueryOptions: [
|
|
||||||
{ label: "充值", value: 0 },
|
|
||||||
{ label: "退款", value: 1 }
|
|
||||||
],
|
|
||||||
orderTypeOptions: [
|
orderTypeOptions: [
|
||||||
{ label: "充值", value: 0 },
|
{ label: "充值", value: 0 },
|
||||||
{ label: "退款", value: 1 },
|
{ label: "退款", value: 1 },
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,19 @@
|
||||||
v-show="showSearch"
|
v-show="showSearch"
|
||||||
label-width="68px"
|
label-width="68px"
|
||||||
>
|
>
|
||||||
|
<el-form-item label="主键ID" prop="id">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.id"
|
||||||
|
placeholder="请输入主键ID"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="用户ID" prop="userId">
|
<el-form-item label="用户ID" prop="userId">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.userId"
|
v-model="queryParams.userId"
|
||||||
placeholder="请输入用户ID"
|
placeholder="请输入用户ID"
|
||||||
clearable
|
clearable
|
||||||
style="width: 150px"
|
|
||||||
@keyup.enter.native="handleQuery"
|
@keyup.enter.native="handleQuery"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -22,12 +29,19 @@
|
||||||
v-model="queryParams.username"
|
v-model="queryParams.username"
|
||||||
placeholder="请输入用户账号"
|
placeholder="请输入用户账号"
|
||||||
clearable
|
clearable
|
||||||
style="width: 150px"
|
|
||||||
@keyup.enter.native="handleQuery"
|
@keyup.enter.native="handleQuery"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态" prop="status" label-width="40px">
|
<el-form-item label="上级ID" prop="superisuperiorUuidorId">
|
||||||
<el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 80px">
|
<el-input
|
||||||
|
v-model="queryParams.superiorUuid"
|
||||||
|
placeholder="请输入上级ID"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="status">
|
||||||
|
<el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 240px">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="dict in dict.type.sys_normal_disable"
|
v-for="dict in dict.type.sys_normal_disable"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
|
|
@ -36,7 +50,7 @@
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="归属团队" prop="deptId">
|
<el-form-item label="归属部门" prop="deptId">
|
||||||
<treeselect
|
<treeselect
|
||||||
v-model="queryParams.deptId"
|
v-model="queryParams.deptId"
|
||||||
:options="deptOptions"
|
:options="deptOptions"
|
||||||
|
|
@ -49,6 +63,11 @@
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
|
|
@ -57,6 +76,8 @@
|
||||||
@click="handleAdd"
|
@click="handleAdd"
|
||||||
v-hasPermi="['ai:user:add']"
|
v-hasPermi="['ai:user:add']"
|
||||||
>新增</el-button>
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
type="danger"
|
type="danger"
|
||||||
plain
|
plain
|
||||||
|
|
@ -66,6 +87,8 @@
|
||||||
@click="handleDelete()"
|
@click="handleDelete()"
|
||||||
v-hasPermi="['ai:user:remove']"
|
v-hasPermi="['ai:user:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
type="warning"
|
type="warning"
|
||||||
plain
|
plain
|
||||||
|
|
@ -74,13 +97,13 @@
|
||||||
@click="handleExport"
|
@click="handleExport"
|
||||||
v-hasPermi="['ai:user:export']"
|
v-hasPermi="['ai:user:export']"
|
||||||
>导出</el-button>
|
>导出</el-button>
|
||||||
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-form-item>
|
</el-row>
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="50" align="center" />
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
<el-table-column label="主键ID" align="center" prop="id" width="60" />
|
<el-table-column label="主键ID" align="center" prop="id" width="90" />
|
||||||
<el-table-column label="用户ID" align="center" prop="userId" />
|
<el-table-column label="用户ID" align="center" prop="userId" />
|
||||||
<el-table-column label="用户账号" align="center" prop="username" />
|
<el-table-column label="用户账号" align="center" prop="username" />
|
||||||
<!--
|
<!--
|
||||||
|
|
@ -88,7 +111,7 @@
|
||||||
<el-table-column label="上级账号" align="center" prop="superiorName" />
|
<el-table-column label="上级账号" align="center" prop="superiorName" />
|
||||||
-->
|
-->
|
||||||
<el-table-column label="用户昵称" align="center" prop="nickname" />
|
<el-table-column label="用户昵称" align="center" prop="nickname" />
|
||||||
<el-table-column label="归属团队" align="center" prop="deptName" width="120" show-overflow-tooltip />
|
<el-table-column label="归属部门" align="center" prop="deptName" width="120" show-overflow-tooltip />
|
||||||
<!--
|
<!--
|
||||||
<el-table-column label="邮箱" align="center" prop="email" />
|
<el-table-column label="邮箱" align="center" prop="email" />
|
||||||
<el-table-column label="性别" align="center" prop="gender">
|
<el-table-column label="性别" align="center" prop="gender">
|
||||||
|
|
@ -98,7 +121,7 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
-->
|
-->
|
||||||
<el-table-column label="状态" align="center" key="status" width="60">
|
<el-table-column label="状态" align="center" key="status">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-switch
|
<el-switch
|
||||||
v-model="scope.row.status"
|
v-model="scope.row.status"
|
||||||
|
|
@ -113,10 +136,11 @@
|
||||||
-->
|
-->
|
||||||
<el-table-column label="登录时间" align="center" prop="loginTime" width="150">
|
<el-table-column label="登录时间" align="center" prop="loginTime" width="150">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ parseTime(scope.row.loginTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
<span>{{ parseTime(scope.row.loginTime, '{y}-{m}-{d}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="剩余积分" align="center" prop="balance" />
|
<el-table-column label="剩余积分" align="center" prop="balance" />
|
||||||
|
<el-table-column label="source" align="center" prop="source" />
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="460">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="460">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button
|
||||||
|
|
@ -125,7 +149,7 @@
|
||||||
icon="el-icon-office-building"
|
icon="el-icon-office-building"
|
||||||
@click="handleOpenAssignDept(scope.row)"
|
@click="handleOpenAssignDept(scope.row)"
|
||||||
v-hasPermi="['ai:user:edit']"
|
v-hasPermi="['ai:user:edit']"
|
||||||
>分配团队</el-button>
|
>分配部门</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -245,15 +269,15 @@
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 分配团队 -->
|
<!-- 分配部门 -->
|
||||||
<el-dialog title="分配归属团队" :visible.sync="assignDeptOpen" width="480px" append-to-body @close="cancelAssignDept">
|
<el-dialog title="分配归属部门" :visible.sync="assignDeptOpen" width="480px" append-to-body @close="cancelAssignDept">
|
||||||
<el-form label-width="88px">
|
<el-form label-width="88px">
|
||||||
<el-form-item label="归属团队">
|
<el-form-item label="归属部门">
|
||||||
<treeselect
|
<treeselect
|
||||||
v-model="assignForm.deptId"
|
v-model="assignForm.deptId"
|
||||||
:options="deptOptions"
|
:options="deptOptions"
|
||||||
:normalizer="deptNormalizer"
|
:normalizer="deptNormalizer"
|
||||||
placeholder="不选则不归属任何团队"
|
placeholder="不选则不归属任何部门"
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -273,9 +297,6 @@
|
||||||
@close="cancelDeptScore"
|
@close="cancelDeptScore"
|
||||||
>
|
>
|
||||||
<el-form ref="deptScoreFormRef" :model="deptScoreForm" :rules="deptScoreRules" label-width="88px">
|
<el-form ref="deptScoreFormRef" :model="deptScoreForm" :rules="deptScoreRules" label-width="88px">
|
||||||
<el-form-item label="所属团队">
|
|
||||||
<span>{{ deptScoreForm.deptName || "—" }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="用户账号">
|
<el-form-item label="用户账号">
|
||||||
<span>{{ deptScoreForm.username }}</span>
|
<span>{{ deptScoreForm.username }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -371,7 +392,6 @@ export default {
|
||||||
deptScoreForm: {
|
deptScoreForm: {
|
||||||
userId: null,
|
userId: null,
|
||||||
username: "",
|
username: "",
|
||||||
deptName: "",
|
|
||||||
amount: undefined,
|
amount: undefined,
|
||||||
remark: ""
|
remark: ""
|
||||||
},
|
},
|
||||||
|
|
@ -506,14 +526,13 @@ export default {
|
||||||
},
|
},
|
||||||
openDeptScoreDialog(row, mode) {
|
openDeptScoreDialog(row, mode) {
|
||||||
if (!row.deptId) {
|
if (!row.deptId) {
|
||||||
this.$modal.msgWarning("请先分配归属团队后再操作积分");
|
this.$modal.msgWarning("请先分配归属部门后再操作积分");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.deptScoreMode = mode;
|
this.deptScoreMode = mode;
|
||||||
this.deptScoreForm = {
|
this.deptScoreForm = {
|
||||||
userId: row.id,
|
userId: row.id,
|
||||||
username: row.username || row.userId || "",
|
username: row.username || row.userId || "",
|
||||||
deptName: row.deptName || "",
|
|
||||||
amount: undefined,
|
amount: undefined,
|
||||||
remark: ""
|
remark: ""
|
||||||
};
|
};
|
||||||
|
|
@ -550,7 +569,7 @@ export default {
|
||||||
},
|
},
|
||||||
cancelDeptScore() {
|
cancelDeptScore() {
|
||||||
this.deptScoreOpen = false;
|
this.deptScoreOpen = false;
|
||||||
this.deptScoreForm = { userId: null, username: "", deptName: "", amount: undefined, remark: "" };
|
this.deptScoreForm = { userId: null, username: "", amount: undefined, remark: "" };
|
||||||
},
|
},
|
||||||
// updateBalance(row) {
|
// updateBalance(row) {
|
||||||
// this.reset();
|
// this.reset();
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@
|
||||||
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true" label-width="88px">
|
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true" label-width="88px">
|
||||||
<el-form-item label="类型" prop="orderType">
|
<el-form-item label="类型" prop="orderType">
|
||||||
<el-select v-model="queryParams.orderType" clearable placeholder="全部">
|
<el-select v-model="queryParams.orderType" clearable placeholder="全部">
|
||||||
<el-option label="充值" :value="0" />
|
<el-option label="充值" :value="0" /><el-option label="退款" :value="1" /><el-option label="手动修改" :value="2" />
|
||||||
<el-option label="退款" :value="1" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="订单编号" prop="orderNum">
|
<el-form-item label="订单编号" prop="orderNum">
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
<el-card shadow="hover"><div class="metric-title">团队名称</div><div class="metric-val">{{ info.deptName }}</div></el-card>
|
<el-card shadow="hover"><div class="metric-title">团队名称</div><div class="metric-val">{{ info.deptName }}</div></el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-card shadow="hover"><div class="metric-title">团队剩余积分</div><div class="metric-val">{{ info.balance }}</div></el-card>
|
<el-card shadow="hover"><div class="metric-title">积分余额(部门)</div><div class="metric-val">{{ info.balance }}</div></el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="16" style="margin-top:16px">
|
<el-row :gutter="16" style="margin-top:16px">
|
||||||
|
|
|
||||||
|
|
@ -109,9 +109,6 @@
|
||||||
@close="cancelDeptScore"
|
@close="cancelDeptScore"
|
||||||
>
|
>
|
||||||
<el-form ref="deptScoreFormRef" :model="deptScoreForm" :rules="deptScoreRules" label-width="88px">
|
<el-form ref="deptScoreFormRef" :model="deptScoreForm" :rules="deptScoreRules" label-width="88px">
|
||||||
<el-form-item label="所属团队">
|
|
||||||
<span>{{ deptScoreForm.deptName || '—' }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="用户账号">
|
<el-form-item label="用户账号">
|
||||||
<span>{{ deptScoreForm.username }}</span>
|
<span>{{ deptScoreForm.username }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -172,7 +169,6 @@ export default {
|
||||||
deptScoreForm: {
|
deptScoreForm: {
|
||||||
userId: null,
|
userId: null,
|
||||||
username: '',
|
username: '',
|
||||||
deptName: '',
|
|
||||||
amount: undefined,
|
amount: undefined,
|
||||||
remark: ''
|
remark: ''
|
||||||
},
|
},
|
||||||
|
|
@ -274,7 +270,6 @@ export default {
|
||||||
this.deptScoreForm = {
|
this.deptScoreForm = {
|
||||||
userId: row.id,
|
userId: row.id,
|
||||||
username: row.username || row.userId || '',
|
username: row.username || row.userId || '',
|
||||||
deptName: row.deptName || '',
|
|
||||||
amount: undefined,
|
amount: undefined,
|
||||||
remark: ''
|
remark: ''
|
||||||
}
|
}
|
||||||
|
|
@ -311,7 +306,7 @@ export default {
|
||||||
},
|
},
|
||||||
cancelDeptScore() {
|
cancelDeptScore() {
|
||||||
this.deptScoreOpen = false
|
this.deptScoreOpen = false
|
||||||
this.deptScoreForm = { userId: null, username: '', deptName: '', amount: undefined, remark: '' }
|
this.deptScoreForm = { userId: null, username: '', amount: undefined, remark: '' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
package com.ruoyi.ai.controller;
|
package com.ruoyi.ai.controller;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import com.ruoyi.ai.domain.request.GroupReportDataRequest;
|
import com.ruoyi.ai.domain.request.GroupReportDataRequest;
|
||||||
import com.ruoyi.ai.domain.vo.TeamDailyConsumeAggregateVO;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
@ -15,10 +12,10 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.constant.HttpStatus;
|
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
|
@ -47,17 +44,8 @@ public class AiVideoReportDataController extends BaseController {
|
||||||
@PreAuthorize("@ss.hasPermi('ai:data:list')")
|
@PreAuthorize("@ss.hasPermi('ai:data:list')")
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public TableDataInfo list(@Valid @ModelAttribute GroupReportDataRequest query) {
|
public TableDataInfo list(@Valid @ModelAttribute GroupReportDataRequest query) {
|
||||||
TeamDailyConsumeAggregateVO aggregate = aiVideoReportDataService.selectTeamDailyConsumeAggregate(query);
|
List<AiVideoReportData> list = aiVideoReportDataService.selectTeamDailyConsumeList(query);
|
||||||
List<AiVideoReportData> list = aiVideoReportDataService.selectTeamDailyConsumeListPaged(query);
|
return getDataTable(list);
|
||||||
TableDataInfo rsp = new TableDataInfo();
|
|
||||||
rsp.setCode(HttpStatus.SUCCESS);
|
|
||||||
rsp.setMsg("查询成功");
|
|
||||||
rsp.setRows(list);
|
|
||||||
rsp.setTotal(aggregate.getTotalRows());
|
|
||||||
Map<String, Object> param = new HashMap<>(2);
|
|
||||||
param.put("aggregate", aggregate);
|
|
||||||
rsp.setParam(param);
|
|
||||||
return rsp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -66,13 +54,9 @@ public class AiVideoReportDataController extends BaseController {
|
||||||
@PreAuthorize("@ss.hasPermi('ai:data:export')")
|
@PreAuthorize("@ss.hasPermi('ai:data:export')")
|
||||||
@Log(title = "AI视频生成统计数据,作为其他统计报的数据源", businessType = BusinessType.EXPORT)
|
@Log(title = "AI视频生成统计数据,作为其他统计报的数据源", businessType = BusinessType.EXPORT)
|
||||||
@PostMapping("/export")
|
@PostMapping("/export")
|
||||||
public void export(HttpServletResponse response, GroupReportDataRequest query) {
|
public void export(HttpServletResponse response, @Valid @RequestBody GroupReportDataRequest query) {
|
||||||
if (query != null) {
|
|
||||||
query.setPageNum(null);
|
|
||||||
query.setPageSize(null);
|
|
||||||
}
|
|
||||||
List<AiVideoReportData> list = aiVideoReportDataService.selectTeamDailyConsumeList(query);
|
List<AiVideoReportData> list = aiVideoReportDataService.selectTeamDailyConsumeList(query);
|
||||||
ExcelUtil<AiVideoReportData> util = new ExcelUtil<>(AiVideoReportData.class);
|
ExcelUtil<AiVideoReportData> util = new ExcelUtil<AiVideoReportData>(AiVideoReportData.class);
|
||||||
util.exportExcel(response, list, "AI视频生成统计数据,作为其他统计报的数据源数据");
|
util.exportExcel(response, list, "AI视频生成统计数据,作为其他统计报的数据源数据");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ public class SubteamOverviewController extends BaseController {
|
||||||
|
|
||||||
@PreAuthorize("@ss.hasPermi('subteam:overview:view')")
|
@PreAuthorize("@ss.hasPermi('subteam:overview:view')")
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public AjaxResult<SubteamOverviewVO> overview() {
|
public AjaxResult overview() {
|
||||||
return success(subteamOverviewService.loadOverview());
|
SubteamOverviewVO vo = subteamOverviewService.loadOverview();
|
||||||
|
return success(vo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,4 @@ public final class RedisKey {
|
||||||
* Spring Cache 名:部门近七日汇总({@code @Cacheable} 与 TTL 配置须同名)
|
* Spring Cache 名:部门近七日汇总({@code @Cacheable} 与 TTL 配置须同名)
|
||||||
*/
|
*/
|
||||||
public static final String CACHE_DEPT_SUMMARY = "dept_summary";
|
public static final String CACHE_DEPT_SUMMARY = "dept_summary";
|
||||||
|
|
||||||
public static final String VIDEO_METRICS = "video_metrics";
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,8 +85,8 @@ public class AiUser extends BaseEntity {
|
||||||
private String paymentUrl;
|
private String paymentUrl;
|
||||||
|
|
||||||
/** 登录时间 */
|
/** 登录时间 */
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
@Excel(name = "登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
@Excel(name = "登录时间", width = 30, dateFormat = "yyyy-MM-dd")
|
||||||
private Date loginTime;
|
private Date loginTime;
|
||||||
|
|
||||||
/** 余额 */
|
/** 余额 */
|
||||||
|
|
|
||||||
|
|
@ -26,46 +26,43 @@ public class AiVideoReportData implements Serializable {
|
||||||
|
|
||||||
/** 主键 */
|
/** 主键 */
|
||||||
@TableId(type = IdType.AUTO)
|
@TableId(type = IdType.AUTO)
|
||||||
@Excel(name = "主键", type = Excel.Type.IMPORT)
|
@Excel(name = "主键")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/** 统计时间,到小时(库表注释:'%Y-%m-%d %H';业务写入常用 yyyyMMddHH) */
|
/** 统计时间,到小时(库表注释:'%Y-%m-%d %H';业务写入常用 yyyyMMddHH) */
|
||||||
@Excel(name = "日期", sort = 1)
|
@Excel(name = "统计时间(到小时)")
|
||||||
private String dateKey;
|
private String dateKey;
|
||||||
|
|
||||||
/** 部门ID */
|
/** 部门ID */
|
||||||
@Excel(name = "团队ID", sort = 2)
|
@Excel(name = "部门ID")
|
||||||
private Long deptId;
|
private Long deptId;
|
||||||
|
|
||||||
/** 消耗积分,按任务创建时间统计 */
|
/** 消耗积分,按任务创建时间统计 */
|
||||||
@Excel(name = "消耗积分", sort = 5)
|
@Excel(name = "消耗积分")
|
||||||
private BigDecimal score;
|
private BigDecimal score;
|
||||||
|
|
||||||
/** 实际充值积分(充值 - 退款) */
|
/** 实际充值积分(充值 - 退款) */
|
||||||
@Excel(name = "实际充值积分(充值-退款)", sort = 4)
|
@Excel(name = "实际充值积分")
|
||||||
private BigDecimal rechargeScore;
|
private BigDecimal rechargeScore;
|
||||||
|
|
||||||
/** 实际订单数,仅统计生成成功的任务 */
|
/** 实际订单数,仅统计生成成功的任务 */
|
||||||
@Excel(name = "实际订单数量(成功)", sort = 6)
|
@Excel(name = "订单数")
|
||||||
private Long orderCount;
|
private Long orderCount;
|
||||||
|
|
||||||
/** 三方消耗 tokens,按任务创建时间统计 */
|
/** 三方消耗 tokens,按任务创建时间统计 */
|
||||||
@Excel(name = "三方消耗tokens数量", sort = 7)
|
@Excel(name = "消耗tokens")
|
||||||
private Long useTokens;
|
private Long useTokens;
|
||||||
|
|
||||||
/** 创建时间 */
|
/** 创建时间 */
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
@Excel(name = "创建时间", type = Excel.Type.IMPORT)
|
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
/** 更新时间 */
|
/** 更新时间 */
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
@Excel(name = "更新时间", type = Excel.Type.IMPORT)
|
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
/** 团队名称(查询结果展示,非表字段) */
|
/** 团队名称(查询结果展示,非表字段) */
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
@Excel(name = "团队名称", sort = 3)
|
|
||||||
private String deptName;
|
private String deptName;
|
||||||
|
|
||||||
/** 查询日期 yyyyMMdd(非表字段,子团队单日统计等仍可用) */
|
/** 查询日期 yyyyMMdd(非表字段,子团队单日统计等仍可用) */
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,4 @@ public class GroupReportDataRequest implements Serializable {
|
||||||
|
|
||||||
/** 二级团队部门 ID,可选;为空表示不限团队 */
|
/** 二级团队部门 ID,可选;为空表示不限团队 */
|
||||||
private Long deptId;
|
private Long deptId;
|
||||||
|
|
||||||
/** 列表分页:页码,从 1 开始;导出不传 */
|
|
||||||
private Integer pageNum;
|
|
||||||
|
|
||||||
/** 列表分页:每页条数;导出不传 */
|
|
||||||
private Integer pageSize;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
package com.ruoyi.ai.domain.vo;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 团队每日消耗统计:分组总行数与明细列全量合计(与列表筛选条件一致)。
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class TeamDailyConsumeAggregateVO implements Serializable {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/** 按日+团队聚合后的行数(与分页 total 一致) */
|
|
||||||
private long totalRows;
|
|
||||||
|
|
||||||
private BigDecimal sumRechargeScore;
|
|
||||||
|
|
||||||
private BigDecimal sumScore;
|
|
||||||
|
|
||||||
private Long sumOrderCount;
|
|
||||||
|
|
||||||
private Long sumUseTokens;
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package com.ruoyi.ai.mapper;
|
package com.ruoyi.ai.mapper;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.ruoyi.ai.domain.AiOrder;
|
import com.ruoyi.ai.domain.AiOrder;
|
||||||
import com.ruoyi.ai.domain.AiVideoReportData;
|
import com.ruoyi.ai.domain.AiVideoReportData;
|
||||||
import com.ruoyi.ai.domain.request.GroupReportDataRequest;
|
import com.ruoyi.ai.domain.request.GroupReportDataRequest;
|
||||||
import com.ruoyi.ai.domain.vo.TeamDailyConsumeAggregateVO;
|
|
||||||
import com.ruoyi.system.domain.subteam.SubteamVideoMetrics;
|
import com.ruoyi.system.domain.subteam.SubteamVideoMetrics;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
|
@ -24,21 +24,6 @@ public interface AiVideoReportDataMapper extends BaseMapper<AiVideoReportData> {
|
||||||
*/
|
*/
|
||||||
List<AiVideoReportData> selectTeamDailyConsumeList(GroupReportDataRequest query);
|
List<AiVideoReportData> selectTeamDailyConsumeList(GroupReportDataRequest query);
|
||||||
|
|
||||||
/**
|
|
||||||
* 与列表相同筛选下的分组行数 + 四列合计(一条 SQL)。
|
|
||||||
*/
|
|
||||||
TeamDailyConsumeAggregateVO selectTeamDailyConsumeAggregate(GroupReportDataRequest query);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 按日+团队聚合后的分页列表(一条 SQL,LIMIT/OFFSET)。
|
|
||||||
* 参数须为标量:全局 {@code pagehelper.supportMethodsArguments=true} 时,若传入含 pageNum/pageSize 的请求对象,PageHelper 会再次追加 LIMIT。
|
|
||||||
*/
|
|
||||||
List<AiVideoReportData> selectTeamDailyConsumeListPaged(@Param("startDate") String startDate,
|
|
||||||
@Param("endDate") String endDate,
|
|
||||||
@Param("deptId") Long deptId,
|
|
||||||
@Param("offset") int offset,
|
|
||||||
@Param("limit") int limit);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按团队部门、日期聚合(团队后台消耗统计)
|
* 按团队部门、日期聚合(团队后台消耗统计)
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import com.ruoyi.ai.domain.AiVideoReportData;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.ruoyi.ai.domain.request.GroupReportDataRequest;
|
import com.ruoyi.ai.domain.request.GroupReportDataRequest;
|
||||||
import com.ruoyi.ai.domain.vo.TeamDailyConsumeAggregateVO;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI视频生成统计数据,作为其他统计报的数据源Service接口
|
* AI视频生成统计数据,作为其他统计报的数据源Service接口
|
||||||
|
|
@ -33,12 +32,6 @@ public interface IAiVideoReportDataService {
|
||||||
*/
|
*/
|
||||||
List<AiVideoReportData> selectTeamDailyConsumeList(GroupReportDataRequest query);
|
List<AiVideoReportData> selectTeamDailyConsumeList(GroupReportDataRequest query);
|
||||||
|
|
||||||
/** 分组总行数 + 四列合计(与列表筛选一致)。 */
|
|
||||||
TeamDailyConsumeAggregateVO selectTeamDailyConsumeAggregate(GroupReportDataRequest query);
|
|
||||||
|
|
||||||
/** 团队每日消耗分页列表(依赖 query 中的 pageNum/pageSize,Service 内写入 offset)。 */
|
|
||||||
List<AiVideoReportData> selectTeamDailyConsumeListPaged(GroupReportDataRequest query);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 团队每日消耗(按部门 ID,团队后台)
|
* 团队每日消耗(按部门 ID,团队后台)
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,20 @@
|
||||||
package com.ruoyi.ai.service.impl;
|
package com.ruoyi.ai.service.impl;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
||||||
import com.ruoyi.ai.domain.AiOrder;
|
import com.ruoyi.ai.domain.AiOrder;
|
||||||
import com.ruoyi.ai.domain.request.GroupReportDataRequest;
|
import com.ruoyi.ai.domain.request.GroupReportDataRequest;
|
||||||
import com.ruoyi.ai.domain.vo.TeamDailyConsumeAggregateVO;
|
import com.ruoyi.common.annotation.Excel;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.ruoyi.ai.mapper.AiVideoReportDataMapper;
|
import com.ruoyi.ai.mapper.AiVideoReportDataMapper;
|
||||||
|
|
@ -42,44 +49,6 @@ public class AiVideoReportDataServiceImpl implements IAiVideoReportDataService {
|
||||||
return aiVideoReportDataMapper.selectTeamDailyConsumeList(query);
|
return aiVideoReportDataMapper.selectTeamDailyConsumeList(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public TeamDailyConsumeAggregateVO selectTeamDailyConsumeAggregate(GroupReportDataRequest query) {
|
|
||||||
TeamDailyConsumeAggregateVO vo = aiVideoReportDataMapper.selectTeamDailyConsumeAggregate(query);
|
|
||||||
if (vo == null) {
|
|
||||||
vo = new TeamDailyConsumeAggregateVO();
|
|
||||||
vo.setTotalRows(0L);
|
|
||||||
vo.setSumRechargeScore(BigDecimal.ZERO);
|
|
||||||
vo.setSumScore(BigDecimal.ZERO);
|
|
||||||
vo.setSumOrderCount(0L);
|
|
||||||
vo.setSumUseTokens(0L);
|
|
||||||
} else {
|
|
||||||
if (vo.getSumRechargeScore() == null) {
|
|
||||||
vo.setSumRechargeScore(BigDecimal.ZERO);
|
|
||||||
}
|
|
||||||
if (vo.getSumScore() == null) {
|
|
||||||
vo.setSumScore(BigDecimal.ZERO);
|
|
||||||
}
|
|
||||||
if (vo.getSumOrderCount() == null) {
|
|
||||||
vo.setSumOrderCount(0L);
|
|
||||||
}
|
|
||||||
if (vo.getSumUseTokens() == null) {
|
|
||||||
vo.setSumUseTokens(0L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return vo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<AiVideoReportData> selectTeamDailyConsumeListPaged(GroupReportDataRequest query) {
|
|
||||||
int pageNum = query.getPageNum() == null || query.getPageNum() < 1 ? 1 : query.getPageNum();
|
|
||||||
int pageSize = query.getPageSize() == null || query.getPageSize() < 1 ? 10 : query.getPageSize();
|
|
||||||
query.setPageNum(pageNum);
|
|
||||||
query.setPageSize(pageSize);
|
|
||||||
int offset = (pageNum - 1) * pageSize;
|
|
||||||
return aiVideoReportDataMapper.selectTeamDailyConsumeListPaged(
|
|
||||||
query.getStartDate(), query.getEndDate(), query.getDeptId(), offset, pageSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AiVideoReportData> selectTeamDailyConsumeByDeptId(String statDate, Long deptId) {
|
public List<AiVideoReportData> selectTeamDailyConsumeByDeptId(String statDate, Long deptId) {
|
||||||
return aiVideoReportDataMapper.selectTeamDailyConsumeByDeptId(statDate, deptId);
|
return aiVideoReportDataMapper.selectTeamDailyConsumeByDeptId(statDate, deptId);
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@ import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import com.ruoyi.common.constant.RedisKey;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.ruoyi.ai.mapper.AiVideoReportDataMapper;
|
import com.ruoyi.ai.mapper.AiVideoReportDataMapper;
|
||||||
|
|
@ -23,8 +21,6 @@ public class SubteamOverviewServiceImpl implements ISubteamOverviewService {
|
||||||
|
|
||||||
private static final int METRICS_CACHE_MINUTES = 5;
|
private static final int METRICS_CACHE_MINUTES = 5;
|
||||||
|
|
||||||
private static final DateTimeFormatter VIDEO_METRICS_DAY = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISubteamScopeService subteamScopeService;
|
private ISubteamScopeService subteamScopeService;
|
||||||
|
|
||||||
|
|
@ -52,12 +48,12 @@ public class SubteamOverviewServiceImpl implements ISubteamOverviewService {
|
||||||
|
|
||||||
LocalDate end = LocalDate.now();
|
LocalDate end = LocalDate.now();
|
||||||
LocalDate start = end.minusDays(6);
|
LocalDate start = end.minusDays(6);
|
||||||
String startDate = start.format(VIDEO_METRICS_DAY);
|
String startDay = start.format(DateTimeFormatter.BASIC_ISO_DATE);
|
||||||
String endDate = end.format(VIDEO_METRICS_DAY);
|
String endDay = end.format(DateTimeFormatter.BASIC_ISO_DATE);
|
||||||
String cacheKey = RedisKey.VIDEO_METRICS + ":" + deptId + ":" + startDate + ":" + endDate;
|
String cacheKey = "subteam:videoMetrics:" + deptId + ":" + startDay + ":" + endDay;
|
||||||
SubteamVideoMetrics metrics = redisCache.getCacheObject(cacheKey);
|
SubteamVideoMetrics metrics = redisCache.getCacheObject(cacheKey);
|
||||||
if (metrics == null) {
|
if (metrics == null) {
|
||||||
metrics = aiVideoReportDataMapper.selectDeptVideoMetricsBetween(deptId, startDate, endDate);
|
metrics = aiVideoReportDataMapper.selectDeptVideoMetricsBetween(deptId, startDay, endDay);
|
||||||
if (metrics == null) {
|
if (metrics == null) {
|
||||||
metrics = new SubteamVideoMetrics();
|
metrics = new SubteamVideoMetrics();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,65 +26,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<sql id="teamDailyConsumeWhere">
|
|
||||||
<where>
|
|
||||||
<if test="startDate != null and startDate != ''">
|
|
||||||
and substr(vrd.date_key, 1, 10) >= #{startDate}
|
|
||||||
</if>
|
|
||||||
<if test="endDate != null and endDate != ''">
|
|
||||||
and substr(vrd.date_key, 1, 10) <= #{endDate}
|
|
||||||
</if>
|
|
||||||
<if test="deptId != null">
|
|
||||||
and vrd.dept_id = #{deptId}
|
|
||||||
</if>
|
|
||||||
</where>
|
|
||||||
</sql>
|
|
||||||
|
|
||||||
<sql id="teamDailyConsumeWhereVrd2">
|
|
||||||
<where>
|
|
||||||
<if test="startDate != null and startDate != ''">
|
|
||||||
and substr(vrd2.date_key, 1, 10) >= #{startDate}
|
|
||||||
</if>
|
|
||||||
<if test="endDate != null and endDate != ''">
|
|
||||||
and substr(vrd2.date_key, 1, 10) <= #{endDate}
|
|
||||||
</if>
|
|
||||||
<if test="deptId != null">
|
|
||||||
and vrd2.dept_id = #{deptId}
|
|
||||||
</if>
|
|
||||||
</where>
|
|
||||||
</sql>
|
|
||||||
|
|
||||||
<select id="selectTeamDailyConsumeAggregate" parameterType="com.ruoyi.ai.domain.request.GroupReportDataRequest"
|
|
||||||
resultType="com.ruoyi.ai.domain.vo.TeamDailyConsumeAggregateVO">
|
|
||||||
SELECT
|
|
||||||
(SELECT COUNT(*) FROM (
|
|
||||||
SELECT 1
|
|
||||||
FROM ai_video_report_data vrd
|
|
||||||
LEFT JOIN sys_dept d ON d.dept_id = vrd.dept_id
|
|
||||||
<include refid="teamDailyConsumeWhere"/>
|
|
||||||
GROUP BY substr(vrd.date_key, 1, 10), vrd.dept_id, d.dept_name
|
|
||||||
) cnt) AS total_rows,
|
|
||||||
IFNULL((SELECT SUM(vrd2.recharge_score) FROM ai_video_report_data vrd2
|
|
||||||
<include refid="teamDailyConsumeWhereVrd2"/>), 0) AS sum_recharge_score,
|
|
||||||
IFNULL((SELECT SUM(vrd2.score) FROM ai_video_report_data vrd2
|
|
||||||
<include refid="teamDailyConsumeWhereVrd2"/>), 0) AS sum_score,
|
|
||||||
IFNULL((SELECT SUM(vrd2.order_count) FROM ai_video_report_data vrd2
|
|
||||||
<include refid="teamDailyConsumeWhereVrd2"/>), 0) AS sum_order_count,
|
|
||||||
IFNULL((SELECT SUM(vrd2.use_tokens) FROM ai_video_report_data vrd2
|
|
||||||
<include refid="teamDailyConsumeWhereVrd2"/>), 0) AS sum_use_tokens
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectTeamDailyConsumeList" parameterType="com.ruoyi.ai.domain.request.GroupReportDataRequest" resultMap="AiVideoReportDataResult">
|
<select id="selectTeamDailyConsumeList" parameterType="com.ruoyi.ai.domain.request.GroupReportDataRequest" resultMap="AiVideoReportDataResult">
|
||||||
select substr(vrd.date_key, 1, 10) as date_key, vrd.dept_id, d.dept_name, sum(vrd.recharge_score) as recharge_score,
|
|
||||||
sum(vrd.score) as score, sum(vrd.order_count) as order_count, sum(vrd.use_tokens) as use_tokens
|
|
||||||
from ai_video_report_data vrd left join sys_dept d on d.dept_id = vrd.dept_id
|
|
||||||
<include refid="teamDailyConsumeWhere"/>
|
|
||||||
group by substr(vrd.date_key, 1, 10), vrd.dept_id, d.dept_name
|
|
||||||
order by substr(vrd.date_key, 1, 10) desc, vrd.dept_id desc
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectTeamDailyConsumeListPaged" resultMap="AiVideoReportDataResult">
|
|
||||||
SELECT * FROM (
|
|
||||||
select substr(vrd.date_key, 1, 10) as date_key, vrd.dept_id, d.dept_name, sum(vrd.recharge_score) as recharge_score,
|
select substr(vrd.date_key, 1, 10) as date_key, vrd.dept_id, d.dept_name, sum(vrd.recharge_score) as recharge_score,
|
||||||
sum(vrd.score) as score, sum(vrd.order_count) as order_count, sum(vrd.use_tokens) as use_tokens
|
sum(vrd.score) as score, sum(vrd.order_count) as order_count, sum(vrd.use_tokens) as use_tokens
|
||||||
from ai_video_report_data vrd left join sys_dept d on d.dept_id = vrd.dept_id
|
from ai_video_report_data vrd left join sys_dept d on d.dept_id = vrd.dept_id
|
||||||
|
|
@ -100,9 +42,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
group by substr(vrd.date_key, 1, 10), vrd.dept_id, d.dept_name
|
group by substr(vrd.date_key, 1, 10), vrd.dept_id, d.dept_name
|
||||||
) x
|
order by substr(vrd.date_key, 1, 10) desc, vrd.dept_id desc
|
||||||
ORDER BY x.date_key DESC, x.dept_id DESC
|
|
||||||
LIMIT #{limit} OFFSET #{offset}
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectTeamDailyConsumeByDeptId" resultMap="AiVideoReportDataResult">
|
<select id="selectTeamDailyConsumeByDeptId" resultMap="AiVideoReportDataResult">
|
||||||
|
|
@ -122,9 +62,34 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectDeptVideoMetricsBetween" resultType="com.ruoyi.system.domain.subteam.SubteamVideoMetrics">
|
<select id="selectDeptVideoMetricsBetween" resultType="com.ruoyi.system.domain.subteam.SubteamVideoMetrics">
|
||||||
select ifnull(sum(vrd.score), 0) as consumeScore, ifnull(sum(vrd.order_count), 0) as orderCount
|
select
|
||||||
from ai_video_report_data vrd where vrd.dept_id = #{deptId}
|
coalesce(sum(vrd.score), 0) as consumeScore,
|
||||||
and substr(vrd.date_key, 1, 10) >= #{startDay}
|
coalesce(sum(vrd.order_count), 0) as orderCount
|
||||||
and substr(vrd.date_key, 1, 10) <= #{endDay}
|
from ai_video_report_data vrd
|
||||||
|
where vrd.dept_id = #{deptId}
|
||||||
|
and substr(vrd.date_key, 1, 8) >= #{startDay}
|
||||||
|
and substr(vrd.date_key, 1, 8) <= #{endDay}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<insert id="upsertVideoConsumeIncrement">
|
||||||
|
insert into ai_video_report_data
|
||||||
|
(date_key, dept_id, score, order_count, use_tokens, recharge_score, create_time, update_time)
|
||||||
|
values
|
||||||
|
(#{dateKey}, #{deptId}, #{score}, #{orderCount}, #{useTokens}, 0, now(), now())
|
||||||
|
on duplicate key update
|
||||||
|
score = score + values(score),
|
||||||
|
order_count = order_count + values(order_count),
|
||||||
|
use_tokens = use_tokens + values(use_tokens),
|
||||||
|
update_time = now()
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<insert id="upsertRechargeScoreIncrement">
|
||||||
|
insert into ai_video_report_data
|
||||||
|
(date_key, dept_id, score, order_count, use_tokens, recharge_score, create_time, update_time)
|
||||||
|
values
|
||||||
|
(#{dateKey}, #{deptId}, 0, 0, 0, 0, #{rechargeScore}, now(), now())
|
||||||
|
on duplicate key update
|
||||||
|
recharge_score = recharge_score + values(recharge_score),
|
||||||
|
update_time = now()
|
||||||
|
</insert>
|
||||||
</mapper>
|
</mapper>
|
||||||
Loading…
Reference in New Issue