Merge branch 'seedance_balance' of https://gitea.06zk.com/best_yunwei/ai_images into seedance_balance
# Conflicts: # web-api/ruoyi-system/src/main/java/com/ruoyi/ai/mapper/AiVideoReportDataMapper.java
This commit is contained in:
commit
b2f1bc8439
|
|
@ -0,0 +1,44 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询团队(部门)对应火山引擎配置列表
|
||||||
|
export function listConfig(query) {
|
||||||
|
return request({
|
||||||
|
url: '/ai/config/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询团队(部门)对应火山引擎配置详细
|
||||||
|
export function getConfig(id) {
|
||||||
|
return request({
|
||||||
|
url: '/ai/config/' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增团队(部门)对应火山引擎配置
|
||||||
|
export function addConfig(data) {
|
||||||
|
return request({
|
||||||
|
url: '/ai/config',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改团队(部门)对应火山引擎配置
|
||||||
|
export function updateConfig(data) {
|
||||||
|
return request({
|
||||||
|
url: '/ai/config',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除团队(部门)对应火山引擎配置
|
||||||
|
export function delConfig(id) {
|
||||||
|
return request({
|
||||||
|
url: '/ai/config/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询团队每日消耗统计
|
||||||
|
export function listData(query) {
|
||||||
|
return request({
|
||||||
|
url: '/ai/data/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询订单管理列表
|
// 查询团队(部门)充值退款订单列表
|
||||||
export function listOrder(query) {
|
export function listOrder(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/ai/order/list',
|
url: '/ai/order/list',
|
||||||
|
|
@ -9,7 +9,7 @@ export function listOrder(query) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询订单管理详细
|
// 查询团队(部门)充值退款订单详细
|
||||||
export function getOrder(id) {
|
export function getOrder(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/ai/order/' + id,
|
url: '/ai/order/' + id,
|
||||||
|
|
@ -17,7 +17,7 @@ export function getOrder(id) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增订单管理
|
// 新增团队(部门)充值退款订单
|
||||||
export function addOrder(data) {
|
export function addOrder(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/ai/order',
|
url: '/ai/order',
|
||||||
|
|
@ -26,7 +26,7 @@ export function addOrder(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改订单管理
|
// 修改团队(部门)充值退款订单
|
||||||
export function updateOrder(data) {
|
export function updateOrder(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/ai/order',
|
url: '/ai/order',
|
||||||
|
|
@ -35,29 +35,10 @@ export function updateOrder(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function changeIsTop(id, isTop) {
|
// 删除团队(部门)充值退款订单
|
||||||
const data = {
|
|
||||||
id,
|
|
||||||
isTop
|
|
||||||
}
|
|
||||||
return request({
|
|
||||||
url: '/ai/order',
|
|
||||||
method: 'put',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除订单管理
|
|
||||||
export function delOrder(id) {
|
export function delOrder(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/ai/order/' + id,
|
url: '/ai/order/' + id,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function downloadVideo(id) {
|
|
||||||
return request({
|
|
||||||
url: '/api/ai/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询团队(部门)余额变动列表
|
||||||
|
export function listRecord(query) {
|
||||||
|
return request({
|
||||||
|
url: '/ai/record/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询团队(部门)余额变动详细
|
||||||
|
export function getRecord(id) {
|
||||||
|
return request({
|
||||||
|
url: '/ai/record/' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增团队(部门)余额变动
|
||||||
|
export function addRecord(data) {
|
||||||
|
return request({
|
||||||
|
url: '/ai/record',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改团队(部门)余额变动
|
||||||
|
export function updateRecord(data) {
|
||||||
|
return request({
|
||||||
|
url: '/ai/record',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除团队(部门)余额变动
|
||||||
|
export function delRecord(id) {
|
||||||
|
return request({
|
||||||
|
url: '/ai/record/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export function getSubteamOverview() {
|
||||||
|
return request({ url: '/subteam/overview', method: 'get' })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listSubteamUser(query) {
|
||||||
|
return request({ url: '/subteam/user/list', method: 'get', params: query })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSubteamUser(id) {
|
||||||
|
const url = id != null && id !== '' ? '/subteam/user/' + id : '/subteam/user'
|
||||||
|
return request({ url, method: 'get' })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addSubteamUser(data) {
|
||||||
|
return request({ url: '/subteam/user', method: 'post', data })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSubteamUser(data) {
|
||||||
|
return request({ url: '/subteam/user', method: 'put', data })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function delSubteamUser(userIds) {
|
||||||
|
return request({ url: '/subteam/user/' + userIds, method: 'delete' })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetSubteamUserPwd(data) {
|
||||||
|
return request({ url: '/subteam/user/resetPwd', method: 'put', data })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function changeSubteamUserStatus(data) {
|
||||||
|
return request({ url: '/subteam/user/changeStatus', method: 'put', data })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listSubteamVideoOrder(query) {
|
||||||
|
return request({ url: '/subteam/video-order/list', method: 'get', params: query })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSubteamVideoOrder(id) {
|
||||||
|
return request({ url: '/subteam/video-order/' + id, method: 'get' })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listSubteamChargeOrder(query) {
|
||||||
|
return request({ url: '/subteam/charge-order/list', method: 'get', params: query })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSubteamChargeOrder(id) {
|
||||||
|
return request({ url: '/subteam/charge-order/' + id, method: 'get' })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listSubteamUserBalance(query) {
|
||||||
|
return request({ url: '/subteam/user-balance/list', method: 'get', params: query })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSubteamUserBalance(id) {
|
||||||
|
return request({ url: '/subteam/user-balance/' + id, method: 'get' })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listSubteamConsumeStat(query) {
|
||||||
|
return request({ url: '/subteam/consume-stat/list', method: 'get', params: query })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listSubteamGroupBalance(query) {
|
||||||
|
return request({ url: '/subteam/group-balance/list', method: 'get', params: query })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSubteamGroupBalance(id) {
|
||||||
|
return request({ url: '/subteam/group-balance/' + id, method: 'get' })
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,270 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
|
<el-form-item label="部门ID" prop="deptId">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.deptId"
|
||||||
|
placeholder="请输入部门ID"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<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-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['ai:config:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
icon="el-icon-edit"
|
||||||
|
size="mini"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUpdate"
|
||||||
|
v-hasPermi="['ai:config:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="el-icon-delete"
|
||||||
|
size="mini"
|
||||||
|
:disabled="multiple"
|
||||||
|
@click="handleDelete"
|
||||||
|
v-hasPermi="['ai:config:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="el-icon-download"
|
||||||
|
size="mini"
|
||||||
|
@click="handleExport"
|
||||||
|
v-hasPermi="['ai:config:export']"
|
||||||
|
>导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="configList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="ID" align="center" prop="id" />
|
||||||
|
<el-table-column label="部门ID" align="center" prop="deptId" />
|
||||||
|
<el-table-column label="视频模型列表JSON(label+value)" align="center" prop="modelParm" />
|
||||||
|
<el-table-column label="Byte project,加密" align="center" prop="project" />
|
||||||
|
<el-table-column label="Byte API Key,加密" align="center" prop="byteApiKey" />
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['ai:config:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
v-hasPermi="['ai:config:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total>0"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="queryParams.pageNum"
|
||||||
|
:limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加或修改团队(部门)对应火山引擎配置对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="部门ID" prop="deptId">
|
||||||
|
<el-input v-model="form.deptId" placeholder="请输入部门ID" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="视频模型列表JSON(label+value)" prop="modelParm">
|
||||||
|
<el-input v-model="form.modelParm" type="textarea" placeholder="请输入内容" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="Byte project,加密" prop="project">
|
||||||
|
<el-input v-model="form.project" placeholder="请输入Byte project,加密" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="Byte API Key,加密" prop="byteApiKey">
|
||||||
|
<el-input v-model="form.byteApiKey" placeholder="请输入Byte API Key,加密" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listConfig, getConfig, delConfig, addConfig, updateConfig } from "@/api/ai/config"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Config",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 选中数组
|
||||||
|
ids: [],
|
||||||
|
// 非单个禁用
|
||||||
|
single: true,
|
||||||
|
// 非多个禁用
|
||||||
|
multiple: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 团队(部门)对应火山引擎配置表格数据
|
||||||
|
configList: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
deptId: null,
|
||||||
|
modelParm: null,
|
||||||
|
project: null,
|
||||||
|
byteApiKey: null,
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
deptId: [
|
||||||
|
{ required: true, message: "部门ID不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 查询团队(部门)对应火山引擎配置列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listConfig(this.queryParams).then(response => {
|
||||||
|
this.configList = response.rows
|
||||||
|
this.total = response.total
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
id: null,
|
||||||
|
deptId: null,
|
||||||
|
modelParm: null,
|
||||||
|
project: null,
|
||||||
|
byteApiKey: null,
|
||||||
|
createBy: null,
|
||||||
|
createTime: null,
|
||||||
|
updateBy: null,
|
||||||
|
updateTime: null
|
||||||
|
}
|
||||||
|
this.resetForm("form")
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
// 多选框选中数据
|
||||||
|
handleSelectionChange(selection) {
|
||||||
|
this.ids = selection.map(item => item.id)
|
||||||
|
this.single = selection.length!==1
|
||||||
|
this.multiple = !selection.length
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset()
|
||||||
|
this.open = true
|
||||||
|
this.title = "添加团队(部门)对应火山引擎配置"
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset()
|
||||||
|
const id = row.id || this.ids
|
||||||
|
getConfig(id).then(response => {
|
||||||
|
this.form = response.data
|
||||||
|
this.open = true
|
||||||
|
this.title = "修改团队(部门)对应火山引擎配置"
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.form.id != null) {
|
||||||
|
updateConfig(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
addConfig(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("新增成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const ids = row.id || this.ids
|
||||||
|
this.$modal.confirm('是否确认删除团队(部门)对应火山引擎配置编号为"' + ids + '"的数据项?').then(function() {
|
||||||
|
return delConfig(ids)
|
||||||
|
}).then(() => {
|
||||||
|
this.getList()
|
||||||
|
this.$modal.msgSuccess("删除成功")
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
this.download('ai/config/export', {
|
||||||
|
...this.queryParams
|
||||||
|
}, `config_${new Date().getTime()}.xlsx`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="96px">
|
||||||
|
<el-form-item label="日期" prop="statDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="queryParams.statDate"
|
||||||
|
type="date"
|
||||||
|
value-format="yyyyMMdd"
|
||||||
|
placeholder="请选择日期"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="团队名称" prop="deptId">
|
||||||
|
<el-select
|
||||||
|
v-model="queryParams.deptId"
|
||||||
|
placeholder="请选择团队"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 220px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in deptOptions"
|
||||||
|
:key="item.deptId"
|
||||||
|
:label="item.deptName"
|
||||||
|
:value="item.deptId"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<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-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="dataList">
|
||||||
|
<el-table-column label="日期" align="center" prop="dateKey" />
|
||||||
|
<el-table-column label="团队名称" align="center" prop="deptName" />
|
||||||
|
<el-table-column label="实际充值积分(充值-退款)" align="center" prop="rechargeScore" />
|
||||||
|
<el-table-column label="消耗积分" align="center" prop="score" />
|
||||||
|
<el-table-column label="实际订单数量(成功)" align="center" prop="orderCount" />
|
||||||
|
<el-table-column label="三方消耗tokens数量" align="center" prop="useTokens" />
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total>0"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="queryParams.pageNum"
|
||||||
|
:limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listData } from "@/api/ai/data"
|
||||||
|
import { listDept } from "@/api/ai/dept"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "TeamConsumeData",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层:首屏不自动查询,默认不展示加载状态
|
||||||
|
loading: false,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 团队每日消耗统计表格数据
|
||||||
|
dataList: [],
|
||||||
|
// 团队下拉选项(仅二级部门)
|
||||||
|
deptOptions: [],
|
||||||
|
// 首次进入默认不查询
|
||||||
|
searched: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
statDate: null,
|
||||||
|
deptId: null
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadSecondLevelDeptOptions()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 加载二级部门选项 */
|
||||||
|
loadSecondLevelDeptOptions() {
|
||||||
|
listDept({ status: "0" }).then(response => {
|
||||||
|
const allDeptList = response.data || []
|
||||||
|
this.deptOptions = allDeptList.filter(item => this.isSecondLevelDept(item))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 判断是否为二级部门(一级部门的直属子部门) */
|
||||||
|
isSecondLevelDept(dept) {
|
||||||
|
if (!dept || !dept.ancestors) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return String(dept.ancestors).split(",").filter(Boolean).length === 2
|
||||||
|
},
|
||||||
|
/** 查询团队每日消耗统计列表 */
|
||||||
|
getList() {
|
||||||
|
if (!this.searched) {
|
||||||
|
this.loading = false
|
||||||
|
this.dataList = []
|
||||||
|
this.total = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.loading = true
|
||||||
|
listData(this.queryParams).then(response => {
|
||||||
|
this.dataList = response.rows
|
||||||
|
this.total = response.total
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
if (!this.queryParams.statDate || !this.queryParams.deptId) {
|
||||||
|
this.$modal.msgWarning("请先填写日期和团队名称后再搜索")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.searched = true
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.searched = false
|
||||||
|
this.loading = false
|
||||||
|
this.dataList = []
|
||||||
|
this.total = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -1,79 +1,59 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-form
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="88px">
|
||||||
:model="queryParams"
|
<el-form-item label="团队名称" prop="deptName">
|
||||||
ref="queryForm"
|
|
||||||
size="small"
|
|
||||||
:inline="true"
|
|
||||||
v-show="showSearch"
|
|
||||||
label-width="68px"
|
|
||||||
>
|
|
||||||
<el-form-item label="订单编号" prop="orderNum">
|
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.orderNum"
|
v-model="queryParams.deptName"
|
||||||
placeholder="请输入订单编号"
|
placeholder="支持模糊搜索"
|
||||||
clearable
|
clearable
|
||||||
@keyup.enter.native="handleQuery"
|
@keyup.enter.native="handleQuery"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="用户ID" prop="uuid">
|
<el-form-item label="类型" prop="orderType">
|
||||||
<el-input
|
<el-select v-model="queryParams.orderType" placeholder="全部" clearable style="width: 140px">
|
||||||
v-model="queryParams.uuid"
|
<el-option v-for="item in orderTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
placeholder="请输入用户ID"
|
|
||||||
clearable
|
|
||||||
@keyup.enter.native="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="操作类型" prop="type">
|
|
||||||
<el-select v-model="queryParams.type" placeholder="请选择操作类型" clearable>
|
|
||||||
<el-option
|
|
||||||
v-for="dict in dict.type.ai_function_type"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="是否置顶" prop="isTop">
|
|
||||||
<el-select v-model="queryParams.isTop" placeholder="请选择" clearable>
|
|
||||||
<el-option
|
|
||||||
v-for="dict in dict.type.sys_yes_no"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="状态" prop="status">
|
|
||||||
<el-select
|
|
||||||
v-model="queryParams.status"
|
|
||||||
placeholder="请选择状态"
|
|
||||||
filterable
|
|
||||||
clearable
|
|
||||||
style="width: 200px; margin-bottom: 16px;"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="(label, value) in statusMap"
|
|
||||||
:key="value"
|
|
||||||
:label="label"
|
|
||||||
:value="Number(value)"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="创建时间">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<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
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['ai:order:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
icon="el-icon-edit"
|
||||||
|
size="mini"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUpdate"
|
||||||
|
v-hasPermi="['ai:order:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="el-icon-delete"
|
||||||
|
size="mini"
|
||||||
|
:disabled="multiple"
|
||||||
|
@click="handleDelete"
|
||||||
|
v-hasPermi="['ai:order:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
type="warning"
|
type="warning"
|
||||||
plain
|
plain
|
||||||
|
|
@ -82,113 +62,45 @@
|
||||||
@click="handleExport"
|
@click="handleExport"
|
||||||
v-hasPermi="['ai:order:export']"
|
v-hasPermi="['ai:order:export']"
|
||||||
>导出</el-button>
|
>导出</el-button>
|
||||||
</el-form-item>
|
</el-col>
|
||||||
</el-form>
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
</el-row>
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="orderList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="orderList" @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" 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="72" />
|
||||||
<!-- <el-table-column label="备注" align="center" prop="remark" /> -->
|
<el-table-column label="团队名称" align="center" prop="deptName" min-width="120" show-overflow-tooltip />
|
||||||
<el-table-column label="订单编号" align="center" prop="orderNum" width="150"/>
|
<el-table-column label="类型" align="center" width="100">
|
||||||
<el-table-column label="用户ID" align="center" prop="uuid" width="100" />
|
|
||||||
<el-table-column label="操作类型" align="center" prop="type" width="90" >
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<dict-tag :options="dict.type.ai_function_type" :value="scope.row.type" />
|
<span>{{ orderTypeLabel(scope.row.orderType) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="金额" align="center" prop="amount" width="100" />
|
<el-table-column label="金额(元)" align="center" prop="money" width="100" />
|
||||||
<el-table-column label="生成结果" align="center" width="200">
|
<el-table-column label="积分" align="center" prop="amount" width="100" />
|
||||||
|
<el-table-column label="时间" align="center" prop="createTime" width="160">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!-- 判断是否为链接 -->
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
<template v-if="isUrl(scope.row.result)">
|
|
||||||
<!-- 图片链接 -->
|
|
||||||
<img
|
|
||||||
v-if="isImage(scope.row.result)"
|
|
||||||
:src="scope.row.result"
|
|
||||||
class="preview-img"
|
|
||||||
@click="viewImage(scope.row.result)"
|
|
||||||
alt="预览图片"
|
|
||||||
/>
|
|
||||||
<!-- 视频链接 -->
|
|
||||||
<video
|
|
||||||
v-else-if="isVideo(scope.row.result)"
|
|
||||||
:src="scope.row.result"
|
|
||||||
class="preview-video"
|
|
||||||
@click="playVideo(scope.row.result)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<!-- 视频任务失败等场景:result 为 VideoTaskError JSON(表格内简短,悬停看全文) -->
|
|
||||||
<template v-else-if="parseVolcTaskErrorJson(scope.row.result)">
|
|
||||||
<span
|
|
||||||
v-for="err in [parseVolcTaskErrorJson(scope.row.result)]"
|
|
||||||
:key="'oe-' + scope.row.id"
|
|
||||||
class="order-result-error-wrap"
|
|
||||||
>
|
|
||||||
<el-tooltip
|
|
||||||
placement="top-start"
|
|
||||||
effect="dark"
|
|
||||||
:open-delay="200"
|
|
||||||
popper-class="order-result-error-tooltip-popper"
|
|
||||||
>
|
|
||||||
<div slot="content" class="order-result-error-tooltip-body">
|
|
||||||
<div class="order-result-error-tooltip-row">
|
|
||||||
<span class="order-result-error-tooltip-k">错误编号:</span>
|
|
||||||
<span class="order-result-error-tooltip-v">{{ err.code || '—' }}</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="volcTaskErrorHintForCode(err.code)"
|
|
||||||
class="order-result-error-tooltip-row"
|
|
||||||
>
|
|
||||||
<span class="order-result-error-tooltip-k">中文说明:</span>
|
|
||||||
<span class="order-result-error-tooltip-v">{{
|
|
||||||
volcTaskErrorHintForCode(err.code)
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<div class="order-result-error-tooltip-row order-result-error-tooltip-row--msg">
|
|
||||||
<span class="order-result-error-tooltip-k">信息:</span>
|
|
||||||
<span class="order-result-error-tooltip-v">{{ err.message || '—' }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span class="order-result-error-compact">{{ volcTaskErrorCellSummary(err) }}</span>
|
|
||||||
</el-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<!-- 非链接内容(如任务 id,可点击尝试拉取视频) -->
|
|
||||||
<span v-else @click="handleOtherEvent(scope.row)">{{ scope.row.result }}</span>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="文字描述" align="center" prop="text">
|
<el-table-column label="备注" align="center" prop="remark" min-width="140" show-overflow-tooltip />
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="140">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!-- 核心:给 popover 加 ref,触发元素绑定 v-popover -->
|
<el-button
|
||||||
<el-popover
|
size="mini"
|
||||||
ref="promptPopover"
|
type="text"
|
||||||
placement="top"
|
icon="el-icon-edit"
|
||||||
width="400"
|
@click="handleUpdate(scope.row)"
|
||||||
trigger="hover"
|
v-hasPermi="['ai:order:edit']"
|
||||||
:content="scope.row.text || '无提示词'"
|
>修改</el-button>
|
||||||
></el-popover>
|
<el-button
|
||||||
<!-- 触发元素:绑定 v-popover 到 popover 的 ref -->
|
size="mini"
|
||||||
<div
|
type="text"
|
||||||
class="text-ellipsis-two-lines"
|
icon="el-icon-delete"
|
||||||
v-popover:promptPopover
|
@click="handleDelete(scope.row)"
|
||||||
style="cursor: pointer;"
|
v-hasPermi="['ai:order:remove']"
|
||||||
>{{ scope.row.text}}</div>
|
>删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="置顶" align="center" key="status" width="60">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-switch
|
|
||||||
v-model="scope.row.isTop"
|
|
||||||
active-value="Y"
|
|
||||||
inactive-value="N"
|
|
||||||
@change="handleIsTopChange(scope.row)"
|
|
||||||
></el-switch>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="150"/>
|
|
||||||
<el-table-column label="状态" align="center" prop="status" :formatter="formatStatus" width="70"/>
|
|
||||||
<el-table-column label="来源" align="center" prop="source" width="70"/>
|
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination
|
<pagination
|
||||||
|
|
@ -199,39 +111,40 @@
|
||||||
@pagination="getList"
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 添加或修改订单管理对话框 -->
|
<el-dialog :title="title" :visible.sync="open" width="560px" append-to-body>
|
||||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
<el-form-item label="团队" prop="deptId">
|
||||||
<el-form-item label="订单编号" prop="orderNum">
|
<treeselect
|
||||||
<el-input v-model="form.orderNum" placeholder="请输入订单编号" />
|
v-model="form.deptId"
|
||||||
|
:options="deptOptions"
|
||||||
|
:normalizer="normalizer"
|
||||||
|
:show-count="true"
|
||||||
|
placeholder="请选择团队(二级部门)"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="用户ID" prop="userId">
|
<el-form-item label="类型" prop="orderType">
|
||||||
<el-input v-model="form.userId" placeholder="请输入用户ID" />
|
<el-select v-model="form.orderType" placeholder="请选择" style="width: 100%">
|
||||||
</el-form-item>
|
<el-option v-for="item in orderTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
<el-form-item label="状态" prop="status">
|
|
||||||
<el-select
|
|
||||||
v-model="form.status"
|
|
||||||
placeholder="请选择状态"
|
|
||||||
filterable
|
|
||||||
clearable
|
|
||||||
style="width: 200px;"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="(label, value) in statusMap"
|
|
||||||
:key="value"
|
|
||||||
:label="label"
|
|
||||||
:value="Number(value)"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="金额" prop="amount">
|
<el-form-item label="金额(元)" prop="money">
|
||||||
<el-input v-model="form.amount" placeholder="请输入金额" />
|
<el-input v-model="form.money" placeholder="可选,对账用金额" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="生成结果" prop="result">
|
<el-form-item label="积分" prop="amount">
|
||||||
<el-input v-model="form.result" placeholder="请输入生成结果" />
|
<el-input v-model="form.amount" placeholder="充值/退款填正数;手动修改可填负数表示扣减" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="status">
|
||||||
|
<el-select v-model="form.status" placeholder="请选择" style="width: 100%">
|
||||||
|
<el-option label="进行中" :value="0" />
|
||||||
|
<el-option label="已完成" :value="1" />
|
||||||
|
<el-option label="失败" :value="2" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="订单编号" prop="orderNum" v-if="form.id != null">
|
||||||
|
<el-input v-model="form.orderNum" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
<el-input v-model="form.remark" type="textarea" :rows="3" placeholder="对账说明、打款信息等" maxlength="500" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
|
|
@ -239,424 +152,158 @@
|
||||||
<el-button @click="cancel">取 消</el-button>
|
<el-button @click="cancel">取 消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 图片预览弹窗 -->
|
|
||||||
<el-dialog :visible.sync="imageDialogVisible" title="图片预览" width="60%">
|
|
||||||
<img :src="previewImageUrl" class="dialog-img" alt="大图预览" />
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 新增视频弹窗 -->
|
|
||||||
<el-dialog :visible.sync="videoDialogVisible" title="视频播放" width="60%">
|
|
||||||
<video :src="previewVideoUrl" controls class="dialog-video"></video>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import { listOrder, getOrder, delOrder, addOrder, updateOrder } from "@/api/ai/order"
|
||||||
listOrder,
|
import { deptTreeSelect } from "@/api/system/user"
|
||||||
getOrder,
|
import Treeselect from "@riophae/vue-treeselect"
|
||||||
delOrder,
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
|
||||||
addOrder,
|
|
||||||
downloadVideo,
|
|
||||||
changeIsTop,
|
|
||||||
updateOrder
|
|
||||||
} from "@/api/ai/order";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Order",
|
name: "TeamChargeOrder",
|
||||||
dicts: ["ai_function_type", "sys_yes_no"],
|
components: { Treeselect },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
imageDialogVisible: false,
|
|
||||||
videoDialogVisible: false,
|
|
||||||
previewVideoUrl: "",
|
|
||||||
previewImageUrl: "",
|
|
||||||
dateRange: [],
|
|
||||||
statusMap: {
|
|
||||||
0: "进行中",
|
|
||||||
1: "已完成",
|
|
||||||
2: "已失败"
|
|
||||||
},
|
|
||||||
// 遮罩层
|
|
||||||
loading: true,
|
loading: true,
|
||||||
// 选中数组
|
|
||||||
ids: [],
|
ids: [],
|
||||||
// 非单个禁用
|
|
||||||
single: true,
|
single: true,
|
||||||
// 非多个禁用
|
|
||||||
multiple: true,
|
multiple: true,
|
||||||
// 显示搜索条件
|
|
||||||
showSearch: true,
|
showSearch: true,
|
||||||
// 总条数
|
|
||||||
total: 0,
|
total: 0,
|
||||||
// 订单管理表格数据
|
|
||||||
orderList: [],
|
orderList: [],
|
||||||
// 弹出层标题
|
|
||||||
title: "",
|
title: "",
|
||||||
// 是否显示弹出层
|
|
||||||
open: false,
|
open: false,
|
||||||
// 查询参数
|
deptOptions: [],
|
||||||
|
orderTypeOptions: [
|
||||||
|
{ label: "充值", value: 0 },
|
||||||
|
{ label: "退款", value: 1 },
|
||||||
|
{ label: "手动修改", value: 2 }
|
||||||
|
],
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
orderNum: null,
|
deptName: null,
|
||||||
userId: null,
|
orderType: null
|
||||||
type: null,
|
|
||||||
amount: null,
|
|
||||||
result: null,
|
|
||||||
status: null
|
|
||||||
},
|
},
|
||||||
// 表单参数
|
|
||||||
form: {},
|
form: {},
|
||||||
// 表单校验
|
|
||||||
rules: {
|
rules: {
|
||||||
delFlag: [
|
deptId: [{ required: true, message: "请选择团队", trigger: "change" }],
|
||||||
{ required: true, message: "删除标志不能为空", trigger: "blur" }
|
orderType: [{ required: true, message: "请选择类型", trigger: "change" }],
|
||||||
]
|
amount: [{ required: true, message: "请填写积分", trigger: "blur" }],
|
||||||
|
status: [{ required: true, message: "请选择状态", trigger: "change" }]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getList();
|
this.getDeptTree()
|
||||||
|
this.getList()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleIsTopChange(row) {
|
orderTypeLabel(orderType) {
|
||||||
let text = row.isTop === "Y" ? "置顶" : "取消置顶";
|
const n = orderType !== undefined && orderType !== null ? Number(orderType) : null
|
||||||
this.$modal
|
const hit = this.orderTypeOptions.find(o => o.value === n)
|
||||||
.confirm('确认要"' + text + '""' + row.id + '"作品吗?')
|
return hit ? hit.label : "—"
|
||||||
.then(function() {
|
|
||||||
return changeIsTop(row.id, row.isTop);
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
this.$modal.msgSuccess(text + "成功");
|
|
||||||
})
|
|
||||||
.catch(function() {
|
|
||||||
row.isTop = row.isTop === "Y" ? "N" : "Y";
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
// 判断是否为 http(s) URL(与 portal-ui 生成视频模块一致)
|
getDeptTree() {
|
||||||
isUrl(str) {
|
deptTreeSelect().then(response => {
|
||||||
const value = String(str || "").trim();
|
this.deptOptions = response.data || []
|
||||||
return /^https?:\/\//i.test(value);
|
})
|
||||||
},
|
},
|
||||||
/** 已知错误码对应中文说明(与门户 VideoGen 一致) */
|
normalizer(node) {
|
||||||
volcTaskErrorHintForCode(code) {
|
if (node.children && !node.children.length) {
|
||||||
const c = String(code || "").trim();
|
delete node.children
|
||||||
const hints = {
|
|
||||||
OutputVideoSensitiveContentDetected: "输出视频可能包含敏感信息",
|
|
||||||
InvalidParameter: "请求参数无效"
|
|
||||||
};
|
|
||||||
return hints[c] || "";
|
|
||||||
},
|
|
||||||
/** 表格内摘要:已知码只显示中文,未知码显示 code */
|
|
||||||
volcTaskErrorCellSummary(err) {
|
|
||||||
if (!err) return "—";
|
|
||||||
const code = String(err.code || "").trim();
|
|
||||||
const hint = this.volcTaskErrorHintForCode(code);
|
|
||||||
if (hint) return hint;
|
|
||||||
if (code) return code;
|
|
||||||
const msg = String(err.message || "").trim();
|
|
||||||
return msg ? msg.slice(0, 32) + (msg.length > 32 ? "…" : "") : "—";
|
|
||||||
},
|
|
||||||
/** 已知火山错误码后附中文说明(括号),导出等场景可用 */
|
|
||||||
volcFailureCodeWithHint(code) {
|
|
||||||
const c = String(code || "").trim();
|
|
||||||
if (!c) return "";
|
|
||||||
const hint = this.volcTaskErrorHintForCode(c);
|
|
||||||
return hint ? `${c}(${hint})` : c;
|
|
||||||
},
|
|
||||||
/** result 为火山回调失败写入的 VideoTaskError JSON 时解析为 { code, message } */
|
|
||||||
parseVolcTaskErrorJson(str) {
|
|
||||||
const s = String(str || "").trim();
|
|
||||||
if (!s || s[0] !== "{") return null;
|
|
||||||
try {
|
|
||||||
const o = JSON.parse(s);
|
|
||||||
if (
|
|
||||||
o &&
|
|
||||||
typeof o === "object" &&
|
|
||||||
!Array.isArray(o) &&
|
|
||||||
("code" in o || "message" in o)
|
|
||||||
) {
|
|
||||||
return {
|
|
||||||
code: o.code != null ? String(o.code) : "",
|
|
||||||
message: o.message != null ? String(o.message) : ""
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (_) {
|
|
||||||
/* ignore */
|
|
||||||
}
|
}
|
||||||
return null;
|
return {
|
||||||
},
|
id: node.id,
|
||||||
// 判断是否为图片结果(与 portal-ui GeneratedAssets 一致)
|
label: node.label,
|
||||||
isImage(url) {
|
children: node.children
|
||||||
const value = String(url || "").trim();
|
|
||||||
if (!value) return false;
|
|
||||||
return /\.(jpeg|jpg|png|gif|webp|bmp)(\?.*)?$/i.test(value);
|
|
||||||
},
|
|
||||||
// 判断是否为视频结果(与 portal-ui VideoGen/GeneratedAssets 一致)
|
|
||||||
isVideo(url) {
|
|
||||||
const value = String(url || "").trim();
|
|
||||||
if (!value) return false;
|
|
||||||
return /\.(mp4|mov|webm|ogg|m4v|avi|mkv)(\?.*)?$/i.test(value);
|
|
||||||
},
|
|
||||||
// 查看图片
|
|
||||||
viewImage(url) {
|
|
||||||
this.previewImageUrl = url;
|
|
||||||
this.imageDialogVisible = true;
|
|
||||||
},
|
|
||||||
// 播放视频
|
|
||||||
playVideo(url) {
|
|
||||||
this.previewVideoUrl = url;
|
|
||||||
this.videoDialogVisible = true;
|
|
||||||
},
|
|
||||||
// 非链接内容点击事件
|
|
||||||
async handleOtherEvent(row) {
|
|
||||||
if (this.parseVolcTaskErrorJson(row.result)) return;
|
|
||||||
// 防止重复点击
|
|
||||||
if (row.isDownloading) return;
|
|
||||||
const originalResult = row.result;
|
|
||||||
try {
|
|
||||||
// 标记为下载中状态
|
|
||||||
row.isDownloading = true;
|
|
||||||
// 保存原始内容
|
|
||||||
|
|
||||||
// 修改显示内容为“下载中...”
|
|
||||||
row.result = "下载中...";
|
|
||||||
|
|
||||||
// 执行下载操作
|
|
||||||
const resultId = originalResult; // 假设result存储的是ID
|
|
||||||
var res = await downloadVideo(resultId);
|
|
||||||
if (res.status === "succeeded") {
|
|
||||||
row.result = res.content.video_url;
|
|
||||||
} else {
|
|
||||||
row.result = "视频生成中"
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('下载失败:', error);
|
|
||||||
// 失败后恢复原始内容
|
|
||||||
row.result = originalResult || row.result.replace("下载中...", "");
|
|
||||||
this.$message.error('下载失败,请重试');
|
|
||||||
} finally {
|
|
||||||
// 重置下载状态
|
|
||||||
row.isDownloading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
formatStatus(row) {
|
|
||||||
// 如果有匹配的类型则显示对应文字,否则显示"未知"
|
|
||||||
return this.statusMap[row.status] || "未知";
|
|
||||||
},
|
|
||||||
/** 查询订单管理列表 */
|
|
||||||
getList() {
|
getList() {
|
||||||
this.loading = true;
|
this.loading = true
|
||||||
listOrder(this.addDateRange(this.queryParams, this.dateRange)).then(
|
listOrder(this.queryParams).then(response => {
|
||||||
response => {
|
this.orderList = response.rows
|
||||||
this.orderList = response.rows;
|
this.total = response.total
|
||||||
this.total = response.total;
|
this.loading = false
|
||||||
this.loading = false;
|
})
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
// 取消按钮
|
|
||||||
cancel() {
|
cancel() {
|
||||||
this.open = false;
|
this.open = false
|
||||||
this.reset();
|
this.reset()
|
||||||
},
|
},
|
||||||
// 表单重置
|
|
||||||
reset() {
|
reset() {
|
||||||
this.form = {
|
this.form = {
|
||||||
id: null,
|
id: null,
|
||||||
delFlag: null,
|
deptId: undefined,
|
||||||
createBy: null,
|
orderType: 0,
|
||||||
createTime: null,
|
money: undefined,
|
||||||
updateBy: null,
|
amount: undefined,
|
||||||
updateTime: null,
|
remark: undefined,
|
||||||
remark: null,
|
status: 1,
|
||||||
orderNum: null,
|
orderNum: undefined
|
||||||
userId: null,
|
}
|
||||||
type: null,
|
this.resetForm("form")
|
||||||
amount: null,
|
|
||||||
result: null,
|
|
||||||
status: null
|
|
||||||
};
|
|
||||||
this.resetForm("form");
|
|
||||||
},
|
},
|
||||||
/** 搜索按钮操作 */
|
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
this.queryParams.pageNum = 1;
|
this.queryParams.pageNum = 1
|
||||||
this.getList();
|
this.getList()
|
||||||
},
|
},
|
||||||
/** 重置按钮操作 */
|
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.dateRange = [];
|
this.resetForm("queryForm")
|
||||||
this.resetForm("queryForm");
|
this.handleQuery()
|
||||||
this.handleQuery();
|
|
||||||
},
|
},
|
||||||
// 多选框选中数据
|
|
||||||
handleSelectionChange(selection) {
|
handleSelectionChange(selection) {
|
||||||
this.ids = selection.map(item => item.id);
|
this.ids = selection.map(item => item.id)
|
||||||
this.single = selection.length !== 1;
|
this.single = selection.length !== 1
|
||||||
this.multiple = !selection.length;
|
this.multiple = !selection.length
|
||||||
},
|
},
|
||||||
/** 新增按钮操作 */
|
|
||||||
handleAdd() {
|
handleAdd() {
|
||||||
this.reset();
|
this.reset()
|
||||||
this.open = true;
|
this.open = true
|
||||||
this.title = "添加订单管理";
|
this.title = "新增团队订单"
|
||||||
},
|
},
|
||||||
/** 修改按钮操作 */
|
|
||||||
handleUpdate(row) {
|
handleUpdate(row) {
|
||||||
this.reset();
|
this.reset()
|
||||||
const id = row.id || this.ids;
|
const id = row.id || this.ids[0]
|
||||||
getOrder(id).then(response => {
|
getOrder(id).then(response => {
|
||||||
this.form = response.data;
|
this.form = response.data
|
||||||
this.open = true;
|
this.open = true
|
||||||
this.title = "修改订单管理";
|
this.title = "修改团队订单"
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
/** 提交按钮 */
|
|
||||||
submitForm() {
|
submitForm() {
|
||||||
this.$refs["form"].validate(valid => {
|
this.$refs["form"].validate(valid => {
|
||||||
if (valid) {
|
if (!valid) {
|
||||||
if (this.form.id != null) {
|
return
|
||||||
updateOrder(this.form).then(response => {
|
|
||||||
this.$modal.msgSuccess("修改成功");
|
|
||||||
this.open = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
addOrder(this.form).then(response => {
|
|
||||||
this.$modal.msgSuccess("新增成功");
|
|
||||||
this.open = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
const payload = { ...this.form }
|
||||||
|
if (payload.id == null) {
|
||||||
|
addOrder(payload).then(() => {
|
||||||
|
this.$modal.msgSuccess("新增成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
updateOrder(payload).then(() => {
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
/** 删除按钮操作 */
|
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
const ids = row.id || this.ids;
|
const ids = row.id || this.ids
|
||||||
this.$modal
|
this.$modal.confirm("是否确认删除所选团队订单?").then(() => delOrder(ids)).then(() => {
|
||||||
.confirm('是否确认删除订单管理编号为"' + ids + '"的数据项?')
|
this.getList()
|
||||||
.then(function() {
|
this.$modal.msgSuccess("删除成功")
|
||||||
return delOrder(ids);
|
}).catch(() => {})
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
this.getList();
|
|
||||||
this.$modal.msgSuccess("删除成功");
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
|
||||||
handleExport() {
|
handleExport() {
|
||||||
this.download(
|
this.download("ai/order/export", { ...this.queryParams }, `team_orders_${new Date().getTime()}.xlsx`)
|
||||||
"ai/order/export",
|
|
||||||
{
|
|
||||||
...this.queryParams
|
|
||||||
},
|
|
||||||
`order_${new Date().getTime()}.xlsx`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
.dialog-video {
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-img {
|
|
||||||
width: 80px;
|
|
||||||
height: 60px;
|
|
||||||
object-fit: cover;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-video {
|
|
||||||
width: 120px;
|
|
||||||
height: 80px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-img {
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-result-error-wrap {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-result-error-compact {
|
|
||||||
display: inline-block;
|
|
||||||
max-width: 200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 1.35;
|
|
||||||
color: #c45656;
|
|
||||||
cursor: help;
|
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-result-error-tooltip-body {
|
|
||||||
max-width: 420px;
|
|
||||||
text-align: left;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-result-error-tooltip-row {
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-result-error-tooltip-row:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-result-error-tooltip-row--msg .order-result-error-tooltip-v {
|
|
||||||
display: block;
|
|
||||||
margin-top: 2px;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-result-error-tooltip-k {
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fde2e2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-result-error-tooltip-v {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-ellipsis-two-lines {
|
|
||||||
/* 必须设置宽度(继承表格列宽,也可手动指定) */
|
|
||||||
width: 100%;
|
|
||||||
/* 核心属性:多行文本溢出隐藏 */
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
-webkit-line-clamp: 2; /* 显示2行 */
|
|
||||||
line-clamp: 2; /* 标准属性,兼容现代浏览器 */
|
|
||||||
overflow: hidden;
|
|
||||||
/* 可选:调整行高,优化显示 */
|
|
||||||
line-height: 1.5;
|
|
||||||
max-height: 3em; /* 行高1.5 × 2行 = 3em,防止高度溢出 */
|
|
||||||
/* 可选:文本对齐 */
|
|
||||||
text-align: center;
|
|
||||||
/* 解决scoped样式穿透(如果需要) */
|
|
||||||
/deep/ & {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 0 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,312 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
|
<el-form-item label="订单号" prop="relationOrderNo">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.relationOrderNo"
|
||||||
|
placeholder="请输入关联(充值/退款)订单号"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="部门ID" prop="deptId">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.deptId"
|
||||||
|
placeholder="请输入部门ID"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="变更金额" prop="changeAmount">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.changeAmount"
|
||||||
|
placeholder="请输入变更金额"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="变更后金额" prop="resultAmount">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.resultAmount"
|
||||||
|
placeholder="请输入变更后金额"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<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-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['ai:record:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
icon="el-icon-edit"
|
||||||
|
size="mini"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUpdate"
|
||||||
|
v-hasPermi="['ai:record:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="el-icon-delete"
|
||||||
|
size="mini"
|
||||||
|
:disabled="multiple"
|
||||||
|
@click="handleDelete"
|
||||||
|
v-hasPermi="['ai:record:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="el-icon-download"
|
||||||
|
size="mini"
|
||||||
|
@click="handleExport"
|
||||||
|
v-hasPermi="['ai:record:export']"
|
||||||
|
>导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="recordList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="ID" align="center" prop="id" />
|
||||||
|
<el-table-column label="订单号" align="center" prop="relationOrderNo" />
|
||||||
|
<el-table-column label="部门ID" align="center" prop="deptId" />
|
||||||
|
<el-table-column label="操作类型" align="center" prop="type" />
|
||||||
|
<el-table-column label="变更金额" align="center" prop="changeAmount" />
|
||||||
|
<el-table-column label="变更后金额" align="center" prop="resultAmount" />
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" />
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['ai:record:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
v-hasPermi="['ai:record:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total>0"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="queryParams.pageNum"
|
||||||
|
:limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加或修改团队(部门)余额变动对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="订单号" prop="relationOrderNo">
|
||||||
|
<el-input v-model="form.relationOrderNo" placeholder="请输入关联(充值/退款)订单号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="部门ID" prop="deptId">
|
||||||
|
<el-input v-model="form.deptId" placeholder="请输入部门ID" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="变更金额" prop="changeAmount">
|
||||||
|
<el-input v-model="form.changeAmount" placeholder="请输入变更金额" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="变更后金额" prop="resultAmount">
|
||||||
|
<el-input v-model="form.resultAmount" placeholder="请输入变更后金额" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listRecord, getRecord, delRecord, addRecord, updateRecord } from "@/api/ai/record"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Record",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 选中数组
|
||||||
|
ids: [],
|
||||||
|
// 非单个禁用
|
||||||
|
single: true,
|
||||||
|
// 非多个禁用
|
||||||
|
multiple: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 团队(部门)余额变动表格数据
|
||||||
|
recordList: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
relationOrderNo: null,
|
||||||
|
deptId: null,
|
||||||
|
type: null,
|
||||||
|
changeAmount: null,
|
||||||
|
resultAmount: null,
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
deptId: [
|
||||||
|
{ required: true, message: "部门ID不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
type: [
|
||||||
|
{ required: true, message: "操作类型不能为空", trigger: "change" }
|
||||||
|
],
|
||||||
|
changeAmount: [
|
||||||
|
{ required: true, message: "变更金额不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
resultAmount: [
|
||||||
|
{ required: true, message: "变更后金额不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
createTime: [
|
||||||
|
{ required: true, message: "创建时间不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 查询团队(部门)余额变动列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listRecord(this.queryParams).then(response => {
|
||||||
|
this.recordList = response.rows
|
||||||
|
this.total = response.total
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
id: null,
|
||||||
|
relationOrderNo: null,
|
||||||
|
deptId: null,
|
||||||
|
type: null,
|
||||||
|
changeAmount: null,
|
||||||
|
resultAmount: null,
|
||||||
|
remark: null,
|
||||||
|
createTime: null,
|
||||||
|
updateTime: null
|
||||||
|
}
|
||||||
|
this.resetForm("form")
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
// 多选框选中数据
|
||||||
|
handleSelectionChange(selection) {
|
||||||
|
this.ids = selection.map(item => item.id)
|
||||||
|
this.single = selection.length!==1
|
||||||
|
this.multiple = !selection.length
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset()
|
||||||
|
this.open = true
|
||||||
|
this.title = "添加团队(部门)余额变动"
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset()
|
||||||
|
const id = row.id || this.ids
|
||||||
|
getRecord(id).then(response => {
|
||||||
|
this.form = response.data
|
||||||
|
this.open = true
|
||||||
|
this.title = "修改团队(部门)余额变动"
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.form.id != null) {
|
||||||
|
updateRecord(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
addRecord(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("新增成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const ids = row.id || this.ids
|
||||||
|
this.$modal.confirm('是否确认删除团队(部门)余额变动编号为"' + ids + '"的数据项?').then(function() {
|
||||||
|
return delRecord(ids)
|
||||||
|
}).then(() => {
|
||||||
|
this.getList()
|
||||||
|
this.$modal.msgSuccess("删除成功")
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
this.download('ai/record/export', {
|
||||||
|
...this.queryParams
|
||||||
|
}, `record_${new Date().getTime()}.xlsx`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true" label-width="88px">
|
||||||
|
<el-form-item label="类型" prop="orderType">
|
||||||
|
<el-select v-model="queryParams.orderType" clearable placeholder="全部">
|
||||||
|
<el-option label="充值" :value="0" /><el-option label="退款" :value="1" /><el-option label="手动修改" :value="2" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="订单编号" prop="orderNum">
|
||||||
|
<el-input v-model="queryParams.orderNum" clearable @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<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-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-row class="mb8"><right-toolbar :show-search.sync="showSearch" @queryTable="getList" /></el-row>
|
||||||
|
<el-table v-loading="loading" :data="list">
|
||||||
|
<el-table-column label="ID" prop="id" width="70" />
|
||||||
|
<el-table-column label="团队" prop="deptName" min-width="100" show-overflow-tooltip />
|
||||||
|
<el-table-column label="类型" width="90">
|
||||||
|
<template slot-scope="s">{{ typeLabel(s.row.orderType) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="金额" prop="money" width="90" />
|
||||||
|
<el-table-column label="积分" prop="amount" width="90" />
|
||||||
|
<el-table-column label="时间" width="160"><template slot-scope="s">{{ parseTime(s.row.createTime) }}</template></el-table-column>
|
||||||
|
<el-table-column label="备注" prop="remark" min-width="120" show-overflow-tooltip />
|
||||||
|
</el-table>
|
||||||
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listSubteamChargeOrder } from '@/api/subteam'
|
||||||
|
export default {
|
||||||
|
name: 'SubteamChargeOrder',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
showSearch: true,
|
||||||
|
list: [],
|
||||||
|
total: 0,
|
||||||
|
queryParams: { pageNum: 1, pageSize: 10, orderType: undefined, orderNum: undefined }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() { this.getList() },
|
||||||
|
methods: {
|
||||||
|
typeLabel(t) {
|
||||||
|
const m = { 0: '充值', 1: '退款', 2: '手动修改' }
|
||||||
|
return m[t] != null ? m[t] : '—'
|
||||||
|
},
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listSubteamChargeOrder(this.queryParams).then(res => {
|
||||||
|
this.list = res.rows
|
||||||
|
this.total = res.total
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleQuery() { this.queryParams.pageNum = 1; this.getList() },
|
||||||
|
resetQuery() { this.resetForm('queryForm'); this.handleQuery() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form ref="queryForm" :model="queryParams" size="small" :inline="true" label-width="96px">
|
||||||
|
<el-form-item label="统计日期" prop="statDate">
|
||||||
|
<el-date-picker v-model="queryParams.statDate" type="date" value-format="yyyyMMdd" placeholder="请选择日期" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<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-form-item>
|
||||||
|
</el-form>
|
||||||
|
<p class="tip">仅展示当前团队数据;请选择日期后查询。</p>
|
||||||
|
<el-table v-loading="loading" :data="list">
|
||||||
|
<el-table-column label="日期" prop="dateKey" />
|
||||||
|
<el-table-column label="团队" prop="deptName" />
|
||||||
|
<el-table-column label="充值积分" prop="rechargeScore" />
|
||||||
|
<el-table-column label="消耗积分" prop="score" />
|
||||||
|
<el-table-column label="成功订单" prop="orderCount" />
|
||||||
|
<el-table-column label="Tokens" prop="useTokens" />
|
||||||
|
</el-table>
|
||||||
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listSubteamConsumeStat } from '@/api/subteam'
|
||||||
|
export default {
|
||||||
|
name: 'SubteamConsumeStat',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
list: [],
|
||||||
|
total: 0,
|
||||||
|
queryParams: { pageNum: 1, pageSize: 10, statDate: null }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getList() {
|
||||||
|
if (!this.queryParams.statDate) {
|
||||||
|
this.list = []
|
||||||
|
this.total = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.loading = true
|
||||||
|
listSubteamConsumeStat(this.queryParams).then(res => {
|
||||||
|
this.list = res.rows
|
||||||
|
this.total = res.total
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm('queryForm')
|
||||||
|
this.list = []
|
||||||
|
this.total = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.tip { color: #909399; font-size: 13px; margin-bottom: 12px; }
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true">
|
||||||
|
<el-form-item label="类型" prop="type">
|
||||||
|
<el-input v-model="queryParams.type" clearable placeholder="0-4" @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="关联单号" prop="relationOrderNo">
|
||||||
|
<el-input v-model="queryParams.relationOrderNo" clearable @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<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-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-row class="mb8"><right-toolbar :show-search.sync="showSearch" @queryTable="getList" /></el-row>
|
||||||
|
<el-table v-loading="loading" :data="list">
|
||||||
|
<el-table-column label="ID" prop="id" width="80" />
|
||||||
|
<el-table-column label="关联单号" prop="relationOrderNo" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column label="类型" prop="type" width="80" />
|
||||||
|
<el-table-column label="变更金额" prop="changeAmount" width="100" />
|
||||||
|
<el-table-column label="变更后" prop="resultAmount" width="100" />
|
||||||
|
<el-table-column label="时间" width="160"><template slot-scope="s">{{ parseTime(s.row.createTime) }}</template></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listSubteamGroupBalance } from '@/api/subteam'
|
||||||
|
export default {
|
||||||
|
name: 'SubteamGroupBalance',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
showSearch: true,
|
||||||
|
list: [],
|
||||||
|
total: 0,
|
||||||
|
queryParams: { pageNum: 1, pageSize: 10, type: undefined, relationOrderNo: undefined }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() { this.getList() },
|
||||||
|
methods: {
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listSubteamGroupBalance(this.queryParams).then(res => {
|
||||||
|
this.list = res.rows
|
||||||
|
this.total = res.total
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleQuery() { this.queryParams.pageNum = 1; this.getList() },
|
||||||
|
resetQuery() { this.resetForm('queryForm'); this.handleQuery() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-row :gutter="16" v-loading="loading">
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card shadow="hover"><div class="metric-title">团队 ID</div><div class="metric-val">{{ info.deptId }}</div></el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card shadow="hover"><div class="metric-title">团队名称</div><div class="metric-val">{{ info.deptName }}</div></el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card shadow="hover"><div class="metric-title">积分余额(部门)</div><div class="metric-val">{{ info.balance }}</div></el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16" style="margin-top:16px">
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card shadow="hover"><div class="metric-title">AI用户数(实时)</div><div class="metric-val">{{ info.aiUserCount }}</div></el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card shadow="hover"><div class="metric-title">近 7 日消耗积分 <span class="hint">(5 分钟缓存)</span></div><div class="metric-val">{{ info.last7DaysConsumeScore }}</div></el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card shadow="hover"><div class="metric-title">近 7 日成功订单数 <span class="hint">(5 分钟缓存)</span></div><div class="metric-val">{{ info.last7DaysOrderCount }}</div></el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getSubteamOverview } from '@/api/subteam'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SubteamOverview',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
info: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.load()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
load() {
|
||||||
|
this.loading = true
|
||||||
|
getSubteamOverview().then(res => {
|
||||||
|
this.info = res.data || {}
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.metric-title { color: #909399; font-size: 13px; }
|
||||||
|
.metric-val { font-size: 22px; margin-top: 8px; font-weight: 600; }
|
||||||
|
.hint { font-size: 12px; color: #909399; }
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,300 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true">
|
||||||
|
<el-form-item label="账号" prop="username">
|
||||||
|
<el-input v-model="queryParams.username" placeholder="账号" clearable @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机号" prop="phone">
|
||||||
|
<el-input v-model="queryParams.phone" placeholder="手机号" clearable @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="status">
|
||||||
|
<el-select v-model="queryParams.status" placeholder="状态" clearable>
|
||||||
|
<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" size="mini" @click="handleQuery">搜索</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 v-hasPermi="['subteam:user:add']" type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button v-hasPermi="['subteam:user:edit']" type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate">修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button v-hasPermi="['subteam:user:remove']" type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :show-search.sync="showSearch" @queryTable="getList" />
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="50" />
|
||||||
|
<el-table-column label="主键ID" prop="id" width="80" />
|
||||||
|
<el-table-column label="账号" prop="username" />
|
||||||
|
<el-table-column label="昵称" prop="nickname" />
|
||||||
|
<el-table-column label="部门" prop="deptName" />
|
||||||
|
<el-table-column label="手机" prop="phone" width="120" />
|
||||||
|
<el-table-column label="状态" width="80">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<dict-tag :options="dict.type.sys_normal_disable" :value="String(scope.row.status)" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="320">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-download"
|
||||||
|
@click="openDeptScoreDialog(scope.row, 'issue')"
|
||||||
|
v-hasPermi="['ai:user:deptScoreIssue']"
|
||||||
|
>下放积分</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-upload2"
|
||||||
|
@click="openDeptScoreDialog(scope.row, 'reclaim')"
|
||||||
|
v-hasPermi="['ai:user:deptScoreReclaim']"
|
||||||
|
>回收积分</el-button>
|
||||||
|
<el-button v-hasPermi="['subteam:user:edit']" size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||||
|
<el-button v-hasPermi="['subteam:user:resetPwd']" size="mini" type="text" icon="el-icon-key" @click="handleResetPwd(scope.row)">密码</el-button>
|
||||||
|
<el-button v-hasPermi="['subteam:user:remove']" size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||||
|
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="640px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="88px">
|
||||||
|
<el-form-item label="昵称" prop="nickname"><el-input v-model="form.nickname" /></el-form-item>
|
||||||
|
<el-row v-if="!form.id">
|
||||||
|
<el-col :span="12"><el-form-item label="账号" prop="username"><el-input v-model="form.username" /></el-form-item></el-col>
|
||||||
|
<el-col :span="12"><el-form-item label="密码" prop="password"><el-input v-model="form.password" type="password" show-password /></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-form-item label="手机" prop="phone"><el-input v-model="form.phone" /></el-form-item>
|
||||||
|
<el-form-item label="邮箱" prop="email"><el-input v-model="form.email" /></el-form-item>
|
||||||
|
<el-form-item label="状态" prop="status">
|
||||||
|
<el-radio-group v-model="form.status">
|
||||||
|
<el-radio :label="0">正常</el-radio>
|
||||||
|
<el-radio :label="1">停用</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注"><el-input v-model="form.remark" type="textarea" /></el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog
|
||||||
|
:title="deptScoreMode === 'issue' ? '下放积分' : '回收积分'"
|
||||||
|
:visible.sync="deptScoreOpen"
|
||||||
|
width="480px"
|
||||||
|
append-to-body
|
||||||
|
@close="cancelDeptScore"
|
||||||
|
>
|
||||||
|
<el-form ref="deptScoreFormRef" :model="deptScoreForm" :rules="deptScoreRules" label-width="88px">
|
||||||
|
<el-form-item label="用户账号">
|
||||||
|
<span>{{ deptScoreForm.username }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="积分数量" prop="amount">
|
||||||
|
<el-input-number
|
||||||
|
v-model="deptScoreForm.amount"
|
||||||
|
:min="1"
|
||||||
|
:max="100000000"
|
||||||
|
:precision="0"
|
||||||
|
:step="1"
|
||||||
|
controls-position="right"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input
|
||||||
|
v-model="deptScoreForm.remark"
|
||||||
|
type="textarea"
|
||||||
|
:rows="2"
|
||||||
|
maxlength="50"
|
||||||
|
show-word-limit
|
||||||
|
placeholder="选填,最多50字"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitDeptScore">确 定</el-button>
|
||||||
|
<el-button @click="cancelDeptScore">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
listSubteamUser, getSubteamUser, addSubteamUser, updateSubteamUser, delSubteamUser,
|
||||||
|
resetSubteamUserPwd
|
||||||
|
} from '@/api/subteam'
|
||||||
|
import { issueDeptScore, reclaimDeptScore } from '@/api/ai/user'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SubteamUser',
|
||||||
|
dicts: ['sys_normal_disable'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
showSearch: true,
|
||||||
|
userList: [],
|
||||||
|
total: 0,
|
||||||
|
ids: [],
|
||||||
|
single: true,
|
||||||
|
multiple: true,
|
||||||
|
title: '',
|
||||||
|
open: false,
|
||||||
|
deptScoreOpen: false,
|
||||||
|
deptScoreMode: 'issue',
|
||||||
|
deptScoreForm: {
|
||||||
|
userId: null,
|
||||||
|
username: '',
|
||||||
|
amount: undefined,
|
||||||
|
remark: ''
|
||||||
|
},
|
||||||
|
deptScoreRules: {
|
||||||
|
amount: [
|
||||||
|
{ required: true, message: '请输入积分数量', trigger: 'blur' },
|
||||||
|
{
|
||||||
|
type: 'number',
|
||||||
|
min: 1,
|
||||||
|
max: 100000000,
|
||||||
|
message: '请输入 1~100000000 的整数',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
remark: [{ max: 50, message: '备注最多50个字', trigger: 'blur' }]
|
||||||
|
},
|
||||||
|
queryParams: { pageNum: 1, pageSize: 10, username: undefined, phone: undefined, status: undefined },
|
||||||
|
form: {},
|
||||||
|
rules: {
|
||||||
|
nickname: [{ required: true, message: '必填', trigger: 'blur' }],
|
||||||
|
username: [{ required: true, message: '必填', trigger: 'blur' }],
|
||||||
|
password: [{ required: true, message: '必填', trigger: 'blur' }],
|
||||||
|
email: [{ type: 'email', message: '邮箱格式', trigger: ['blur', 'change'] }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listSubteamUser(this.queryParams).then(res => {
|
||||||
|
this.userList = res.rows
|
||||||
|
this.total = res.total
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm('queryForm')
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
handleSelectionChange(rows) {
|
||||||
|
this.ids = rows.map(r => r.id)
|
||||||
|
this.single = rows.length !== 1
|
||||||
|
this.multiple = !rows.length
|
||||||
|
},
|
||||||
|
reset() {
|
||||||
|
this.form = { id: undefined, username: undefined, nickname: undefined, password: undefined,
|
||||||
|
phone: undefined, email: undefined, status: 0, remark: undefined }
|
||||||
|
this.resetForm('form')
|
||||||
|
},
|
||||||
|
handleAdd() {
|
||||||
|
this.reset()
|
||||||
|
this.open = true
|
||||||
|
this.title = '新增AI用户'
|
||||||
|
},
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset()
|
||||||
|
const id = row.id || this.ids[0]
|
||||||
|
getSubteamUser(id).then(r => {
|
||||||
|
this.form = r.data || {}
|
||||||
|
this.form.status = Number(this.form.status || 0)
|
||||||
|
this.open = true
|
||||||
|
this.title = '修改AI用户'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
submitForm() {
|
||||||
|
this.$refs.form.validate(valid => {
|
||||||
|
if (!valid) return
|
||||||
|
if (this.form.id) {
|
||||||
|
updateSubteamUser(this.form).then(() => { this.$modal.msgSuccess('成功'); this.open = false; this.getList() })
|
||||||
|
} else {
|
||||||
|
addSubteamUser(this.form).then(() => { this.$modal.msgSuccess('成功'); this.open = false; this.getList() })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
cancel() { this.open = false },
|
||||||
|
handleDelete(row) {
|
||||||
|
const userIds = row.id || this.ids
|
||||||
|
this.$modal.confirm('确认删除?').then(() => delSubteamUser(userIds)).then(() => { this.getList(); this.$modal.msgSuccess('已删除') }).catch(() => {})
|
||||||
|
},
|
||||||
|
handleResetPwd(row) {
|
||||||
|
this.$prompt('新密码', '重置', { inputType: 'password' }).then(({ value }) => {
|
||||||
|
resetSubteamUserPwd({ id: row.id, password: value }).then(() => this.$modal.msgSuccess('已重置'))
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
openDeptScoreDialog(row, mode) {
|
||||||
|
if (!row.deptId) {
|
||||||
|
this.$modal.msgWarning('请先分配归属部门后再操作积分')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.deptScoreMode = mode
|
||||||
|
this.deptScoreForm = {
|
||||||
|
userId: row.id,
|
||||||
|
username: row.username || row.userId || '',
|
||||||
|
amount: undefined,
|
||||||
|
remark: ''
|
||||||
|
}
|
||||||
|
this.deptScoreOpen = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.deptScoreFormRef) {
|
||||||
|
this.$refs.deptScoreFormRef.clearValidate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
submitDeptScore() {
|
||||||
|
this.$refs.deptScoreFormRef.validate(valid => {
|
||||||
|
if (!valid) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const raw = this.deptScoreForm.amount
|
||||||
|
const amount = typeof raw === 'number' ? Math.trunc(raw) : parseInt(String(raw), 10)
|
||||||
|
if (!Number.isFinite(amount) || amount < 1 || amount > 100000000) {
|
||||||
|
this.$modal.msgWarning('请输入 1~100000000 的整数积分')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const payload = {
|
||||||
|
userId: this.deptScoreForm.userId,
|
||||||
|
amount,
|
||||||
|
remark: this.deptScoreForm.remark || undefined
|
||||||
|
}
|
||||||
|
const req = this.deptScoreMode === 'issue' ? issueDeptScore : reclaimDeptScore
|
||||||
|
req(payload).then(() => {
|
||||||
|
this.$modal.msgSuccess('操作成功')
|
||||||
|
this.deptScoreOpen = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
cancelDeptScore() {
|
||||||
|
this.deptScoreOpen = false
|
||||||
|
this.deptScoreForm = { userId: null, username: '', amount: undefined, remark: '' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true">
|
||||||
|
<el-form-item label="用户ID" prop="userId">
|
||||||
|
<el-input v-model="queryParams.userId" clearable @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="类型" prop="type">
|
||||||
|
<el-input v-model="queryParams.type" clearable placeholder="类型码" @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<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-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-row class="mb8"><right-toolbar :show-search.sync="showSearch" @queryTable="getList" /></el-row>
|
||||||
|
<el-table v-loading="loading" :data="list">
|
||||||
|
<el-table-column label="ID" prop="id" width="80" />
|
||||||
|
<el-table-column label="用户ID" prop="userId" width="90" />
|
||||||
|
<el-table-column label="账号" prop="nickname" min-width="100" />
|
||||||
|
<el-table-column label="类型" prop="type" width="80" />
|
||||||
|
<el-table-column label="变更" prop="changeAmount" width="100" />
|
||||||
|
<el-table-column label="余额" prop="resultAmount" width="100" />
|
||||||
|
<el-table-column label="时间" width="160"><template slot-scope="s">{{ parseTime(s.row.createTime) }}</template></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listSubteamUserBalance } from '@/api/subteam'
|
||||||
|
export default {
|
||||||
|
name: 'SubteamUserBalance',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
showSearch: true,
|
||||||
|
list: [],
|
||||||
|
total: 0,
|
||||||
|
queryParams: { pageNum: 1, pageSize: 10, userId: undefined, type: undefined }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() { this.getList() },
|
||||||
|
methods: {
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listSubteamUserBalance(this.queryParams).then(res => {
|
||||||
|
this.list = res.rows
|
||||||
|
this.total = res.total
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleQuery() { this.queryParams.pageNum = 1; this.getList() },
|
||||||
|
resetQuery() { this.resetForm('queryForm'); this.handleQuery() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true">
|
||||||
|
<el-form-item label="订单号" prop="orderNum">
|
||||||
|
<el-input v-model="queryParams.orderNum" clearable @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户ID" prop="userId">
|
||||||
|
<el-input v-model="queryParams.userId" clearable @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="status">
|
||||||
|
<el-select v-model="queryParams.status" clearable placeholder="状态">
|
||||||
|
<el-option label="进行中" :value="0" /><el-option label="已完成" :value="1" /><el-option label="失败" :value="2" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<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-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-row class="mb8"><right-toolbar :show-search.sync="showSearch" @queryTable="getList" /></el-row>
|
||||||
|
<el-table v-loading="loading" :data="list">
|
||||||
|
<el-table-column label="ID" prop="id" width="70" />
|
||||||
|
<el-table-column label="订单号" prop="orderNum" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column label="用户ID" prop="userId" width="90" />
|
||||||
|
<el-table-column label="金额" prop="amount" width="90" />
|
||||||
|
<el-table-column label="状态" prop="status" width="80" />
|
||||||
|
<el-table-column label="结果预览" min-width="220">
|
||||||
|
<template slot-scope="s">
|
||||||
|
<div v-if="extractVideoUrl(s.row.result)">
|
||||||
|
<video
|
||||||
|
:src="extractVideoUrl(s.row.result)"
|
||||||
|
controls
|
||||||
|
preload="metadata"
|
||||||
|
style="width: 180px; max-height: 100px; border-radius: 4px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间" prop="createTime" width="160"><template slot-scope="s">{{ parseTime(s.row.createTime) }}</template></el-table-column>
|
||||||
|
<el-table-column label="操作" width="90" fixed="right">
|
||||||
|
<template slot-scope="s">
|
||||||
|
<el-button type="text" size="mini" @click="handleDetail(s.row)">详情</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||||
|
|
||||||
|
<el-dialog title="订单详情" :visible.sync="detailVisible" width="720px" append-to-body>
|
||||||
|
<el-descriptions :column="1" border size="small">
|
||||||
|
<el-descriptions-item v-for="(value, key) in detailData" :key="key" :label="key">
|
||||||
|
<pre v-if="isObjectValue(value)" style="margin: 0; white-space: pre-wrap;">{{ formatJson(value) }}</pre>
|
||||||
|
<span v-else>{{ value === null || value === undefined || value === '' ? '-' : value }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
<span slot="footer">
|
||||||
|
<el-button size="mini" @click="detailVisible = false">关闭</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listSubteamVideoOrder } from '@/api/subteam'
|
||||||
|
export default {
|
||||||
|
name: 'SubteamVideoOrder',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
showSearch: true,
|
||||||
|
list: [],
|
||||||
|
total: 0,
|
||||||
|
detailVisible: false,
|
||||||
|
detailData: {},
|
||||||
|
queryParams: { pageNum: 1, pageSize: 10, orderNum: undefined, userId: undefined, status: undefined }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() { this.getList() },
|
||||||
|
methods: {
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listSubteamVideoOrder(this.queryParams).then(res => {
|
||||||
|
this.list = res.rows
|
||||||
|
this.total = res.total
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
extractVideoUrl(result) {
|
||||||
|
if (!result) return ''
|
||||||
|
if (typeof result === 'string') {
|
||||||
|
const value = result.trim()
|
||||||
|
if (!value) return ''
|
||||||
|
if (/^https?:\/\/|^\/\//.test(value)) return value
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(value)
|
||||||
|
return this.extractVideoUrl(parsed)
|
||||||
|
} catch (e) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Array.isArray(result)) {
|
||||||
|
for (let i = 0; i < result.length; i += 1) {
|
||||||
|
const url = this.extractVideoUrl(result[i])
|
||||||
|
if (url) return url
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
if (typeof result === 'object') {
|
||||||
|
const directKeys = ['videoUrl', 'url', 'resultUrl', 'playUrl', 'output', 'fileUrl']
|
||||||
|
for (let i = 0; i < directKeys.length; i += 1) {
|
||||||
|
const key = directKeys[i]
|
||||||
|
if (result[key]) {
|
||||||
|
const url = this.extractVideoUrl(result[key])
|
||||||
|
if (url) return url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
handleDetail(row) {
|
||||||
|
this.detailData = row || {}
|
||||||
|
this.detailVisible = true
|
||||||
|
},
|
||||||
|
isObjectValue(value) {
|
||||||
|
return value !== null && typeof value === 'object'
|
||||||
|
},
|
||||||
|
formatJson(value) {
|
||||||
|
try {
|
||||||
|
return JSON.stringify(value, null, 2)
|
||||||
|
} catch (e) {
|
||||||
|
return String(value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleQuery() { this.queryParams.pageNum = 1; this.getList() },
|
||||||
|
resetQuery() { this.resetForm('queryForm'); this.handleQuery() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -26,16 +26,6 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
icon="el-icon-plus"
|
|
||||||
size="mini"
|
|
||||||
@click="handleAdd"
|
|
||||||
v-hasPermi="['system:dept:add']"
|
|
||||||
>新增</el-button>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
type="info"
|
type="info"
|
||||||
|
|
@ -57,10 +47,10 @@
|
||||||
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
||||||
>
|
>
|
||||||
<el-table-column prop="deptName" label="部门名称" width="260"></el-table-column>
|
<el-table-column prop="deptName" label="部门名称" width="260"></el-table-column>
|
||||||
<el-table-column prop="orderNum" label="排序" width="80"></el-table-column>
|
<el-table-column prop="orderNum" label="排序" width="200"></el-table-column>
|
||||||
<el-table-column prop="balance" label="剩余积分" width="200" align="right">
|
<el-table-column prop="maxUserCount" label="账号上限" width="100" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ scope.row.balance != null ? scope.row.balance : '—' }}</span>
|
<span>{{ scope.row.maxUserCount != null && scope.row.maxUserCount > 0 ? scope.row.maxUserCount : '不限制' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="status" label="状态" width="100">
|
<el-table-column prop="status" label="状态" width="100">
|
||||||
|
|
@ -68,20 +58,13 @@
|
||||||
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
|
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="150">
|
<el-table-column label="创建时间" align="center" prop="createTime" width="200">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-plus"
|
|
||||||
@click="handleAdd(scope.row)"
|
|
||||||
v-hasPermi="['system:dept:add']"
|
|
||||||
>新增</el-button>
|
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -89,6 +72,14 @@
|
||||||
@click="handleUpdate(scope.row)"
|
@click="handleUpdate(scope.row)"
|
||||||
v-hasPermi="['system:dept:edit']"
|
v-hasPermi="['system:dept:edit']"
|
||||||
>修改</el-button>
|
>修改</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
@click="handleAdd(scope.row)"
|
||||||
|
v-if="isFirstLevelRow(scope.row)"
|
||||||
|
v-hasPermi="['system:dept:add']"
|
||||||
|
>新增</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="scope.row.parentId != 0"
|
v-if="scope.row.parentId != 0"
|
||||||
size="mini"
|
size="mini"
|
||||||
|
|
@ -97,20 +88,6 @@
|
||||||
@click="handleDelete(scope.row)"
|
@click="handleDelete(scope.row)"
|
||||||
v-hasPermi="['system:dept:remove']"
|
v-hasPermi="['system:dept:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
<el-button
|
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-wallet"
|
|
||||||
@click="handleChargeRefund(scope.row)"
|
|
||||||
v-hasPermi="['system:dept:chargeRefund']"
|
|
||||||
>充值/退款</el-button>
|
|
||||||
<el-button
|
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-s-operation"
|
|
||||||
@click="handleEditScore(scope.row)"
|
|
||||||
v-hasPermi="['system:dept:chargeRefund']"
|
|
||||||
>积分更正</el-button>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
@ -133,31 +110,31 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="显示排序" prop="orderNum">
|
<el-form-item label="显示排序" prop="orderNum">
|
||||||
<el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
|
<el-input-number v-model="form.orderNum" controls-position="right" :min="0" :disabled="isFirstLevelEditForm" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="负责人" prop="leader">
|
<el-form-item label="负责人" prop="leader">
|
||||||
<el-input v-model="form.leader" placeholder="请输入负责人" maxlength="20" />
|
<el-input v-model="form.leader" placeholder="请输入负责人" maxlength="20" :disabled="isFirstLevelEditForm" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="联系电话" prop="phone">
|
<el-form-item label="联系电话" prop="phone">
|
||||||
<el-input v-model="form.phone" placeholder="请输入联系电话" maxlength="11" />
|
<el-input v-model="form.phone" placeholder="请输入联系电话" maxlength="11" :disabled="isFirstLevelEditForm" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="邮箱" prop="email">
|
<el-form-item label="邮箱" prop="email">
|
||||||
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
|
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" :disabled="isFirstLevelEditForm" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="部门状态">
|
<el-form-item label="部门状态">
|
||||||
<el-radio-group v-model="form.status">
|
<el-radio-group v-model="form.status" :disabled="isFirstLevelEditForm">
|
||||||
<el-radio
|
<el-radio
|
||||||
v-for="dict in dict.type.sys_normal_disable"
|
v-for="dict in dict.type.sys_normal_disable"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
|
|
@ -167,6 +144,25 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="账号上限" prop="maxUserCount">
|
||||||
|
<el-input-number
|
||||||
|
v-model="form.maxUserCount"
|
||||||
|
:min="0"
|
||||||
|
:max="999999"
|
||||||
|
:precision="0"
|
||||||
|
controls-position="right"
|
||||||
|
placeholder="0=不限制"
|
||||||
|
style="width: 100%"
|
||||||
|
:disabled="isFirstLevelEditForm"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<p class="model-parm-hint" style="margin: 0; padding-top: 8px">限制本部门下「启用」状态账号数量;0 或不填表示不限制。</p>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
<el-row v-if="isSecondLevelCompanyForm">
|
<el-row v-if="isSecondLevelCompanyForm">
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="Byte API Key">
|
<el-form-item label="Byte API Key">
|
||||||
|
|
@ -230,95 +226,11 @@
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<span v-if="isFirstLevelEditForm" class="form-tip">一级部门仅允许修改名称</span>
|
||||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
<el-button @click="cancel">取 消</el-button>
|
<el-button @click="cancel">取 消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog
|
|
||||||
:title="'充值/退款 — ' + (chargeRefundForm.deptName || '')"
|
|
||||||
:visible.sync="chargeRefundOpen"
|
|
||||||
width="520px"
|
|
||||||
append-to-body
|
|
||||||
@close="resetChargeRefund"
|
|
||||||
>
|
|
||||||
<el-form ref="chargeRefundFormRef" :model="chargeRefundForm" :rules="chargeRefundRules" label-width="88px">
|
|
||||||
<el-form-item label="类型" prop="orderType">
|
|
||||||
<el-radio-group v-model="chargeRefundForm.orderType">
|
|
||||||
<el-radio :label="0">充值</el-radio>
|
|
||||||
<el-radio :label="1">退款</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="金额" prop="money">
|
|
||||||
<el-input
|
|
||||||
:value="chargeRefundMoneyDisplay"
|
|
||||||
placeholder="财务记录(元),如 9,999,999.00"
|
|
||||||
clearable
|
|
||||||
@input="onChargeRefundMoneyInput"
|
|
||||||
@blur="onChargeRefundMoneyBlur"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="积分" prop="amount">
|
|
||||||
<el-input
|
|
||||||
:value="chargeRefundAmountDisplay"
|
|
||||||
placeholder="变动积分,如 99,999,999"
|
|
||||||
clearable
|
|
||||||
@input="onChargeRefundAmountInput"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="备注" prop="remark">
|
|
||||||
<el-input
|
|
||||||
v-model="chargeRefundForm.remark"
|
|
||||||
type="textarea"
|
|
||||||
:rows="2"
|
|
||||||
maxlength="50"
|
|
||||||
show-word-limit
|
|
||||||
placeholder="选填,最多50字"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="submitChargeRefund">确 定</el-button>
|
|
||||||
<el-button @click="chargeRefundOpen = false">取 消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<el-dialog
|
|
||||||
:title="'积分更正 — ' + (editScoreForm.deptName || '')"
|
|
||||||
:visible.sync="editScoreOpen"
|
|
||||||
width="520px"
|
|
||||||
append-to-body
|
|
||||||
@close="resetEditScore"
|
|
||||||
>
|
|
||||||
<el-form ref="editScoreFormRef" :model="editScoreForm" :rules="editScoreRules" label-width="88px">
|
|
||||||
<el-form-item label="积分" prop="score">
|
|
||||||
<el-input-number
|
|
||||||
v-model="editScoreForm.score"
|
|
||||||
:precision="0"
|
|
||||||
:step="1"
|
|
||||||
:min="-100000000"
|
|
||||||
:max="100000000"
|
|
||||||
controls-position="right"
|
|
||||||
class="edit-score-input-number"
|
|
||||||
placeholder="正数增加,负数扣减,不能为0"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="备注" prop="remark">
|
|
||||||
<el-input
|
|
||||||
v-model="editScoreForm.remark"
|
|
||||||
type="textarea"
|
|
||||||
:rows="2"
|
|
||||||
maxlength="50"
|
|
||||||
show-word-limit
|
|
||||||
placeholder="必填,最多50字"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="submitEditScore">确 定</el-button>
|
|
||||||
<el-button @click="editScoreOpen = false">取 消</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -345,23 +257,15 @@
|
||||||
color: #909399;
|
color: #909399;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
.edit-score-input-number {
|
.form-tip {
|
||||||
width: 100%;
|
margin-right: 16px;
|
||||||
|
color: #e6a23c;
|
||||||
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild, chargeRefundDept, editScore } from "@/api/system/dept"
|
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept"
|
||||||
import {
|
|
||||||
WESTERN_MONEY_MAX,
|
|
||||||
sanitizeMoneyDigits,
|
|
||||||
formatMoneyWesternDisplay,
|
|
||||||
moneyStringToNumber,
|
|
||||||
formatMoneyWesternFinal,
|
|
||||||
sanitizeIntDigits,
|
|
||||||
formatIntWesternDisplay,
|
|
||||||
intStringToNumber
|
|
||||||
} from "@/utils/westernNumberFormat"
|
|
||||||
import Treeselect from "@riophae/vue-treeselect"
|
import Treeselect from "@riophae/vue-treeselect"
|
||||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
|
||||||
|
|
||||||
|
|
@ -394,76 +298,8 @@ export default {
|
||||||
},
|
},
|
||||||
// 表单参数
|
// 表单参数
|
||||||
form: {},
|
form: {},
|
||||||
|
originalForm: {},
|
||||||
modelParamRows: [{ label: '', value: '' }],
|
modelParamRows: [{ label: '', value: '' }],
|
||||||
chargeRefundOpen: false,
|
|
||||||
chargeRefundMoneyDisplay: "",
|
|
||||||
chargeRefundAmountDisplay: "",
|
|
||||||
chargeRefundForm: {
|
|
||||||
deptId: undefined,
|
|
||||||
deptName: "",
|
|
||||||
orderType: 0,
|
|
||||||
money: undefined,
|
|
||||||
amount: undefined,
|
|
||||||
remark: ""
|
|
||||||
},
|
|
||||||
chargeRefundRules: {
|
|
||||||
orderType: [
|
|
||||||
{ required: true, message: "类型不能为空", trigger: "change" }
|
|
||||||
],
|
|
||||||
money: [
|
|
||||||
{ required: true, message: "金额不能为空", trigger: "blur" },
|
|
||||||
{ type: "number", min: 0, max: 10000000, message: "金额须在 0~10000000 之间", trigger: "blur" }
|
|
||||||
],
|
|
||||||
amount: [
|
|
||||||
{ required: true, message: "积分不能为空", trigger: "blur" },
|
|
||||||
{ type: "number", min: 1, max: 100000000, message: "积分须在 1~100000000 之间", trigger: "blur" }
|
|
||||||
],
|
|
||||||
remark: [
|
|
||||||
{ max: 50, message: "备注不能超过50个字符", trigger: "blur" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
editScoreOpen: false,
|
|
||||||
editScoreForm: {
|
|
||||||
deptId: undefined,
|
|
||||||
deptName: "",
|
|
||||||
score: undefined,
|
|
||||||
remark: ""
|
|
||||||
},
|
|
||||||
editScoreRules: {
|
|
||||||
score: [
|
|
||||||
{ required: true, message: "积分不能为空", trigger: "blur" },
|
|
||||||
{
|
|
||||||
validator(rule, value, callback) {
|
|
||||||
if (value === undefined || value === null || value === "") {
|
|
||||||
callback(new Error("积分不能为空"))
|
|
||||||
} else if (!Number.isInteger(Number(value))) {
|
|
||||||
callback(new Error("积分须为整数"))
|
|
||||||
} else if (Number(value) === 0) {
|
|
||||||
callback(new Error("积分不能为0"))
|
|
||||||
} else if (Number(value) < -100000000 || Number(value) > 100000000) {
|
|
||||||
callback(new Error("积分须在 -100000000~100000000 之间(不含0)"))
|
|
||||||
} else {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
trigger: "blur"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
remark: [
|
|
||||||
{ required: true, message: "备注不能为空", trigger: "blur" },
|
|
||||||
{
|
|
||||||
validator(rule, value, callback) {
|
|
||||||
if (!value || String(value).trim() === "") {
|
|
||||||
callback(new Error("备注不能为空"))
|
|
||||||
} else {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
trigger: "blur"
|
|
||||||
},
|
|
||||||
{ max: 50, message: "备注不能超过50个字符", trigger: "blur" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
// 表单校验
|
// 表单校验
|
||||||
rules: {
|
rules: {
|
||||||
parentId: [
|
parentId: [
|
||||||
|
|
@ -506,9 +342,35 @@ export default {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
},
|
||||||
|
isFirstLevelEditForm() {
|
||||||
|
return this.form.deptId !== undefined && this.isFirstLevelRow(this.form)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
isFirstLevelRow(row) {
|
||||||
|
if (!row) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return Number(row.parentId) === 0 && String(row.ancestors || "") === "0"
|
||||||
|
},
|
||||||
|
isSecondLevelRow(row) {
|
||||||
|
if (!row) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const ancestors = String(row.ancestors || "").split(",").filter(Boolean)
|
||||||
|
return ancestors.length === 2
|
||||||
|
},
|
||||||
|
getFirstLevelDeptOptions(nodes) {
|
||||||
|
if (!Array.isArray(nodes)) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return nodes.filter(item => this.isFirstLevelRow(item)).map(item => {
|
||||||
|
const current = { ...item }
|
||||||
|
delete current.children
|
||||||
|
return current
|
||||||
|
})
|
||||||
|
},
|
||||||
syncModelRowsFromForm() {
|
syncModelRowsFromForm() {
|
||||||
this.modelParamRows = [{ label: '', value: '' }]
|
this.modelParamRows = [{ label: '', value: '' }]
|
||||||
const raw = this.form.modelParm
|
const raw = this.form.modelParm
|
||||||
|
|
@ -578,11 +440,13 @@ export default {
|
||||||
leader: undefined,
|
leader: undefined,
|
||||||
phone: undefined,
|
phone: undefined,
|
||||||
email: undefined,
|
email: undefined,
|
||||||
|
maxUserCount: undefined,
|
||||||
byteApiKey: undefined,
|
byteApiKey: undefined,
|
||||||
project: undefined,
|
project: undefined,
|
||||||
modelParm: undefined,
|
modelParm: undefined,
|
||||||
status: "0"
|
status: "0"
|
||||||
}
|
}
|
||||||
|
this.originalForm = {}
|
||||||
this.modelParamRows = [{ label: '', value: '' }]
|
this.modelParamRows = [{ label: '', value: '' }]
|
||||||
this.resetForm("form")
|
this.resetForm("form")
|
||||||
},
|
},
|
||||||
|
|
@ -598,13 +462,17 @@ export default {
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
handleAdd(row) {
|
handleAdd(row) {
|
||||||
this.reset()
|
this.reset()
|
||||||
if (row != undefined) {
|
if (row !== undefined) {
|
||||||
|
if (!this.isFirstLevelRow(row)) {
|
||||||
|
this.$modal.msgError("仅允许在一级部门下新增二级部门")
|
||||||
|
return
|
||||||
|
}
|
||||||
this.form.parentId = row.deptId
|
this.form.parentId = row.deptId
|
||||||
}
|
}
|
||||||
this.open = true
|
this.open = true
|
||||||
this.title = "添加部门"
|
this.title = "添加二级部门"
|
||||||
listDept().then(response => {
|
listDept().then(response => {
|
||||||
this.deptOptions = this.handleTree(response.data, "deptId")
|
this.deptOptions = this.getFirstLevelDeptOptions(this.handleTree(response.data, "deptId"))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
/** 展开/折叠操作 */
|
/** 展开/折叠操作 */
|
||||||
|
|
@ -620,11 +488,13 @@ export default {
|
||||||
this.reset()
|
this.reset()
|
||||||
getDept(row.deptId).then(response => {
|
getDept(row.deptId).then(response => {
|
||||||
this.form = response.data
|
this.form = response.data
|
||||||
|
this.originalForm = { ...response.data }
|
||||||
this.syncModelRowsFromForm()
|
this.syncModelRowsFromForm()
|
||||||
this.open = true
|
this.open = true
|
||||||
this.title = "修改部门"
|
this.title = "修改部门"
|
||||||
listDeptExcludeChild(row.deptId).then(response => {
|
listDeptExcludeChild(row.deptId).then(response => {
|
||||||
this.deptOptions = this.handleTree(response.data, "deptId")
|
const allOptions = this.handleTree(response.data, "deptId")
|
||||||
|
this.deptOptions = this.getFirstLevelDeptOptions(allOptions)
|
||||||
if (this.deptOptions.length == 0) {
|
if (this.deptOptions.length == 0) {
|
||||||
const noResultsOptions = { deptId: this.form.parentId, deptName: this.form.parentName, children: [] }
|
const noResultsOptions = { deptId: this.form.parentId, deptName: this.form.parentName, children: [] }
|
||||||
this.deptOptions.push(noResultsOptions)
|
this.deptOptions.push(noResultsOptions)
|
||||||
|
|
@ -637,7 +507,24 @@ export default {
|
||||||
this.$refs["form"].validate(valid => {
|
this.$refs["form"].validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.buildModelParmPayload()
|
this.buildModelParmPayload()
|
||||||
|
if (this.form.deptId == undefined && !this.deptOptions.some(item => Number(item.deptId) === Number(this.form.parentId))) {
|
||||||
|
this.$modal.msgError("仅允许在一级部门下创建二级部门")
|
||||||
|
return
|
||||||
|
}
|
||||||
if (this.form.deptId != undefined) {
|
if (this.form.deptId != undefined) {
|
||||||
|
if (this.isFirstLevelEditForm) {
|
||||||
|
const oldDept = this.originalForm || {}
|
||||||
|
this.form.parentId = oldDept.parentId
|
||||||
|
this.form.orderNum = oldDept.orderNum
|
||||||
|
this.form.leader = oldDept.leader
|
||||||
|
this.form.phone = oldDept.phone
|
||||||
|
this.form.email = oldDept.email
|
||||||
|
this.form.status = oldDept.status
|
||||||
|
this.form.maxUserCount = oldDept.maxUserCount
|
||||||
|
this.form.byteApiKey = oldDept.byteApiKey
|
||||||
|
this.form.project = oldDept.project
|
||||||
|
this.form.modelParm = oldDept.modelParm
|
||||||
|
}
|
||||||
updateDept(this.form).then(response => {
|
updateDept(this.form).then(response => {
|
||||||
this.$modal.msgSuccess("修改成功")
|
this.$modal.msgSuccess("修改成功")
|
||||||
this.open = false
|
this.open = false
|
||||||
|
|
@ -653,132 +540,6 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
resetChargeRefund() {
|
|
||||||
this.chargeRefundMoneyDisplay = ""
|
|
||||||
this.chargeRefundAmountDisplay = ""
|
|
||||||
this.chargeRefundForm = {
|
|
||||||
deptId: undefined,
|
|
||||||
deptName: "",
|
|
||||||
orderType: 0,
|
|
||||||
money: undefined,
|
|
||||||
amount: undefined,
|
|
||||||
remark: ""
|
|
||||||
}
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$refs.chargeRefundFormRef) {
|
|
||||||
this.$refs.chargeRefundFormRef.clearValidate()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleChargeRefund(row) {
|
|
||||||
this.chargeRefundMoneyDisplay = ""
|
|
||||||
this.chargeRefundAmountDisplay = ""
|
|
||||||
this.chargeRefundForm = {
|
|
||||||
deptId: row.deptId,
|
|
||||||
deptName: row.deptName,
|
|
||||||
orderType: 0,
|
|
||||||
money: undefined,
|
|
||||||
amount: undefined,
|
|
||||||
remark: ""
|
|
||||||
}
|
|
||||||
this.chargeRefundOpen = true
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$refs.chargeRefundFormRef) {
|
|
||||||
this.$refs.chargeRefundFormRef.clearValidate()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
onChargeRefundMoneyInput(val) {
|
|
||||||
const sanitized = sanitizeMoneyDigits(val)
|
|
||||||
if (!sanitized) {
|
|
||||||
this.chargeRefundMoneyDisplay = ""
|
|
||||||
this.chargeRefundForm.money = undefined
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const raw = parseFloat(sanitized)
|
|
||||||
if (!isNaN(raw) && raw > WESTERN_MONEY_MAX) {
|
|
||||||
this.chargeRefundForm.money = WESTERN_MONEY_MAX
|
|
||||||
this.chargeRefundMoneyDisplay = formatMoneyWesternFinal(WESTERN_MONEY_MAX)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.chargeRefundMoneyDisplay = formatMoneyWesternDisplay(sanitized)
|
|
||||||
this.chargeRefundForm.money = moneyStringToNumber(sanitized)
|
|
||||||
},
|
|
||||||
onChargeRefundMoneyBlur() {
|
|
||||||
if (this.chargeRefundForm.money !== undefined && this.chargeRefundForm.money !== null) {
|
|
||||||
this.chargeRefundMoneyDisplay = formatMoneyWesternFinal(this.chargeRefundForm.money)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onChargeRefundAmountInput(val) {
|
|
||||||
const digits = sanitizeIntDigits(val)
|
|
||||||
this.chargeRefundAmountDisplay = digits === "" ? "" : formatIntWesternDisplay(digits)
|
|
||||||
this.chargeRefundForm.amount = intStringToNumber(digits)
|
|
||||||
},
|
|
||||||
submitChargeRefund() {
|
|
||||||
this.onChargeRefundMoneyBlur()
|
|
||||||
this.$refs["chargeRefundFormRef"].validate(valid => {
|
|
||||||
if (!valid) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const data = {
|
|
||||||
deptId: this.chargeRefundForm.deptId,
|
|
||||||
orderType: this.chargeRefundForm.orderType,
|
|
||||||
money: this.chargeRefundForm.money,
|
|
||||||
amount: this.chargeRefundForm.amount,
|
|
||||||
remark: this.chargeRefundForm.remark ? this.chargeRefundForm.remark.trim() : undefined
|
|
||||||
}
|
|
||||||
chargeRefundDept(data).then(() => {
|
|
||||||
this.$modal.msgSuccess("操作成功")
|
|
||||||
this.chargeRefundOpen = false
|
|
||||||
this.getList()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
resetEditScore() {
|
|
||||||
this.editScoreForm = {
|
|
||||||
deptId: undefined,
|
|
||||||
deptName: "",
|
|
||||||
score: undefined,
|
|
||||||
remark: ""
|
|
||||||
}
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$refs.editScoreFormRef) {
|
|
||||||
this.$refs.editScoreFormRef.clearValidate()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleEditScore(row) {
|
|
||||||
this.editScoreForm = {
|
|
||||||
deptId: row.deptId,
|
|
||||||
deptName: row.deptName,
|
|
||||||
score: undefined,
|
|
||||||
remark: ""
|
|
||||||
}
|
|
||||||
this.editScoreOpen = true
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$refs.editScoreFormRef) {
|
|
||||||
this.$refs.editScoreFormRef.clearValidate()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
submitEditScore() {
|
|
||||||
this.$refs["editScoreFormRef"].validate(valid => {
|
|
||||||
if (!valid) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const remark = (this.editScoreForm.remark || "").trim()
|
|
||||||
const data = {
|
|
||||||
deptId: this.editScoreForm.deptId,
|
|
||||||
score: this.editScoreForm.score,
|
|
||||||
remark: remark
|
|
||||||
}
|
|
||||||
editScore(data).then(() => {
|
|
||||||
this.$modal.msgSuccess("操作成功")
|
|
||||||
this.editScoreOpen = false
|
|
||||||
this.getList()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
this.$modal.confirm('是否确认删除名称为"' + row.deptName + '"的数据项?').then(function() {
|
this.$modal.confirm('是否确认删除名称为"' + row.deptName + '"的数据项?').then(function() {
|
||||||
|
|
|
||||||
|
|
@ -44,20 +44,7 @@
|
||||||
inputType="password"
|
inputType="password"
|
||||||
:placeholder="`${$t('common.passwordPlaceholder')}`" />
|
:placeholder="`${$t('common.passwordPlaceholder')}`" />
|
||||||
|
|
||||||
<div class="login-link">
|
|
||||||
<mf-button
|
|
||||||
class="grey"
|
|
||||||
type="text"
|
|
||||||
@click="showForgot">
|
|
||||||
{{ $t('common.forgotPassword') }}?
|
|
||||||
</mf-button>
|
|
||||||
</div>
|
|
||||||
<div class="login-submit">
|
<div class="login-submit">
|
||||||
<mf-button
|
|
||||||
size="large"
|
|
||||||
@click="showRegister">
|
|
||||||
{{ $t('common.register') }}
|
|
||||||
</mf-button>
|
|
||||||
<mf-button
|
<mf-button
|
||||||
size="large"
|
size="large"
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|
@ -67,25 +54,10 @@
|
||||||
</mf-button>
|
</mf-button>
|
||||||
</div>
|
</div>
|
||||||
</mf-dialog>
|
</mf-dialog>
|
||||||
<Forgot
|
|
||||||
v-if="forgotVisible"
|
|
||||||
:visible="forgotVisible"
|
|
||||||
@open="forgotVisible = true"
|
|
||||||
@back="back"
|
|
||||||
@cancel="forgotVisible = false" />
|
|
||||||
|
|
||||||
<Register
|
|
||||||
v-if="registerVisible"
|
|
||||||
:visible="registerVisible"
|
|
||||||
@cancel="registerVisible = false"
|
|
||||||
@back="backFormRegister"
|
|
||||||
@open="registerVisible = true" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Forgot from './Forgot.vue'
|
|
||||||
import Register from './Register.vue'
|
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import i18n from '@/lang/i18n'
|
import i18n from '@/lang/i18n'
|
||||||
|
|
||||||
|
|
@ -93,22 +65,16 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
email: '',
|
email: '',
|
||||||
forgotVisible: false,
|
|
||||||
emailVisible: false,
|
emailVisible: false,
|
||||||
registerVisible: false,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
username: '',
|
username: '',
|
||||||
password: ''
|
password: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
visible: Boolean,
|
visible: Boolean
|
||||||
register: Boolean
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
Forgot,
|
|
||||||
Register
|
|
||||||
},
|
},
|
||||||
|
components: {},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['lang'])
|
...mapGetters(['lang'])
|
||||||
},
|
},
|
||||||
|
|
@ -121,10 +87,6 @@ export default {
|
||||||
// }
|
// }
|
||||||
this.username = ""
|
this.username = ""
|
||||||
this.password = ""
|
this.password = ""
|
||||||
let { inviteCode } = this.$route.query || {}
|
|
||||||
if (inviteCode) {
|
|
||||||
this.showRegister()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
cancel() {
|
cancel() {
|
||||||
|
|
@ -132,24 +94,12 @@ export default {
|
||||||
this.password = ''
|
this.password = ''
|
||||||
this.$emit('cancel')
|
this.$emit('cancel')
|
||||||
},
|
},
|
||||||
showRegister() {
|
|
||||||
this.registerVisible = true
|
|
||||||
this.$emit('cancel')
|
|
||||||
},
|
|
||||||
changeLang(value) {
|
changeLang(value) {
|
||||||
if (value != this.lang) {
|
if (value != this.lang) {
|
||||||
this.$store.dispatch('main/setLanguage', value)
|
this.$store.dispatch('main/setLanguage', value)
|
||||||
i18n.global.locale = value
|
i18n.global.locale = value
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
back() {
|
|
||||||
this.forgotVisible = false
|
|
||||||
this.$emit('open')
|
|
||||||
},
|
|
||||||
backFormRegister() {
|
|
||||||
this.registerVisible = false
|
|
||||||
this.$emit('open')
|
|
||||||
},
|
|
||||||
login() {
|
login() {
|
||||||
if (!this.username) {
|
if (!this.username) {
|
||||||
this.$message.error(this.$t('common.userEmailPlaceholder'))
|
this.$message.error(this.$t('common.userEmailPlaceholder'))
|
||||||
|
|
@ -191,10 +141,6 @@ export default {
|
||||||
.catch((_) => {
|
.catch((_) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
},
|
|
||||||
showForgot() {
|
|
||||||
this.forgotVisible = true
|
|
||||||
this.$emit('cancel')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -324,36 +270,8 @@ export default {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
.mf-button {
|
.mf-button {
|
||||||
width: 160px;
|
width: 220px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
margin: 0 14px;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
color: #ffffff;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
&:hover {
|
|
||||||
background-color: #262626;
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
background-color: #0d0d0d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-link {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
color: #999;
|
|
||||||
margin-top: 10px;
|
|
||||||
.mf-button {
|
|
||||||
padding: 0;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 12px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,22 +42,10 @@
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</div>
|
</div>
|
||||||
</mf-dialog>
|
</mf-dialog>
|
||||||
<Forgot
|
|
||||||
:visible="forgotVisible"
|
|
||||||
@open="forgotVisible = true"
|
|
||||||
@back="back"
|
|
||||||
@cancel="forgotVisible = false" />
|
|
||||||
<Register
|
|
||||||
:visible="registerVisible"
|
|
||||||
@cancel="registerVisible = false"
|
|
||||||
@back="backFormRegister"
|
|
||||||
@open="registerVisible = true" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Forgot from './Forgot.vue'
|
|
||||||
import Register from './Register.vue'
|
|
||||||
import UserAccount from './UserAccount.vue'
|
import UserAccount from './UserAccount.vue'
|
||||||
import ResumeRecord from './ResumeRecord.vue'
|
import ResumeRecord from './ResumeRecord.vue'
|
||||||
|
|
||||||
|
|
@ -65,9 +53,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
email: '',
|
email: '',
|
||||||
forgotVisible: false,
|
|
||||||
emailVisible: false,
|
emailVisible: false,
|
||||||
registerVisible: false,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
|
|
@ -75,22 +61,13 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
visible: Boolean,
|
visible: Boolean
|
||||||
register: Boolean
|
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Forgot,
|
|
||||||
Register,
|
|
||||||
UserAccount,
|
UserAccount,
|
||||||
ResumeRecord
|
ResumeRecord
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.register) {
|
|
||||||
this.showRegister()
|
|
||||||
setTimeout((_) => {
|
|
||||||
this.$emit('cancel')
|
|
||||||
}, 300)
|
|
||||||
}
|
|
||||||
window.addEventListener('message', (event) => {
|
window.addEventListener('message', (event) => {
|
||||||
if (event.data.type === 'google-login') {
|
if (event.data.type === 'google-login') {
|
||||||
const { token } = event.data
|
const { token } = event.data
|
||||||
|
|
@ -104,18 +81,6 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
showRegister() {
|
|
||||||
this.registerVisible = true
|
|
||||||
this.$emit('cancel')
|
|
||||||
},
|
|
||||||
back() {
|
|
||||||
this.forgotVisible = false
|
|
||||||
this.$emit('open')
|
|
||||||
},
|
|
||||||
backFormRegister() {
|
|
||||||
this.registerVisible = false
|
|
||||||
this.$emit('open')
|
|
||||||
},
|
|
||||||
backEmail() {
|
backEmail() {
|
||||||
this.emailVisible = false
|
this.emailVisible = false
|
||||||
this.$emit('open')
|
this.$emit('open')
|
||||||
|
|
@ -148,10 +113,6 @@ export default {
|
||||||
.catch((_) => {
|
.catch((_) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
},
|
|
||||||
showForgot() {
|
|
||||||
this.forgotVisible = true
|
|
||||||
this.$emit('cancel')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Login
|
<Login
|
||||||
:register="!$datas.isEmpty(inviteCode)"
|
|
||||||
:visible="showLogin"
|
:visible="showLogin"
|
||||||
@open="openLogin"
|
@open="openLogin"
|
||||||
@cancel="cancelLogin" />
|
@cancel="cancelLogin" />
|
||||||
|
|
@ -118,7 +117,6 @@ export default {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
publishVisible: false,
|
publishVisible: false,
|
||||||
inviteCode: this.$route.query?.inviteCode,
|
|
||||||
userVisible: false,
|
userVisible: false,
|
||||||
logoUrl: null
|
logoUrl: null
|
||||||
}
|
}
|
||||||
|
|
@ -179,9 +177,6 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.inviteCode) {
|
|
||||||
this.openLogin()
|
|
||||||
}
|
|
||||||
this.getLogo()
|
this.getLogo()
|
||||||
if (getToken()) {
|
if (getToken()) {
|
||||||
this.$store.dispatch('user/getInfo').catch(() => {})
|
this.$store.dispatch('user/getInfo').catch(() => {})
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
package com.ruoyi.ai.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
||||||
|
import com.ruoyi.ai.service.IAiChargeRefundOrderService;
|
||||||
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 团队(部门)充值退款订单Controller
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/ai/order")
|
||||||
|
public class AiChargeRefundOrderController extends BaseController
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private IAiChargeRefundOrderService aiChargeRefundOrderService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询团队(部门)充值退款订单列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:order:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(AiChargeRefundOrder aiChargeRefundOrder)
|
||||||
|
{
|
||||||
|
startPage();
|
||||||
|
List<AiChargeRefundOrder> list = aiChargeRefundOrderService.selectAiChargeRefundOrderList(aiChargeRefundOrder);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出团队(部门)充值退款订单列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:order:export')")
|
||||||
|
@Log(title = "团队(部门)充值退款订单", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/export")
|
||||||
|
public void export(HttpServletResponse response, AiChargeRefundOrder aiChargeRefundOrder)
|
||||||
|
{
|
||||||
|
List<AiChargeRefundOrder> list = aiChargeRefundOrderService.selectAiChargeRefundOrderList(aiChargeRefundOrder);
|
||||||
|
ExcelUtil<AiChargeRefundOrder> util = new ExcelUtil<AiChargeRefundOrder>(AiChargeRefundOrder.class);
|
||||||
|
util.exportExcel(response, list, "团队(部门)充值退款订单数据");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取团队(部门)充值退款订单详细信息
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:order:query')")
|
||||||
|
@GetMapping(value = "/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||||
|
{
|
||||||
|
return success(aiChargeRefundOrderService.selectAiChargeRefundOrderById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增团队(部门)充值退款订单
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:order:add')")
|
||||||
|
@Log(title = "团队(部门)充值退款订单", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping
|
||||||
|
public AjaxResult add(@RequestBody AiChargeRefundOrder aiChargeRefundOrder)
|
||||||
|
{
|
||||||
|
return toAjax(aiChargeRefundOrderService.insertAiChargeRefundOrder(aiChargeRefundOrder));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改团队(部门)充值退款订单
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:order:edit')")
|
||||||
|
@Log(title = "团队(部门)充值退款订单", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping
|
||||||
|
public AjaxResult edit(@RequestBody AiChargeRefundOrder aiChargeRefundOrder)
|
||||||
|
{
|
||||||
|
return toAjax(aiChargeRefundOrderService.updateAiChargeRefundOrder(aiChargeRefundOrder));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除团队(部门)充值退款订单
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:order:remove')")
|
||||||
|
@Log(title = "团队(部门)充值退款订单", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public AjaxResult remove(@PathVariable Long[] ids)
|
||||||
|
{
|
||||||
|
return toAjax(aiChargeRefundOrderService.deleteAiChargeRefundOrderByIds(ids));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
package com.ruoyi.ai.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.ai.domain.AiDeptArkConfig;
|
||||||
|
import com.ruoyi.ai.service.IAiDeptArkConfigService;
|
||||||
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 团队(部门)对应火山引擎配置Controller
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/ai/config")
|
||||||
|
public class AiDeptArkConfigController extends BaseController
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private IAiDeptArkConfigService aiDeptArkConfigService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询团队(部门)对应火山引擎配置列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:config:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(AiDeptArkConfig aiDeptArkConfig)
|
||||||
|
{
|
||||||
|
startPage();
|
||||||
|
List<AiDeptArkConfig> list = aiDeptArkConfigService.selectAiDeptArkConfigList(aiDeptArkConfig);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出团队(部门)对应火山引擎配置列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:config:export')")
|
||||||
|
@Log(title = "团队(部门)对应火山引擎配置", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/export")
|
||||||
|
public void export(HttpServletResponse response, AiDeptArkConfig aiDeptArkConfig)
|
||||||
|
{
|
||||||
|
List<AiDeptArkConfig> list = aiDeptArkConfigService.selectAiDeptArkConfigList(aiDeptArkConfig);
|
||||||
|
ExcelUtil<AiDeptArkConfig> util = new ExcelUtil<AiDeptArkConfig>(AiDeptArkConfig.class);
|
||||||
|
util.exportExcel(response, list, "团队(部门)对应火山引擎配置数据");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取团队(部门)对应火山引擎配置详细信息
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:config:query')")
|
||||||
|
@GetMapping(value = "/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||||
|
{
|
||||||
|
return success(aiDeptArkConfigService.selectAiDeptArkConfigById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增团队(部门)对应火山引擎配置
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:config:add')")
|
||||||
|
@Log(title = "团队(部门)对应火山引擎配置", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping
|
||||||
|
public AjaxResult add(@RequestBody AiDeptArkConfig aiDeptArkConfig)
|
||||||
|
{
|
||||||
|
return toAjax(aiDeptArkConfigService.insertAiDeptArkConfig(aiDeptArkConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改团队(部门)对应火山引擎配置
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:config:edit')")
|
||||||
|
@Log(title = "团队(部门)对应火山引擎配置", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping
|
||||||
|
public AjaxResult edit(@RequestBody AiDeptArkConfig aiDeptArkConfig)
|
||||||
|
{
|
||||||
|
return toAjax(aiDeptArkConfigService.updateAiDeptArkConfig(aiDeptArkConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除团队(部门)对应火山引擎配置
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:config:remove')")
|
||||||
|
@Log(title = "团队(部门)对应火山引擎配置", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public AjaxResult remove(@PathVariable String[] ids)
|
||||||
|
{
|
||||||
|
return toAjax(aiDeptArkConfigService.deleteAiDeptArkConfigByIds(ids));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
package com.ruoyi.ai.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.ai.domain.AiGroupBalanceChangeRecord;
|
||||||
|
import com.ruoyi.ai.service.IAiGroupBalanceChangeRecordService;
|
||||||
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 团队(部门)余额变动Controller
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/ai/record")
|
||||||
|
public class AiGroupBalanceChangeRecordController extends BaseController
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private IAiGroupBalanceChangeRecordService aiGroupBalanceChangeRecordService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询团队(部门)余额变动列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:record:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord)
|
||||||
|
{
|
||||||
|
startPage();
|
||||||
|
List<AiGroupBalanceChangeRecord> list = aiGroupBalanceChangeRecordService.selectAiGroupBalanceChangeRecordList(aiGroupBalanceChangeRecord);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出团队(部门)余额变动列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:record:export')")
|
||||||
|
@Log(title = "团队(部门)余额变动", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/export")
|
||||||
|
public void export(HttpServletResponse response, AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord)
|
||||||
|
{
|
||||||
|
List<AiGroupBalanceChangeRecord> list = aiGroupBalanceChangeRecordService.selectAiGroupBalanceChangeRecordList(aiGroupBalanceChangeRecord);
|
||||||
|
ExcelUtil<AiGroupBalanceChangeRecord> util = new ExcelUtil<AiGroupBalanceChangeRecord>(AiGroupBalanceChangeRecord.class);
|
||||||
|
util.exportExcel(response, list, "团队(部门)余额变动数据");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取团队(部门)余额变动详细信息
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:record:query')")
|
||||||
|
@GetMapping(value = "/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||||
|
{
|
||||||
|
return success(aiGroupBalanceChangeRecordService.selectAiGroupBalanceChangeRecordById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增团队(部门)余额变动
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:record:add')")
|
||||||
|
@Log(title = "团队(部门)余额变动", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping
|
||||||
|
public AjaxResult add(@RequestBody AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord)
|
||||||
|
{
|
||||||
|
return toAjax(aiGroupBalanceChangeRecordService.insertAiGroupBalanceChangeRecord(aiGroupBalanceChangeRecord));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改团队(部门)余额变动
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:record:edit')")
|
||||||
|
@Log(title = "团队(部门)余额变动", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping
|
||||||
|
public AjaxResult edit(@RequestBody AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord)
|
||||||
|
{
|
||||||
|
return toAjax(aiGroupBalanceChangeRecordService.updateAiGroupBalanceChangeRecord(aiGroupBalanceChangeRecord));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除团队(部门)余额变动
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:record:remove')")
|
||||||
|
@Log(title = "团队(部门)余额变动", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public AjaxResult remove(@PathVariable String[] ids)
|
||||||
|
{
|
||||||
|
return toAjax(aiGroupBalanceChangeRecordService.deleteAiGroupBalanceChangeRecordByIds(ids));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
package com.ruoyi.ai.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.ai.domain.AiVideoReportData;
|
||||||
|
import com.ruoyi.ai.service.IAiVideoReportDataService;
|
||||||
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI视频生成统计数据,作为其他统计报的数据源Controller
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/ai/data")
|
||||||
|
public class AiVideoReportDataController extends BaseController
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private IAiVideoReportDataService aiVideoReportDataService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询AI视频生成统计数据,作为其他统计报的数据源列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:data:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(AiVideoReportData aiVideoReportData)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(aiVideoReportData.getStatDate()) || aiVideoReportData.getDeptId() == null)
|
||||||
|
{
|
||||||
|
return getDataTable(java.util.Collections.emptyList());
|
||||||
|
}
|
||||||
|
startPage();
|
||||||
|
List<AiVideoReportData> list = aiVideoReportDataService.selectTeamDailyConsumeList(
|
||||||
|
aiVideoReportData.getStatDate(), aiVideoReportData.getDeptId());
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出AI视频生成统计数据,作为其他统计报的数据源列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:data:export')")
|
||||||
|
@Log(title = "AI视频生成统计数据,作为其他统计报的数据源", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/export")
|
||||||
|
public void export(HttpServletResponse response, AiVideoReportData aiVideoReportData)
|
||||||
|
{
|
||||||
|
List<AiVideoReportData> list = aiVideoReportDataService.selectAiVideoReportDataList(aiVideoReportData);
|
||||||
|
ExcelUtil<AiVideoReportData> util = new ExcelUtil<AiVideoReportData>(AiVideoReportData.class);
|
||||||
|
util.exportExcel(response, list, "AI视频生成统计数据,作为其他统计报的数据源数据");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取AI视频生成统计数据,作为其他统计报的数据源详细信息
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:data:query')")
|
||||||
|
@GetMapping(value = "/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||||
|
{
|
||||||
|
return success(aiVideoReportDataService.selectAiVideoReportDataById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:data:add')")
|
||||||
|
@Log(title = "AI视频生成统计数据,作为其他统计报的数据源", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping
|
||||||
|
public AjaxResult add(@RequestBody AiVideoReportData aiVideoReportData)
|
||||||
|
{
|
||||||
|
return toAjax(aiVideoReportDataService.insertAiVideoReportData(aiVideoReportData));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:data:edit')")
|
||||||
|
@Log(title = "AI视频生成统计数据,作为其他统计报的数据源", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping
|
||||||
|
public AjaxResult edit(@RequestBody AiVideoReportData aiVideoReportData)
|
||||||
|
{
|
||||||
|
return toAjax(aiVideoReportDataService.updateAiVideoReportData(aiVideoReportData));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('ai:data:remove')")
|
||||||
|
@Log(title = "AI视频生成统计数据,作为其他统计报的数据源", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public AjaxResult remove(@PathVariable String[] ids)
|
||||||
|
{
|
||||||
|
return toAjax(aiVideoReportDataService.deleteAiVideoReportDataByIds(ids));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -162,7 +162,7 @@ public class PortalVideoController extends BaseController {
|
||||||
List<PortalVideoProperties.ModelOption> allowed = loadModelOptionsForAiUser(uid, secondDeptId);
|
List<PortalVideoProperties.ModelOption> allowed = loadModelOptionsForAiUser(uid, secondDeptId);
|
||||||
String modelId = StringUtils.isNotEmpty(req.getModel()) ? req.getModel() : resolveDefaultModelForAiUser(uid, secondDeptId, allowed);
|
String modelId = StringUtils.isNotEmpty(req.getModel()) ? req.getModel() : resolveDefaultModelForAiUser(uid, secondDeptId, allowed);
|
||||||
if (StringUtils.isEmpty(modelId)) {
|
if (StringUtils.isEmpty(modelId)) {
|
||||||
throw new ServiceException("未配置门户视频模型:请在后台为该用户所属二级部门配置 model_parm,或在 portal.video.models 中配置全局列表");
|
throw new ServiceException("未配置门户视频模型:请在后台为该用户所属二级部门配置");
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotEmpty(req.getModel()) && !isModelInOptions(modelId, allowed)) {
|
if (StringUtils.isNotEmpty(req.getModel()) && !isModelInOptions(modelId, allowed)) {
|
||||||
throw new ServiceException("所选模型对当前部门不可用");
|
throw new ServiceException("所选模型对当前部门不可用");
|
||||||
|
|
@ -517,7 +517,7 @@ public class PortalVideoController extends BaseController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/options")
|
@GetMapping("/options")
|
||||||
@ApiOperation("门户视频生成可选参数(模型/比例/时长等,来自配置)")
|
@ApiOperation("门户视频生成可选参数(模型/比例/时长等,来自系统参数)")
|
||||||
public AjaxResult videoParamOptions() {
|
public AjaxResult videoParamOptions() {
|
||||||
Long uid = SecurityUtils.getAiUserId();
|
Long uid = SecurityUtils.getAiUserId();
|
||||||
Long secondDeptId = byteDeptApiKeyService.resolveSecondLevelDeptId(uid);
|
Long secondDeptId = byteDeptApiKeyService.resolveSecondLevelDeptId(uid);
|
||||||
|
|
|
||||||
|
|
@ -1,115 +1,102 @@
|
||||||
package com.ruoyi.config;
|
package com.ruoyi.config;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.system.service.ISysConfigService;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 门户视频生成参数(模型、比例、时长、分辨率等从配置读取,不在代码中写死业务默认值)。
|
* 门户视频生成参数(从 sys_config 读取)。
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties(prefix = "portal.video")
|
|
||||||
public class PortalVideoProperties {
|
public class PortalVideoProperties {
|
||||||
|
|
||||||
private Defaults defaults = new Defaults();
|
private static final ObjectMapper OM = new ObjectMapper();
|
||||||
|
|
||||||
private List<ModelOption> models = new ArrayList<>();
|
/** 默认值:{"model":"...","duration":5,"resolution":"720p","ratio":"16:9"} */
|
||||||
|
private static final String CFG_DEFAULTS = "portal.video.defaults";
|
||||||
|
/** 模型列表:[{"label":"Seedance 2.0","value":"ep-xxx"}] */
|
||||||
|
private static final String CFG_MODELS = "portal.video.models";
|
||||||
|
/** 二级部门模型映射:{"101":[{"label":"...","value":"..."}]} */
|
||||||
|
private static final String CFG_MODELS_BY_SECOND_DEPT = "portal.video.modelsBySecondDept";
|
||||||
|
/** 二级部门默认值覆盖:{"101":{"duration":5,"resolution":"720p"}} */
|
||||||
|
private static final String CFG_DEFAULTS_BY_SECOND_DEPT = "portal.video.defaultsBySecondDept";
|
||||||
|
/** 比例列表:["16:9","9:16"] */
|
||||||
|
private static final String CFG_RATIOS = "portal.video.ratios";
|
||||||
|
/** 时长列表:[5,10] */
|
||||||
|
private static final String CFG_DURATIONS = "portal.video.durations";
|
||||||
|
/** 分辨率列表:["720p","1080p"] */
|
||||||
|
private static final String CFG_RESOLUTIONS = "portal.video.resolutions";
|
||||||
|
/** 功能类型:与 ai_manager.type 对应 */
|
||||||
|
private static final String CFG_FUNCTION_TYPE = "portal.video.functionType";
|
||||||
|
private static final String DEFAULT_FUNCTION_TYPE = "21";
|
||||||
|
|
||||||
/**
|
@Resource
|
||||||
* 按二级部门 {@code dept_id}(字符串,如 {@code "101"})配置专属模型列表;未命中时使用全局 {@link #models}。
|
private ISysConfigService sysConfigService;
|
||||||
*/
|
|
||||||
private Map<String, List<ModelOption>> modelsBySecondDept = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 按二级部门覆盖 {@link #defaults} 中的字段;仅配置需要覆盖的项即可。
|
|
||||||
*/
|
|
||||||
private Map<String, Defaults> defaultsBySecondDept = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
private List<String> ratios = new ArrayList<>();
|
|
||||||
|
|
||||||
private List<Integer> durations = new ArrayList<>();
|
|
||||||
|
|
||||||
private List<String> resolutions = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 与 ai_manager.type 一致,用于扣费与订单;库中需存在对应记录且 status=0、del_flag=0
|
|
||||||
*/
|
|
||||||
private String functionType = "21";
|
|
||||||
|
|
||||||
public String getFunctionType() {
|
public String getFunctionType() {
|
||||||
return functionType;
|
String functionType = trimToNull(sysConfigService.selectConfigByKey(CFG_FUNCTION_TYPE));
|
||||||
}
|
return functionType != null ? functionType : DEFAULT_FUNCTION_TYPE;
|
||||||
|
|
||||||
public void setFunctionType(String functionType) {
|
|
||||||
this.functionType = functionType != null ? functionType : "21";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Defaults getDefaults() {
|
public Defaults getDefaults() {
|
||||||
return defaults;
|
Defaults defaults = parseObjectConfig(CFG_DEFAULTS, Defaults.class);
|
||||||
}
|
return defaults != null ? defaults : new Defaults();
|
||||||
|
|
||||||
public void setDefaults(Defaults defaults) {
|
|
||||||
if (defaults != null) {
|
|
||||||
this.defaults = defaults;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ModelOption> getModels() {
|
public List<ModelOption> getModels() {
|
||||||
return models;
|
List<ModelOption> models = parseListConfig(CFG_MODELS, new TypeReference<List<ModelOption>>() {
|
||||||
}
|
});
|
||||||
|
return models != null ? models : new ArrayList<>();
|
||||||
public void setModels(List<ModelOption> models) {
|
|
||||||
this.models = models != null ? models : new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, List<ModelOption>> getModelsBySecondDept() {
|
public Map<String, List<ModelOption>> getModelsBySecondDept() {
|
||||||
return modelsBySecondDept;
|
Map<String, List<ModelOption>> map = parseObjectConfig(CFG_MODELS_BY_SECOND_DEPT,
|
||||||
}
|
new TypeReference<Map<String, List<ModelOption>>>() {
|
||||||
|
});
|
||||||
public void setModelsBySecondDept(Map<String, List<ModelOption>> modelsBySecondDept) {
|
return map != null ? map : new LinkedHashMap<>();
|
||||||
this.modelsBySecondDept = modelsBySecondDept != null ? modelsBySecondDept : new LinkedHashMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Defaults> getDefaultsBySecondDept() {
|
public Map<String, Defaults> getDefaultsBySecondDept() {
|
||||||
return defaultsBySecondDept;
|
Map<String, Defaults> map = parseObjectConfig(CFG_DEFAULTS_BY_SECOND_DEPT,
|
||||||
}
|
new TypeReference<Map<String, Defaults>>() {
|
||||||
|
});
|
||||||
public void setDefaultsBySecondDept(Map<String, Defaults> defaultsBySecondDept) {
|
return map != null ? map : new LinkedHashMap<>();
|
||||||
this.defaultsBySecondDept = defaultsBySecondDept != null ? defaultsBySecondDept : new LinkedHashMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getRatios() {
|
public List<String> getRatios() {
|
||||||
return ratios;
|
List<String> ratios = parseListConfig(CFG_RATIOS, new TypeReference<List<String>>() {
|
||||||
}
|
});
|
||||||
|
return ratios != null ? ratios : Collections.emptyList();
|
||||||
public void setRatios(List<String> ratios) {
|
|
||||||
this.ratios = ratios != null ? ratios : new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Integer> getDurations() {
|
public List<Integer> getDurations() {
|
||||||
return durations;
|
List<Integer> durations = parseListConfig(CFG_DURATIONS, new TypeReference<List<Integer>>() {
|
||||||
}
|
});
|
||||||
|
return durations != null ? durations : Collections.emptyList();
|
||||||
public void setDurations(List<Integer> durations) {
|
|
||||||
this.durations = durations != null ? durations : new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getResolutions() {
|
public List<String> getResolutions() {
|
||||||
return resolutions;
|
List<String> resolutions = parseListConfig(CFG_RESOLUTIONS, new TypeReference<List<String>>() {
|
||||||
}
|
});
|
||||||
|
return resolutions != null ? resolutions : Collections.emptyList();
|
||||||
public void setResolutions(List<String> resolutions) {
|
|
||||||
this.resolutions = resolutions != null ? resolutions : new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* defaults.model 为空时,取 models 第一项的 value。
|
* defaults.model 为空时,取 models 第一项的 value。
|
||||||
*/
|
*/
|
||||||
public String resolveDefaultModelId() {
|
public String resolveDefaultModelId() {
|
||||||
|
Defaults defaults = getDefaults();
|
||||||
|
List<ModelOption> models = getModels();
|
||||||
if (defaults.getModel() != null && !defaults.getModel().isEmpty()) {
|
if (defaults.getModel() != null && !defaults.getModel().isEmpty()) {
|
||||||
return defaults.getModel();
|
return defaults.getModel();
|
||||||
}
|
}
|
||||||
|
|
@ -120,6 +107,8 @@ public class PortalVideoProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ModelOption> resolveModelsForSecondDept(Long secondDeptId) {
|
public List<ModelOption> resolveModelsForSecondDept(Long secondDeptId) {
|
||||||
|
Map<String, List<ModelOption>> modelsBySecondDept = getModelsBySecondDept();
|
||||||
|
List<ModelOption> models = getModels();
|
||||||
if (secondDeptId != null) {
|
if (secondDeptId != null) {
|
||||||
List<ModelOption> byDept = modelsBySecondDept.get(String.valueOf(secondDeptId));
|
List<ModelOption> byDept = modelsBySecondDept.get(String.valueOf(secondDeptId));
|
||||||
if (byDept != null && !byDept.isEmpty()) {
|
if (byDept != null && !byDept.isEmpty()) {
|
||||||
|
|
@ -131,12 +120,13 @@ public class PortalVideoProperties {
|
||||||
|
|
||||||
public Defaults resolveEffectiveDefaults(Long secondDeptId) {
|
public Defaults resolveEffectiveDefaults(Long secondDeptId) {
|
||||||
Defaults out = new Defaults();
|
Defaults out = new Defaults();
|
||||||
Defaults g = this.defaults;
|
Defaults g = this.getDefaults();
|
||||||
out.setModel(g.getModel());
|
out.setModel(g.getModel());
|
||||||
out.setDuration(g.getDuration());
|
out.setDuration(g.getDuration());
|
||||||
out.setResolution(g.getResolution());
|
out.setResolution(g.getResolution());
|
||||||
out.setRatio(g.getRatio());
|
out.setRatio(g.getRatio());
|
||||||
if (secondDeptId != null) {
|
if (secondDeptId != null) {
|
||||||
|
Map<String, Defaults> defaultsBySecondDept = getDefaultsBySecondDept();
|
||||||
Defaults o = defaultsBySecondDept.get(String.valueOf(secondDeptId));
|
Defaults o = defaultsBySecondDept.get(String.valueOf(secondDeptId));
|
||||||
if (o != null) {
|
if (o != null) {
|
||||||
if (o.getModel() != null && !o.getModel().isEmpty()) {
|
if (o.getModel() != null && !o.getModel().isEmpty()) {
|
||||||
|
|
@ -183,6 +173,51 @@ public class PortalVideoProperties {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T> T parseObjectConfig(String key, Class<T> clazz) {
|
||||||
|
String raw = trimToNull(sysConfigService.selectConfigByKey(key));
|
||||||
|
if (raw == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return OM.readValue(raw, clazz);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T parseObjectConfig(String key, TypeReference<T> typeReference) {
|
||||||
|
String raw = trimToNull(sysConfigService.selectConfigByKey(key));
|
||||||
|
if (raw == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return OM.readValue(raw, typeReference);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> List<T> parseListConfig(String key, TypeReference<List<T>> typeReference) {
|
||||||
|
String raw = trimToNull(sysConfigService.selectConfigByKey(key));
|
||||||
|
if (raw == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
List<T> list = OM.readValue(raw, typeReference);
|
||||||
|
return list != null ? list : new ArrayList<>();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String trimToNull(String value) {
|
||||||
|
if (StringUtils.isEmpty(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String out = value.trim();
|
||||||
|
return out.isEmpty() ? null : out;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Defaults {
|
public static class Defaults {
|
||||||
private String model;
|
private String model;
|
||||||
private Integer duration;
|
private Integer duration;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import java.util.List;
|
||||||
* @date 2025-11-13
|
* @date 2025-11-13
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/ai/order")
|
@RequestMapping("/ai/video/order")
|
||||||
public class AiOrderController extends BaseController
|
public class AiOrderController extends BaseController
|
||||||
{
|
{
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.ruoyi.web.controller.subteam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamDataQueryService;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamScopeService;
|
||||||
|
import com.ruoyi.ai.service.IAiChargeRefundOrderService;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/subteam/charge-order")
|
||||||
|
public class SubteamChargeOrderController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamDataQueryService subteamDataQueryService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamScopeService subteamScopeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAiChargeRefundOrderService aiChargeRefundOrderService;
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:charge:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(AiChargeRefundOrder query) {
|
||||||
|
startPage();
|
||||||
|
List<AiChargeRefundOrder> list = subteamDataQueryService.selectChargeRefundOrders(query);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:charge:query')")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable Long id) {
|
||||||
|
subteamScopeService.assertChargeRefundBelongsToTeam(id);
|
||||||
|
return success(aiChargeRefundOrderService.selectAiChargeRefundOrderById(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.ruoyi.web.controller.subteam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.ai.domain.AiVideoReportData;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamDataQueryService;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/subteam/consume-stat")
|
||||||
|
public class SubteamConsumeStatController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamDataQueryService subteamDataQueryService;
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:consume:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(AiVideoReportData query) {
|
||||||
|
if (StringUtils.isEmpty(query.getStatDate())) {
|
||||||
|
return getDataTable(java.util.Collections.emptyList());
|
||||||
|
}
|
||||||
|
startPage();
|
||||||
|
List<AiVideoReportData> list = subteamDataQueryService.selectTeamDailyConsume(query.getStatDate());
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.ruoyi.web.controller.subteam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.ai.domain.AiGroupBalanceChangeRecord;
|
||||||
|
import com.ruoyi.ai.service.IAiGroupBalanceChangeRecordService;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamDataQueryService;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamScopeService;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/subteam/group-balance")
|
||||||
|
public class SubteamGroupBalanceController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamDataQueryService subteamDataQueryService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamScopeService subteamScopeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAiGroupBalanceChangeRecordService aiGroupBalanceChangeRecordService;
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:groupBalance:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(AiGroupBalanceChangeRecord query) {
|
||||||
|
startPage();
|
||||||
|
List<AiGroupBalanceChangeRecord> list = subteamDataQueryService.selectGroupBalanceRecords(query);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:groupBalance:query')")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable String id) {
|
||||||
|
subteamScopeService.assertGroupBalanceRecordBelongsToTeam(id);
|
||||||
|
return success(aiGroupBalanceChangeRecordService.selectAiGroupBalanceChangeRecordById(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.ruoyi.web.controller.subteam;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.system.domain.subteam.SubteamOverviewVO;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamOverviewService;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/subteam/overview")
|
||||||
|
public class SubteamOverviewController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamOverviewService subteamOverviewService;
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:overview:view')")
|
||||||
|
@GetMapping
|
||||||
|
public AjaxResult overview() {
|
||||||
|
SubteamOverviewVO vo = subteamOverviewService.loadOverview();
|
||||||
|
return success(vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.ruoyi.web.controller.subteam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.ai.domain.AiBalanceChangeRecord;
|
||||||
|
import com.ruoyi.ai.service.IAiBalanceChangeRecordService;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamDataQueryService;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamScopeService;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/subteam/user-balance")
|
||||||
|
public class SubteamUserBalanceController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamDataQueryService subteamDataQueryService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamScopeService subteamScopeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAiBalanceChangeRecordService aiBalanceChangeRecordService;
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:userBalance:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(AiBalanceChangeRecord query) {
|
||||||
|
startPage();
|
||||||
|
List<AiBalanceChangeRecord> list = subteamDataQueryService.selectUserBalanceRecords(query);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:userBalance:query')")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable Long id) {
|
||||||
|
subteamScopeService.assertAiBalanceRecordVisible(id, subteamScopeService.currentTeamDeptId());
|
||||||
|
return success(aiBalanceChangeRecordService.selectAiBalanceChangeRecordById(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
package com.ruoyi.web.controller.subteam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.domain.entity.AiUser;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.ai.service.IAiUserService;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamScopeService;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/subteam/user")
|
||||||
|
public class SubteamUserController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAiUserService aiUserService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamScopeService subteamScopeService;
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:user:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(AiUser aiUser) {
|
||||||
|
aiUser.setDeptId(subteamScopeService.currentTeamDeptId());
|
||||||
|
startPage();
|
||||||
|
List<AiUser> list = aiUserService.selectAiUserList(aiUser);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:user:query')")
|
||||||
|
@GetMapping(value = {"/", "/{userId}"})
|
||||||
|
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) {
|
||||||
|
if (StringUtils.isNotNull(userId)) {
|
||||||
|
subteamScopeService.assertAiUserInTeam(userId);
|
||||||
|
return success(aiUserService.selectAiUserById(userId));
|
||||||
|
}
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:user:add')")
|
||||||
|
@Log(title = "团队后台用户", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping
|
||||||
|
public AjaxResult add(@Validated @RequestBody AiUser aiUser) {
|
||||||
|
if (StringUtils.isEmpty(aiUser.getUsername())) {
|
||||||
|
return error("登录账号不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(aiUser.getPassword())) {
|
||||||
|
return error("密码不能为空");
|
||||||
|
}
|
||||||
|
aiUser.setDeptId(subteamScopeService.currentTeamDeptId());
|
||||||
|
aiUser.setCreateBy(getUsername());
|
||||||
|
return toAjax(aiUserService.insertAiUser(aiUser));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:user:edit')")
|
||||||
|
@Log(title = "团队后台用户", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping
|
||||||
|
public AjaxResult edit(@Validated @RequestBody AiUser aiUser) {
|
||||||
|
if (aiUser.getId() == null) {
|
||||||
|
return error("用户主键不能为空");
|
||||||
|
}
|
||||||
|
subteamScopeService.assertAiUserInTeam(aiUser.getId());
|
||||||
|
aiUser.setDeptId(subteamScopeService.currentTeamDeptId());
|
||||||
|
aiUser.setUpdateBy(getUsername());
|
||||||
|
return toAjax(aiUserService.updateAiUser(aiUser));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:user:remove')")
|
||||||
|
@Log(title = "团队后台用户", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{userIds}")
|
||||||
|
public AjaxResult remove(@PathVariable Long[] userIds) {
|
||||||
|
for (Long userId : userIds) {
|
||||||
|
subteamScopeService.assertAiUserInTeam(userId);
|
||||||
|
}
|
||||||
|
return toAjax(aiUserService.deleteAiUserByIds(userIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:user:resetPwd')")
|
||||||
|
@Log(title = "团队后台用户", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping("/resetPwd")
|
||||||
|
public AjaxResult resetPwd(@RequestBody AiUser aiUser) {
|
||||||
|
if (aiUser.getId() == null) {
|
||||||
|
return error("用户主键不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(aiUser.getPassword())) {
|
||||||
|
return error("新密码不能为空");
|
||||||
|
}
|
||||||
|
subteamScopeService.assertAiUserInTeam(aiUser.getId());
|
||||||
|
aiUser.setNewPassword(aiUser.getPassword());
|
||||||
|
return toAjax(aiUserService.updatePassword(aiUser));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:user:edit')")
|
||||||
|
@Log(title = "团队后台用户", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping("/changeStatus")
|
||||||
|
public AjaxResult changeStatus(@RequestBody AiUser aiUser) {
|
||||||
|
if (aiUser.getId() == null) {
|
||||||
|
return error("用户主键不能为空");
|
||||||
|
}
|
||||||
|
subteamScopeService.assertAiUserInTeam(aiUser.getId());
|
||||||
|
aiUser.setUpdateBy(getUsername());
|
||||||
|
return toAjax(aiUserService.updateUserStatus(aiUser));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.ruoyi.web.controller.subteam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.ai.domain.AiOrder;
|
||||||
|
import com.ruoyi.ai.service.IAiOrderService;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamDataQueryService;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamScopeService;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/subteam/video-order")
|
||||||
|
public class SubteamVideoOrderController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamDataQueryService subteamDataQueryService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamScopeService subteamScopeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAiOrderService aiOrderService;
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:videoOrder:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(AiOrder query) {
|
||||||
|
startPage();
|
||||||
|
List<AiOrder> list = subteamDataQueryService.selectVideoOrders(query);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('subteam:videoOrder:query')")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable Long id) {
|
||||||
|
subteamScopeService.assertAiOrderBelongsToTeam(id);
|
||||||
|
return success(aiOrderService.selectAiOrderById(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -74,20 +74,13 @@ public class BalanceChangerConstants {
|
||||||
public static final int SYSTEM_OPERATION = 11;
|
public static final int SYSTEM_OPERATION = 11;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门积分下放至用户(sys_dept.balance → ai_user.balance)
|
* 部门下发积分给用户
|
||||||
*/
|
*/
|
||||||
public static final int DEPT_SCORE_ISSUE = 12;
|
public static final int DEPT_SCORE_ISSUE = 12;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户积分回收至部门(ai_user.balance → sys_dept.balance)
|
* 从用户回收积分到部门
|
||||||
*/
|
*/
|
||||||
public static final int DEPT_SCORE_RECLAIM = 13;
|
public static final int DEPT_SCORE_RECLAIM = 13;
|
||||||
|
|
||||||
public static class OrderNoPrefix {
|
|
||||||
// 团队充值、退款订单号前缀
|
|
||||||
public static final String RECHARGE_REFUND_PREFIX = "RE";
|
|
||||||
|
|
||||||
// 团队积分下放、回收单号前缀
|
|
||||||
public static final String ISSUE_RECLAIM_PREFIX = "IS";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
<el-form-item label="${comment}" prop="${column.javaField}">
|
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.${column.javaField}"
|
v-model="queryParams.${column.javaField}"
|
||||||
placeholder="请输入${comment}"
|
placeholder="请输入ID"
|
||||||
clearable
|
clearable
|
||||||
@keyup.enter="handleQuery"
|
@keyup.enter="handleQuery"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,56 +1,67 @@
|
||||||
package com.ruoyi.ai.domain;
|
package com.ruoyi.ai.domain;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import java.math.BigDecimal;
|
||||||
import com.ruoyi.common.annotation.Excel;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import com.ruoyi.common.annotation.Excel;
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 充值/退款订单 ai_charge_refund_order
|
* 团队(部门)充值退款订单对象 ai_charge_refund_order
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("ai_charge_refund_order")
|
@TableName("ai_charge_refund_order")
|
||||||
public class AiChargeRefundOrder implements Serializable {
|
public class AiChargeRefundOrder extends BaseEntity {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 主键ID */
|
||||||
@TableId(type = IdType.AUTO)
|
@TableId(type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/** 删除标志(0代表存在 2代表删除) */
|
/** 删除标志(0代表存在 2代表删除) */
|
||||||
private String delFlag;
|
private String delFlag;
|
||||||
|
|
||||||
private Long createBy;
|
/** 订单编号 */
|
||||||
|
@Excel(name = "订单编号")
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date createTime;
|
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date updateTime;
|
|
||||||
|
|
||||||
private String orderNum;
|
private String orderNum;
|
||||||
|
|
||||||
|
/** 第三方单号(预留) */
|
||||||
|
@Excel(name = "第三方单号(预留)")
|
||||||
private String thirdPartyOrderNum;
|
private String thirdPartyOrderNum;
|
||||||
|
|
||||||
|
/** 部门ID */
|
||||||
|
@Excel(name = "部门ID")
|
||||||
private Long deptId;
|
private Long deptId;
|
||||||
|
|
||||||
/** 订单类型:0-充值 1-退款 */
|
/** 团队名称(列表/导出关联查询,非表字段) */
|
||||||
// ChargeRefundOrderType
|
@TableField(exist = false)
|
||||||
private Integer orderType;
|
@Excel(name = "团队名称")
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
/** 订单类型(0-充值;1-退款;2-手动修改) */
|
||||||
|
@Excel(name = "订单类型", readConverterExp = "0=充值,1=退款,2=手动修改")
|
||||||
|
private Long orderType;
|
||||||
|
|
||||||
|
/** 金额(元) */
|
||||||
|
@Excel(name = "金额(元)")
|
||||||
private BigDecimal money;
|
private BigDecimal money;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 积分变动:充值/退款为绝对值(退款在统计中按负数计入);
|
||||||
|
* 手动修改可为正(增加)或负(扣减)。
|
||||||
|
*/
|
||||||
|
@Excel(name = "积分")
|
||||||
private BigDecimal amount;
|
private BigDecimal amount;
|
||||||
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
/** 状态:0-进行中 1-已完成 2-失败 */
|
/** 状态:0-进行中 1-已完成 2-失败 */
|
||||||
// ChargeRefundOrderStatusType
|
@Excel(name = "状态", readConverterExp = "0=进行中,1=已完成,2=失败")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,44 @@
|
||||||
package com.ruoyi.ai.domain;
|
package com.ruoyi.ai.domain;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
import com.ruoyi.common.annotation.Excel;
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门方舟配置 ai_dept_ark_config
|
* 团队(部门)对应火山引擎配置对象 ai_dept_ark_config
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("ai_dept_ark_config")
|
@TableName("ai_dept_ark_config")
|
||||||
public class AiDeptArkConfig implements Serializable {
|
public class AiDeptArkConfig extends BaseEntity {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** $column.columnComment */
|
||||||
@TableId(type = IdType.AUTO)
|
@TableId(type = IdType.AUTO)
|
||||||
private Long id;
|
private String id;
|
||||||
|
|
||||||
|
/** 部门ID */
|
||||||
|
@Excel(name = "部门ID")
|
||||||
private Long deptId;
|
private Long deptId;
|
||||||
|
|
||||||
/** 模型参数 JSON */
|
/** 视频模型列表JSON(label+value) */
|
||||||
|
@Excel(name = "视频模型列表JSON(label+value)")
|
||||||
private String modelParm;
|
private String modelParm;
|
||||||
|
|
||||||
|
/** Byte project,加密 */
|
||||||
|
@Excel(name = "Byte project,加密")
|
||||||
private String project;
|
private String project;
|
||||||
|
|
||||||
|
/** Byte API Key,加密 */
|
||||||
|
@Excel(name = "Byte API Key,加密")
|
||||||
private String byteApiKey;
|
private String byteApiKey;
|
||||||
|
|
||||||
private Long createBy;
|
|
||||||
|
|
||||||
private Long updateBy;
|
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date createTime;
|
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date updateTime;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,49 @@
|
||||||
package com.ruoyi.ai.domain;
|
package com.ruoyi.ai.domain;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import lombok.Data;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import com.baomidou.mybatisplus.annotation.EnumValue;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import com.ruoyi.common.annotation.Excel;
|
import com.ruoyi.common.annotation.Excel;
|
||||||
import lombok.Data;
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 集团余额变动记录 ai_group_balance_change_record
|
* 团队(部门)余额变动对象 ai_group_balance_change_record
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("ai_group_balance_change_record")
|
@TableName("ai_group_balance_change_record")
|
||||||
public class AiGroupBalanceChangeRecord implements Serializable {
|
public class AiGroupBalanceChangeRecord extends BaseEntity {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** $column.columnComment */
|
||||||
@TableId(type = IdType.AUTO)
|
@TableId(type = IdType.AUTO)
|
||||||
private Long id;
|
private String id;
|
||||||
|
|
||||||
/** 关联订单号 */
|
/** 关联(充值/退款)订单号 */
|
||||||
|
@Excel(name = "关联(充值/退款)订单号")
|
||||||
private String relationOrderNo;
|
private String relationOrderNo;
|
||||||
|
|
||||||
|
/** 部门ID */
|
||||||
|
@Excel(name = "部门ID")
|
||||||
private Long deptId;
|
private Long deptId;
|
||||||
|
|
||||||
/** 类型:0-充值 1-退款 2-下发 3-消费 4-手动修改 */
|
/** 操作类型(0-充值、1-退款、2-下发、3-回收、4-手动修改) */
|
||||||
// GroupBalanceChangeType
|
@Excel(name = "操作类型", readConverterExp = "0=-充值、1-退款、2-下发、3-回收、4-手动修改")
|
||||||
private Integer type;
|
private Long type;
|
||||||
|
|
||||||
|
/** 变更金额 */
|
||||||
|
@Excel(name = "变更金额")
|
||||||
private BigDecimal changeAmount;
|
private BigDecimal changeAmount;
|
||||||
|
|
||||||
|
/** 变更后金额 */
|
||||||
|
@Excel(name = "变更后金额")
|
||||||
private BigDecimal resultAmount;
|
private BigDecimal resultAmount;
|
||||||
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
private Long createBy;
|
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date createTime;
|
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date updateTime;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,63 @@
|
||||||
package com.ruoyi.ai.domain;
|
package com.ruoyi.ai.domain;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import java.math.BigDecimal;
|
||||||
import com.ruoyi.common.annotation.Excel;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import com.ruoyi.common.annotation.Excel;
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视频报表数据 ai_video_report_data
|
* AI视频生成统计数据,作为其他统计报的数据源对象 ai_video_report_data
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("ai_video_report_data")
|
@TableName("ai_video_report_data")
|
||||||
public class AiVideoReportData implements Serializable {
|
public class AiVideoReportData extends BaseEntity {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 主键 */
|
/** $column.columnComment */
|
||||||
@TableId(type = IdType.AUTO)
|
@TableId(type = IdType.AUTO)
|
||||||
private Long id;
|
private String id;
|
||||||
|
|
||||||
/** 统计日期键(varchar) */
|
/** 统计时间,到小时(yyyyMMddHH) */
|
||||||
|
@Excel(name = "统计时间,到小时('%Y-%m-%d %H')")
|
||||||
private String dateKey;
|
private String dateKey;
|
||||||
|
|
||||||
/** 部门ID */
|
/** 部门ID */
|
||||||
|
@Excel(name = "部门ID")
|
||||||
private Long deptId;
|
private Long deptId;
|
||||||
|
|
||||||
/** 用户ID */
|
/** 用户ID,用户表的ID,延用其他表设计 */
|
||||||
|
@Excel(name = "用户ID,用户表的ID,延用其他表设计 ")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
/** 积分/分数统计 */
|
/** 消耗积分,按任务创建时间统计 */
|
||||||
|
@Excel(name = "消耗积分,按任务创建时间统计")
|
||||||
private BigDecimal score;
|
private BigDecimal score;
|
||||||
|
|
||||||
/** 订单数 */
|
/** 实际订单数,只统计已生成成功的任务 */
|
||||||
|
@Excel(name = "实际订单数,只统计已生成成功的任务")
|
||||||
private Long orderCount;
|
private Long orderCount;
|
||||||
|
|
||||||
/** 消耗 tokens */
|
/** 三方消耗tokens数量,按任务创建时间统计 */
|
||||||
|
@Excel(name = "三方消耗tokens数量,按任务创建时间统计")
|
||||||
private Long useTokens;
|
private Long useTokens;
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
/** 实际充值积分(充值-退款) */
|
||||||
private Date createTime;
|
@Excel(name = "实际充值积分(充值-退款)")
|
||||||
|
private BigDecimal rechargeScore;
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
/** 团队名称(查询结果展示字段) */
|
||||||
private Date updateTime;
|
@TableField(exist = false)
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
/** 查询日期(yyyyMMdd) */
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String statDate;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import java.util.List;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.ruoyi.ai.domain.AiBalanceChangeRecord;
|
import com.ruoyi.ai.domain.AiBalanceChangeRecord;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 余额使用记录Mapper接口
|
* 余额使用记录Mapper接口
|
||||||
|
|
@ -17,4 +18,7 @@ public interface AiBalanceChangeRecordMapper extends BaseMapper<AiBalanceChangeR
|
||||||
int deleteAiBalanceChangeRecordById(Long id);
|
int deleteAiBalanceChangeRecordById(Long id);
|
||||||
|
|
||||||
List<AiBalanceChangeRecord> selectAiBalanceChangeRecordList(AiBalanceChangeRecord aiBalanceChangeRecord);
|
List<AiBalanceChangeRecord> selectAiBalanceChangeRecordList(AiBalanceChangeRecord aiBalanceChangeRecord);
|
||||||
|
|
||||||
|
List<AiBalanceChangeRecord> selectAiBalanceChangeRecordListByAiUserDept(@Param("q") AiBalanceChangeRecord q,
|
||||||
|
@Param("deptId") Long deptId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,24 @@
|
||||||
package com.ruoyi.ai.mapper;
|
package com.ruoyi.ai.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 充值/退款订单 Mapper
|
* 团队(部门)充值退款订单Mapper接口
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
public interface AiChargeRefundOrderMapper extends BaseMapper<AiChargeRefundOrder> {
|
public interface AiChargeRefundOrderMapper extends BaseMapper<AiChargeRefundOrder> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表(关联团队名称,支持按 deptName 模糊查)
|
||||||
|
*/
|
||||||
|
List<AiChargeRefundOrder> selectAiChargeRefundOrderList(AiChargeRefundOrder query);
|
||||||
|
|
||||||
|
AiChargeRefundOrder selectAiChargeRefundOrderById(Long id);
|
||||||
|
|
||||||
|
int deleteAiChargeRefundOrderByIds(Long[] ids);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
package com.ruoyi.ai.mapper;
|
package com.ruoyi.ai.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.ruoyi.ai.domain.AiDeptArkConfig;
|
import com.ruoyi.ai.domain.AiDeptArkConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门方舟配置 Mapper
|
* 团队(部门)对应火山引擎配置Mapper接口
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
public interface AiDeptArkConfigMapper extends BaseMapper<AiDeptArkConfig> {
|
public interface AiDeptArkConfigMapper extends BaseMapper<AiDeptArkConfig> {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
package com.ruoyi.ai.mapper;
|
package com.ruoyi.ai.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.ruoyi.ai.domain.AiGroupBalanceChangeRecord;
|
import com.ruoyi.ai.domain.AiGroupBalanceChangeRecord;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 集团余额变动记录 Mapper
|
* 团队(部门)余额变动Mapper接口
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
public interface AiGroupBalanceChangeRecordMapper extends BaseMapper<AiGroupBalanceChangeRecord> {
|
public interface AiGroupBalanceChangeRecordMapper extends BaseMapper<AiGroupBalanceChangeRecord> {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,74 @@
|
||||||
package com.ruoyi.ai.mapper;
|
package com.ruoyi.ai.mapper;
|
||||||
|
|
||||||
|
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.common.core.dto.DeptSummaryDTO;
|
import com.ruoyi.system.domain.subteam.SubteamVideoMetrics;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Update;
|
import org.apache.ibatis.annotations.Update;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视频报表数据 Mapper
|
* AI视频生成统计数据,作为其他统计报的数据源Mapper接口
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
public interface AiVideoReportDataMapper extends BaseMapper<AiVideoReportData> {
|
public interface AiVideoReportDataMapper extends BaseMapper<AiVideoReportData> {
|
||||||
@Select("SELECT SUM(order_count) as order_count,SUM(score) as score FROM ai_video_report_data " +
|
/**
|
||||||
" where dept_id=#{deptId} and date_key>=#{startHour} and date_key<=#{endHour}")
|
* 团队每日消耗统计查询(按天、团队聚合)。
|
||||||
DeptSummaryDTO selectOneDeptSummaryData(Long deptId, String startHour, String endHour);
|
*
|
||||||
|
* @param statDate 统计日期(yyyyMMdd)
|
||||||
|
* @param deptId 团队部门ID(精确匹配)
|
||||||
|
* @return 聚合结果
|
||||||
|
*/
|
||||||
|
List<AiVideoReportData> selectTeamDailyConsumeList(@Param("statDate") String statDate,
|
||||||
|
@Param("deptId") Long deptId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按团队部门、日期聚合(团队后台消耗统计)
|
||||||
|
*/
|
||||||
|
List<AiVideoReportData> selectTeamDailyConsumeByDeptId(@Param("statDate") String statDate,
|
||||||
|
@Param("deptId") Long deptId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 近 N 日(含)按 date_key 日维度汇总消耗积分与成功订单数
|
||||||
|
*/
|
||||||
|
SubteamVideoMetrics selectDeptVideoMetricsBetween(@Param("deptId") Long deptId,
|
||||||
|
@Param("startDay") String startDay,
|
||||||
|
@Param("endDay") String endDay);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按(date_key, dept_id, user_id)聚合累加视频消耗统计。
|
||||||
|
*
|
||||||
|
* @param dateKey 小时Key(yyyyMMddHH)
|
||||||
|
* @param deptId 部门ID
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param score 消耗积分增量
|
||||||
|
* @param orderCount 订单数增量
|
||||||
|
* @param useTokens 三方tokens增量
|
||||||
|
* @return 影响行数
|
||||||
|
*/
|
||||||
|
int upsertVideoConsumeIncrement(@Param("dateKey") String dateKey,
|
||||||
|
@Param("deptId") Long deptId,
|
||||||
|
@Param("userId") Long userId,
|
||||||
|
@Param("score") BigDecimal score,
|
||||||
|
@Param("orderCount") Long orderCount,
|
||||||
|
@Param("useTokens") Long useTokens);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按(date_key, dept_id, user_id=0)聚合累加充值积分统计。
|
||||||
|
*
|
||||||
|
* @param dateKey 小时Key(yyyyMMddHH)
|
||||||
|
* @param deptId 部门ID
|
||||||
|
* @param rechargeScore 充值积分增量
|
||||||
|
* @return 影响行数
|
||||||
|
*/
|
||||||
|
int upsertRechargeScoreIncrement(@Param("dateKey") String dateKey,
|
||||||
|
@Param("deptId") Long deptId,
|
||||||
|
@Param("rechargeScore") BigDecimal rechargeScore);
|
||||||
|
|
||||||
void addNewOrderReportData(AiOrder aiOrder);
|
void addNewOrderReportData(AiOrder aiOrder);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,71 @@
|
||||||
package com.ruoyi.ai.service;
|
package com.ruoyi.ai.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 充值/退款订单 Service
|
* 团队(部门)充值退款订单Service接口
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
public interface IAiChargeRefundOrderService {
|
public interface IAiChargeRefundOrderService {
|
||||||
|
|
||||||
AiChargeRefundOrder selectById(Long id);
|
/**
|
||||||
|
* 查询团队(部门)充值退款订单
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)充值退款订单主键
|
||||||
|
* @return 团队(部门)充值退款订单
|
||||||
|
*/
|
||||||
|
AiChargeRefundOrder selectAiChargeRefundOrderById(Long id);
|
||||||
|
|
||||||
int insert(AiChargeRefundOrder entity);
|
/**
|
||||||
|
* 查询团队(部门)充值退款订单列表
|
||||||
|
*
|
||||||
|
* @param aiChargeRefundOrder 团队(部门)充值退款订单
|
||||||
|
* @return 团队(部门)充值退款订单集合
|
||||||
|
*/
|
||||||
|
List<AiChargeRefundOrder> selectAiChargeRefundOrderList(AiChargeRefundOrder aiChargeRefundOrder);
|
||||||
|
|
||||||
int updateById(AiChargeRefundOrder entity);
|
/**
|
||||||
|
* 分页查询团队(部门)充值退款订单列表
|
||||||
|
*
|
||||||
|
* @param aiChargeRefundOrder 团队(部门)充值退款订单
|
||||||
|
* @return 团队(部门)充值退款订单集合
|
||||||
|
*/
|
||||||
|
IPage<AiChargeRefundOrder> selectAiChargeRefundOrderPage(Page page, AiChargeRefundOrder aiChargeRefundOrder);
|
||||||
|
|
||||||
int deleteById(Long id);
|
/**
|
||||||
|
* 新增团队(部门)充值退款订单
|
||||||
|
*
|
||||||
|
* @param aiChargeRefundOrder 团队(部门)充值退款订单
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int insertAiChargeRefundOrder(AiChargeRefundOrder aiChargeRefundOrder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改团队(部门)充值退款订单
|
||||||
|
*
|
||||||
|
* @param aiChargeRefundOrder 团队(部门)充值退款订单
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int updateAiChargeRefundOrder(AiChargeRefundOrder aiChargeRefundOrder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除团队(部门)充值退款订单
|
||||||
|
*
|
||||||
|
* @param ids 需要删除的团队(部门)充值退款订单主键集合
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int deleteAiChargeRefundOrderByIds(Long[] ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除团队(部门)充值退款订单信息
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)充值退款订单主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int deleteAiChargeRefundOrderById(Long id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,71 @@
|
||||||
package com.ruoyi.ai.service;
|
package com.ruoyi.ai.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import com.ruoyi.ai.domain.AiDeptArkConfig;
|
import com.ruoyi.ai.domain.AiDeptArkConfig;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门方舟配置 Service
|
* 团队(部门)对应火山引擎配置Service接口
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
public interface IAiDeptArkConfigService {
|
public interface IAiDeptArkConfigService {
|
||||||
|
|
||||||
AiDeptArkConfig selectById(Long id);
|
/**
|
||||||
|
* 查询团队(部门)对应火山引擎配置
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)对应火山引擎配置主键
|
||||||
|
* @return 团队(部门)对应火山引擎配置
|
||||||
|
*/
|
||||||
|
AiDeptArkConfig selectAiDeptArkConfigById(String id);
|
||||||
|
|
||||||
int insert(AiDeptArkConfig entity);
|
/**
|
||||||
|
* 查询团队(部门)对应火山引擎配置列表
|
||||||
|
*
|
||||||
|
* @param aiDeptArkConfig 团队(部门)对应火山引擎配置
|
||||||
|
* @return 团队(部门)对应火山引擎配置集合
|
||||||
|
*/
|
||||||
|
List<AiDeptArkConfig> selectAiDeptArkConfigList(AiDeptArkConfig aiDeptArkConfig);
|
||||||
|
|
||||||
int updateById(AiDeptArkConfig entity);
|
/**
|
||||||
|
* 分页查询团队(部门)对应火山引擎配置列表
|
||||||
|
*
|
||||||
|
* @param aiDeptArkConfig 团队(部门)对应火山引擎配置
|
||||||
|
* @return 团队(部门)对应火山引擎配置集合
|
||||||
|
*/
|
||||||
|
IPage<AiDeptArkConfig> selectAiDeptArkConfigPage(Page page, AiDeptArkConfig aiDeptArkConfig);
|
||||||
|
|
||||||
int deleteById(Long id);
|
/**
|
||||||
|
* 新增团队(部门)对应火山引擎配置
|
||||||
|
*
|
||||||
|
* @param aiDeptArkConfig 团队(部门)对应火山引擎配置
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int insertAiDeptArkConfig(AiDeptArkConfig aiDeptArkConfig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改团队(部门)对应火山引擎配置
|
||||||
|
*
|
||||||
|
* @param aiDeptArkConfig 团队(部门)对应火山引擎配置
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int updateAiDeptArkConfig(AiDeptArkConfig aiDeptArkConfig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除团队(部门)对应火山引擎配置
|
||||||
|
*
|
||||||
|
* @param ids 需要删除的团队(部门)对应火山引擎配置主键集合
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int deleteAiDeptArkConfigByIds(String[] ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除团队(部门)对应火山引擎配置信息
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)对应火山引擎配置主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int deleteAiDeptArkConfigById(String id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,71 @@
|
||||||
package com.ruoyi.ai.service;
|
package com.ruoyi.ai.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import com.ruoyi.ai.domain.AiGroupBalanceChangeRecord;
|
import com.ruoyi.ai.domain.AiGroupBalanceChangeRecord;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 集团余额变动记录 Service
|
* 团队(部门)余额变动Service接口
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
public interface IAiGroupBalanceChangeRecordService {
|
public interface IAiGroupBalanceChangeRecordService {
|
||||||
|
|
||||||
AiGroupBalanceChangeRecord selectById(Long id);
|
/**
|
||||||
|
* 查询团队(部门)余额变动
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)余额变动主键
|
||||||
|
* @return 团队(部门)余额变动
|
||||||
|
*/
|
||||||
|
AiGroupBalanceChangeRecord selectAiGroupBalanceChangeRecordById(String id);
|
||||||
|
|
||||||
int insert(AiGroupBalanceChangeRecord entity);
|
/**
|
||||||
|
* 查询团队(部门)余额变动列表
|
||||||
|
*
|
||||||
|
* @param aiGroupBalanceChangeRecord 团队(部门)余额变动
|
||||||
|
* @return 团队(部门)余额变动集合
|
||||||
|
*/
|
||||||
|
List<AiGroupBalanceChangeRecord> selectAiGroupBalanceChangeRecordList(AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord);
|
||||||
|
|
||||||
int updateById(AiGroupBalanceChangeRecord entity);
|
/**
|
||||||
|
* 分页查询团队(部门)余额变动列表
|
||||||
|
*
|
||||||
|
* @param aiGroupBalanceChangeRecord 团队(部门)余额变动
|
||||||
|
* @return 团队(部门)余额变动集合
|
||||||
|
*/
|
||||||
|
IPage<AiGroupBalanceChangeRecord> selectAiGroupBalanceChangeRecordPage(Page page, AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord);
|
||||||
|
|
||||||
int deleteById(Long id);
|
/**
|
||||||
|
* 新增团队(部门)余额变动
|
||||||
|
*
|
||||||
|
* @param aiGroupBalanceChangeRecord 团队(部门)余额变动
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int insertAiGroupBalanceChangeRecord(AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改团队(部门)余额变动
|
||||||
|
*
|
||||||
|
* @param aiGroupBalanceChangeRecord 团队(部门)余额变动
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int updateAiGroupBalanceChangeRecord(AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除团队(部门)余额变动
|
||||||
|
*
|
||||||
|
* @param ids 需要删除的团队(部门)余额变动主键集合
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int deleteAiGroupBalanceChangeRecordByIds(String[] ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除团队(部门)余额变动信息
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)余额变动主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int deleteAiGroupBalanceChangeRecordById(String id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,107 @@
|
||||||
package com.ruoyi.ai.service;
|
package com.ruoyi.ai.service;
|
||||||
|
|
||||||
import com.ruoyi.ai.domain.AiVideoReportData;
|
import java.util.List;
|
||||||
import com.ruoyi.common.core.dto.DeptSummaryDTO;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import com.ruoyi.ai.domain.AiVideoReportData;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视频报表数据 Service
|
* AI视频生成统计数据,作为其他统计报的数据源Service接口
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
public interface IAiVideoReportDataService {
|
public interface IAiVideoReportDataService {
|
||||||
AiVideoReportData selectById(Long id);
|
|
||||||
|
|
||||||
int insert(AiVideoReportData entity);
|
/**
|
||||||
|
* 查询AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*
|
||||||
|
* @param id AI视频生成统计数据,作为其他统计报的数据源主键
|
||||||
|
* @return AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*/
|
||||||
|
AiVideoReportData selectAiVideoReportDataById(String id);
|
||||||
|
|
||||||
DeptSummaryDTO getSevenDayDeptSummaryData(Long deptId);
|
/**
|
||||||
|
* 查询AI视频生成统计数据,作为其他统计报的数据源列表
|
||||||
|
*
|
||||||
|
* @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
* @return AI视频生成统计数据,作为其他统计报的数据源集合
|
||||||
|
*/
|
||||||
|
List<AiVideoReportData> selectAiVideoReportDataList(AiVideoReportData aiVideoReportData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询AI视频生成统计数据,作为其他统计报的数据源列表
|
||||||
|
*
|
||||||
|
* @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
* @return AI视频生成统计数据,作为其他统计报的数据源集合
|
||||||
|
*/
|
||||||
|
IPage<AiVideoReportData> selectAiVideoReportDataPage(Page page, AiVideoReportData aiVideoReportData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*
|
||||||
|
* @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int insertAiVideoReportData(AiVideoReportData aiVideoReportData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*
|
||||||
|
* @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int updateAiVideoReportData(AiVideoReportData aiVideoReportData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*
|
||||||
|
* @param ids 需要删除的AI视频生成统计数据,作为其他统计报的数据源主键集合
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int deleteAiVideoReportDataByIds(String[] ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除AI视频生成统计数据,作为其他统计报的数据源信息
|
||||||
|
*
|
||||||
|
* @param id AI视频生成统计数据,作为其他统计报的数据源主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
int deleteAiVideoReportDataById(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 团队每日消耗统计查询(按天、团队聚合)。
|
||||||
|
*
|
||||||
|
* @param statDate 统计日期(yyyyMMdd,必填)
|
||||||
|
* @param deptId 团队部门ID(必填,精确匹配)
|
||||||
|
* @return 聚合后的统计数据
|
||||||
|
*/
|
||||||
|
List<AiVideoReportData> selectTeamDailyConsumeList(String statDate, Long deptId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 团队每日消耗(按部门 ID,团队后台)
|
||||||
|
*/
|
||||||
|
List<AiVideoReportData> selectTeamDailyConsumeByDeptId(String statDate, Long deptId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按视频订单成功结果回写统计来源表(按小时、部门、账号聚合累加)。
|
||||||
|
*
|
||||||
|
* @param createTime 任务创建时间
|
||||||
|
* @param deptId 部门ID
|
||||||
|
* @param userId 账号ID
|
||||||
|
* @param score 消耗积分增量
|
||||||
|
* @param useTokens 三方tokens增量
|
||||||
|
*/
|
||||||
|
void syncVideoConsumeIncrement(Date createTime, Long deptId, Long userId, BigDecimal score, Long useTokens);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按充值/退款成功结果回写统计来源表(按小时、部门聚合累加)。
|
||||||
|
*
|
||||||
|
* @param createTime 订单创建时间
|
||||||
|
* @param deptId 部门ID
|
||||||
|
* @param rechargeScore 实际充值积分增量(充值为正,退款为负)
|
||||||
|
*/
|
||||||
|
void syncRechargeScoreIncrement(Date createTime, Long deptId, BigDecimal rechargeScore);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,30 @@
|
||||||
package com.ruoyi.ai.service.impl;
|
package com.ruoyi.ai.service.impl;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.ruoyi.common.enums.ChargeRefundOrderStatusType;
|
||||||
|
import com.ruoyi.common.enums.ChargeRefundOrderType;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.uuid.IdUtils;
|
||||||
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.domain.AiChargeRefundOrder;
|
|
||||||
import com.ruoyi.ai.mapper.AiChargeRefundOrderMapper;
|
import com.ruoyi.ai.mapper.AiChargeRefundOrderMapper;
|
||||||
|
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
||||||
|
import com.ruoyi.ai.service.IAiVideoReportDataService;
|
||||||
import com.ruoyi.ai.service.IAiChargeRefundOrderService;
|
import com.ruoyi.ai.service.IAiChargeRefundOrderService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 充值/退款订单 Service 实现
|
* 团队(部门)充值退款订单Service业务层处理
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class AiChargeRefundOrderServiceImpl implements IAiChargeRefundOrderService {
|
public class AiChargeRefundOrderServiceImpl implements IAiChargeRefundOrderService {
|
||||||
|
|
@ -16,23 +32,149 @@ public class AiChargeRefundOrderServiceImpl implements IAiChargeRefundOrderServi
|
||||||
@Autowired
|
@Autowired
|
||||||
private AiChargeRefundOrderMapper aiChargeRefundOrderMapper;
|
private AiChargeRefundOrderMapper aiChargeRefundOrderMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAiVideoReportDataService aiVideoReportDataService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询团队(部门)充值退款订单
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)充值退款订单主键
|
||||||
|
* @return 团队(部门)充值退款订单
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public AiChargeRefundOrder selectById(Long id) {
|
public AiChargeRefundOrder selectAiChargeRefundOrderById(Long id) {
|
||||||
return aiChargeRefundOrderMapper.selectById(id);
|
return aiChargeRefundOrderMapper.selectAiChargeRefundOrderById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询团队(部门)充值退款订单列表
|
||||||
|
*
|
||||||
|
* @param aiChargeRefundOrder 团队(部门)充值退款订单
|
||||||
|
* @return 团队(部门)充值退款订单
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int insert(AiChargeRefundOrder entity) {
|
public List<AiChargeRefundOrder> selectAiChargeRefundOrderList(AiChargeRefundOrder aiChargeRefundOrder) {
|
||||||
return aiChargeRefundOrderMapper.insert(entity);
|
return aiChargeRefundOrderMapper.selectAiChargeRefundOrderList(aiChargeRefundOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询团队(部门)充值退款订单列表
|
||||||
|
*
|
||||||
|
* @param aiChargeRefundOrder 团队(部门)充值退款订单
|
||||||
|
* @return 团队(部门)充值退款订单
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int updateById(AiChargeRefundOrder entity) {
|
public IPage<AiChargeRefundOrder> selectAiChargeRefundOrderPage(Page page, AiChargeRefundOrder aiChargeRefundOrder) {
|
||||||
return aiChargeRefundOrderMapper.updateById(entity);
|
if (aiChargeRefundOrder != null) {
|
||||||
|
aiChargeRefundOrder.setDeptName(null);
|
||||||
|
}
|
||||||
|
LambdaQueryWrapper<AiChargeRefundOrder> query = Wrappers.lambdaQuery(aiChargeRefundOrder);
|
||||||
|
query.eq(AiChargeRefundOrder::getDelFlag, "0");
|
||||||
|
return aiChargeRefundOrderMapper.selectPage(page, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增团队(部门)充值退款订单
|
||||||
|
*
|
||||||
|
* @param aiChargeRefundOrder 团队(部门)充值退款订单
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int deleteById(Long id) {
|
public int insertAiChargeRefundOrder(AiChargeRefundOrder aiChargeRefundOrder) {
|
||||||
|
validateChargeAmount(aiChargeRefundOrder);
|
||||||
|
if (StringUtils.isEmpty(aiChargeRefundOrder.getOrderNum())) {
|
||||||
|
aiChargeRefundOrder.setOrderNum("CR" + IdUtils.fastSimpleUUID());
|
||||||
|
}
|
||||||
|
if (aiChargeRefundOrder.getStatus() == null) {
|
||||||
|
aiChargeRefundOrder.setStatus(ChargeRefundOrderStatusType.SUCCESS.getCode());
|
||||||
|
}
|
||||||
|
aiChargeRefundOrder.setDelFlag("0");
|
||||||
|
aiChargeRefundOrder.setCreateBy(SecurityUtils.getUsername());
|
||||||
|
aiChargeRefundOrder.setCreateTime(DateUtils.getNowDate());
|
||||||
|
int rows = aiChargeRefundOrderMapper.insert(aiChargeRefundOrder);
|
||||||
|
syncRechargeReportData(aiChargeRefundOrder);
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改团队(部门)充值退款订单
|
||||||
|
*
|
||||||
|
* @param aiChargeRefundOrder 团队(部门)充值退款订单
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int updateAiChargeRefundOrder(AiChargeRefundOrder aiChargeRefundOrder) {
|
||||||
|
validateChargeAmount(aiChargeRefundOrder);
|
||||||
|
aiChargeRefundOrder.setUpdateTime(DateUtils.getNowDate());
|
||||||
|
int rows = aiChargeRefundOrderMapper.updateById(aiChargeRefundOrder);
|
||||||
|
if (rows > 0) {
|
||||||
|
AiChargeRefundOrder fresh = aiChargeRefundOrderMapper.selectById(aiChargeRefundOrder.getId());
|
||||||
|
syncRechargeReportData(fresh);
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除团队(部门)充值退款订单
|
||||||
|
*
|
||||||
|
* @param ids 需要删除的团队(部门)充值退款订单主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int deleteAiChargeRefundOrderByIds(Long[] ids)
|
||||||
|
{
|
||||||
|
return aiChargeRefundOrderMapper.deleteAiChargeRefundOrderByIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除团队(部门)充值退款订单信息
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)充值退款订单主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int deleteAiChargeRefundOrderById(Long id)
|
||||||
|
{
|
||||||
return aiChargeRefundOrderMapper.deleteById(id);
|
return aiChargeRefundOrderMapper.deleteById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 充值/退款单完成后,按“订单创建时间”同步到团队统计来源表。
|
||||||
|
*
|
||||||
|
* @param order 充值退款订单
|
||||||
|
*/
|
||||||
|
private void syncRechargeReportData(AiChargeRefundOrder order) {
|
||||||
|
if (order == null || order.getCreateTime() == null || order.getDeptId() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (order.getStatus() == null || order.getStatus() != ChargeRefundOrderStatusType.SUCCESS.getCode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (order.getOrderType() == null || order.getAmount() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BigDecimal rechargeScore;
|
||||||
|
int type = order.getOrderType().intValue();
|
||||||
|
if (type == ChargeRefundOrderType.REFUND.getCode()) {
|
||||||
|
rechargeScore = order.getAmount().negate();
|
||||||
|
} else {
|
||||||
|
rechargeScore = order.getAmount();
|
||||||
|
}
|
||||||
|
aiVideoReportDataService.syncRechargeScoreIncrement(order.getCreateTime(), order.getDeptId(), rechargeScore);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 充值、退款积分须为非负数;手动修改允许正负。
|
||||||
|
*/
|
||||||
|
private void validateChargeAmount(AiChargeRefundOrder o) {
|
||||||
|
if (o.getOrderType() == null || o.getAmount() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int t = o.getOrderType().intValue();
|
||||||
|
if (t == ChargeRefundOrderType.CHARGE.getCode() || t == ChargeRefundOrderType.REFUND.getCode()) {
|
||||||
|
if (o.getAmount().compareTo(BigDecimal.ZERO) < 0) {
|
||||||
|
throw new ServiceException("充值、退款类型的积分须填写非负数");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,23 @@
|
||||||
package com.ruoyi.ai.service.impl;
|
package com.ruoyi.ai.service.impl;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
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.domain.AiDeptArkConfig;
|
|
||||||
import com.ruoyi.ai.mapper.AiDeptArkConfigMapper;
|
import com.ruoyi.ai.mapper.AiDeptArkConfigMapper;
|
||||||
|
import com.ruoyi.ai.domain.AiDeptArkConfig;
|
||||||
import com.ruoyi.ai.service.IAiDeptArkConfigService;
|
import com.ruoyi.ai.service.IAiDeptArkConfigService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门方舟配置 Service 实现
|
* 团队(部门)对应火山引擎配置Service业务层处理
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class AiDeptArkConfigServiceImpl implements IAiDeptArkConfigService {
|
public class AiDeptArkConfigServiceImpl implements IAiDeptArkConfigService {
|
||||||
|
|
@ -16,23 +25,89 @@ public class AiDeptArkConfigServiceImpl implements IAiDeptArkConfigService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private AiDeptArkConfigMapper aiDeptArkConfigMapper;
|
private AiDeptArkConfigMapper aiDeptArkConfigMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询团队(部门)对应火山引擎配置
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)对应火山引擎配置主键
|
||||||
|
* @return 团队(部门)对应火山引擎配置
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public AiDeptArkConfig selectById(Long id) {
|
public AiDeptArkConfig selectAiDeptArkConfigById(String id) {
|
||||||
return aiDeptArkConfigMapper.selectById(id);
|
return aiDeptArkConfigMapper.selectById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询团队(部门)对应火山引擎配置列表
|
||||||
|
*
|
||||||
|
* @param aiDeptArkConfig 团队(部门)对应火山引擎配置
|
||||||
|
* @return 团队(部门)对应火山引擎配置
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int insert(AiDeptArkConfig entity) {
|
public List<AiDeptArkConfig> selectAiDeptArkConfigList(AiDeptArkConfig aiDeptArkConfig) {
|
||||||
return aiDeptArkConfigMapper.insert(entity);
|
LambdaQueryWrapper<AiDeptArkConfig> query = Wrappers.lambdaQuery(aiDeptArkConfig);
|
||||||
|
query.orderByDesc(AiDeptArkConfig::getId);
|
||||||
|
return aiDeptArkConfigMapper.selectList(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询团队(部门)对应火山引擎配置列表
|
||||||
|
*
|
||||||
|
* @param aiDeptArkConfig 团队(部门)对应火山引擎配置
|
||||||
|
* @return 团队(部门)对应火山引擎配置
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int updateById(AiDeptArkConfig entity) {
|
public IPage<AiDeptArkConfig> selectAiDeptArkConfigPage(Page page, AiDeptArkConfig aiDeptArkConfig) {
|
||||||
return aiDeptArkConfigMapper.updateById(entity);
|
LambdaQueryWrapper<AiDeptArkConfig> query = Wrappers.lambdaQuery(aiDeptArkConfig);
|
||||||
|
return aiDeptArkConfigMapper.selectPage(page, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增团队(部门)对应火山引擎配置
|
||||||
|
*
|
||||||
|
* @param aiDeptArkConfig 团队(部门)对应火山引擎配置
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int deleteById(Long id) {
|
public int insertAiDeptArkConfig(AiDeptArkConfig aiDeptArkConfig) {
|
||||||
|
aiDeptArkConfig.setCreateBy(SecurityUtils.getUsername());
|
||||||
|
aiDeptArkConfig.setCreateTime(DateUtils.getNowDate());
|
||||||
|
return aiDeptArkConfigMapper.insert(aiDeptArkConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改团队(部门)对应火山引擎配置
|
||||||
|
*
|
||||||
|
* @param aiDeptArkConfig 团队(部门)对应火山引擎配置
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int updateAiDeptArkConfig(AiDeptArkConfig aiDeptArkConfig) {
|
||||||
|
aiDeptArkConfig.setUpdateBy(SecurityUtils.getUsername());
|
||||||
|
aiDeptArkConfig.setUpdateTime(DateUtils.getNowDate());
|
||||||
|
return aiDeptArkConfigMapper.updateById(aiDeptArkConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除团队(部门)对应火山引擎配置
|
||||||
|
*
|
||||||
|
* @param ids 需要删除的团队(部门)对应火山引擎配置主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int deleteAiDeptArkConfigByIds(String[] ids)
|
||||||
|
{
|
||||||
|
return aiDeptArkConfigMapper.deleteBatchIds(java.util.Arrays.asList(ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除团队(部门)对应火山引擎配置信息
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)对应火山引擎配置主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int deleteAiDeptArkConfigById(String id)
|
||||||
|
{
|
||||||
return aiDeptArkConfigMapper.deleteById(id);
|
return aiDeptArkConfigMapper.deleteById(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,22 @@
|
||||||
package com.ruoyi.ai.service.impl;
|
package com.ruoyi.ai.service.impl;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
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.domain.AiGroupBalanceChangeRecord;
|
|
||||||
import com.ruoyi.ai.mapper.AiGroupBalanceChangeRecordMapper;
|
import com.ruoyi.ai.mapper.AiGroupBalanceChangeRecordMapper;
|
||||||
|
import com.ruoyi.ai.domain.AiGroupBalanceChangeRecord;
|
||||||
import com.ruoyi.ai.service.IAiGroupBalanceChangeRecordService;
|
import com.ruoyi.ai.service.IAiGroupBalanceChangeRecordService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 集团余额变动记录 Service 实现
|
* 团队(部门)余额变动Service业务层处理
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class AiGroupBalanceChangeRecordServiceImpl implements IAiGroupBalanceChangeRecordService {
|
public class AiGroupBalanceChangeRecordServiceImpl implements IAiGroupBalanceChangeRecordService {
|
||||||
|
|
@ -16,23 +24,87 @@ public class AiGroupBalanceChangeRecordServiceImpl implements IAiGroupBalanceCha
|
||||||
@Autowired
|
@Autowired
|
||||||
private AiGroupBalanceChangeRecordMapper aiGroupBalanceChangeRecordMapper;
|
private AiGroupBalanceChangeRecordMapper aiGroupBalanceChangeRecordMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询团队(部门)余额变动
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)余额变动主键
|
||||||
|
* @return 团队(部门)余额变动
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public AiGroupBalanceChangeRecord selectById(Long id) {
|
public AiGroupBalanceChangeRecord selectAiGroupBalanceChangeRecordById(String id) {
|
||||||
return aiGroupBalanceChangeRecordMapper.selectById(id);
|
return aiGroupBalanceChangeRecordMapper.selectById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询团队(部门)余额变动列表
|
||||||
|
*
|
||||||
|
* @param aiGroupBalanceChangeRecord 团队(部门)余额变动
|
||||||
|
* @return 团队(部门)余额变动
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int insert(AiGroupBalanceChangeRecord entity) {
|
public List<AiGroupBalanceChangeRecord> selectAiGroupBalanceChangeRecordList(AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord) {
|
||||||
return aiGroupBalanceChangeRecordMapper.insert(entity);
|
LambdaQueryWrapper<AiGroupBalanceChangeRecord> query = Wrappers.lambdaQuery(aiGroupBalanceChangeRecord);
|
||||||
|
query.orderByDesc(AiGroupBalanceChangeRecord::getId);
|
||||||
|
return aiGroupBalanceChangeRecordMapper.selectList(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询团队(部门)余额变动列表
|
||||||
|
*
|
||||||
|
* @param aiGroupBalanceChangeRecord 团队(部门)余额变动
|
||||||
|
* @return 团队(部门)余额变动
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int updateById(AiGroupBalanceChangeRecord entity) {
|
public IPage<AiGroupBalanceChangeRecord> selectAiGroupBalanceChangeRecordPage(Page page, AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord) {
|
||||||
return aiGroupBalanceChangeRecordMapper.updateById(entity);
|
LambdaQueryWrapper<AiGroupBalanceChangeRecord> query = Wrappers.lambdaQuery(aiGroupBalanceChangeRecord);
|
||||||
|
return aiGroupBalanceChangeRecordMapper.selectPage(page, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增团队(部门)余额变动
|
||||||
|
*
|
||||||
|
* @param aiGroupBalanceChangeRecord 团队(部门)余额变动
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int deleteById(Long id) {
|
public int insertAiGroupBalanceChangeRecord(AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord) {
|
||||||
|
aiGroupBalanceChangeRecord.setCreateTime(DateUtils.getNowDate());
|
||||||
|
return aiGroupBalanceChangeRecordMapper.insert(aiGroupBalanceChangeRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改团队(部门)余额变动
|
||||||
|
*
|
||||||
|
* @param aiGroupBalanceChangeRecord 团队(部门)余额变动
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int updateAiGroupBalanceChangeRecord(AiGroupBalanceChangeRecord aiGroupBalanceChangeRecord) {
|
||||||
|
aiGroupBalanceChangeRecord.setUpdateTime(DateUtils.getNowDate());
|
||||||
|
return aiGroupBalanceChangeRecordMapper.updateById(aiGroupBalanceChangeRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除团队(部门)余额变动
|
||||||
|
*
|
||||||
|
* @param ids 需要删除的团队(部门)余额变动主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int deleteAiGroupBalanceChangeRecordByIds(String[] ids)
|
||||||
|
{
|
||||||
|
return aiGroupBalanceChangeRecordMapper.deleteBatchIds(java.util.Arrays.asList(ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除团队(部门)余额变动信息
|
||||||
|
*
|
||||||
|
* @param id 团队(部门)余额变动主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int deleteAiGroupBalanceChangeRecordById(String id)
|
||||||
|
{
|
||||||
return aiGroupBalanceChangeRecordMapper.deleteById(id);
|
return aiGroupBalanceChangeRecordMapper.deleteById(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,9 @@ public class AiOrderServiceImpl implements IAiOrderService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IByteDeptApiKeyService byteDeptApiKeyService;
|
private IByteDeptApiKeyService byteDeptApiKeyService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAiVideoReportDataService aiVideoReportDataService;
|
||||||
|
|
||||||
// 流水表:任务成功时回补
|
// 流水表:任务成功时回补
|
||||||
private static final String TASK_SUCCESS_BACK_FILL_REMARK = "order.number.generation.successbackfill";
|
private static final String TASK_SUCCESS_BACK_FILL_REMARK = "order.number.generation.successbackfill";
|
||||||
|
|
||||||
|
|
@ -248,6 +251,7 @@ public class AiOrderServiceImpl implements IAiOrderService {
|
||||||
public void orderSuccess(AiOrder aiOrder) {
|
public void orderSuccess(AiOrder aiOrder) {
|
||||||
aiOrder.setStatus(1);
|
aiOrder.setStatus(1);
|
||||||
aiOrderMapper.updateById(aiOrder);
|
aiOrderMapper.updateById(aiOrder);
|
||||||
|
syncVideoReportData(aiOrder);
|
||||||
AiStatistics aiStatistics = new AiStatistics();
|
AiStatistics aiStatistics = new AiStatistics();
|
||||||
aiStatistics.setSource(aiOrder.getSource());
|
aiStatistics.setSource(aiOrder.getSource());
|
||||||
aiStatistics.setGenerateCount(1L);
|
aiStatistics.setGenerateCount(1L);
|
||||||
|
|
@ -356,4 +360,18 @@ public class AiOrderServiceImpl implements IAiOrderService {
|
||||||
// BalanceChangerConstants.QUICK_VIDEO_GENERATION, TASK_SUCCESS_BALANCE_REMARK);
|
// BalanceChangerConstants.QUICK_VIDEO_GENERATION, TASK_SUCCESS_BALANCE_REMARK);
|
||||||
return AjaxResult.success("callback success");
|
return AjaxResult.success("callback success");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务成功后按“提交时间”写入团队消耗统计来源表。
|
||||||
|
*
|
||||||
|
* @param aiOrder 已成功订单
|
||||||
|
*/
|
||||||
|
private void syncVideoReportData(AiOrder aiOrder) {
|
||||||
|
if (aiOrder == null || aiOrder.getCreateTime() == null || aiOrder.getDeptId() == null || aiOrder.getUserId() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BigDecimal score = aiOrder.getAmount() != null ? aiOrder.getAmount() : BigDecimal.ZERO;
|
||||||
|
Long useTokens = aiOrder.getTotalUsage() != null ? aiOrder.getTotalUsage().longValue() : 0L;
|
||||||
|
aiVideoReportDataService.syncVideoConsumeIncrement(aiOrder.getCreateTime(), aiOrder.getDeptId(), aiOrder.getUserId(), score, useTokens);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ public class AiUserServiceImpl implements IAiUserService {
|
||||||
private AiUser getUserByInvitationCode(String invitationCode) {
|
private AiUser getUserByInvitationCode(String invitationCode) {
|
||||||
LambdaQueryWrapper<AiUser> query = Wrappers.lambdaQuery();
|
LambdaQueryWrapper<AiUser> query = Wrappers.lambdaQuery();
|
||||||
query.eq(AiUser::getInvitationCode, invitationCode);
|
query.eq(AiUser::getInvitationCode, invitationCode);
|
||||||
query.eq(AiUser::getDelFlag, 0);
|
query.eq(AiUser::getDelFlag, "0");
|
||||||
return aiUserMapper.selectOne(query);
|
return aiUserMapper.selectOne(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,141 @@
|
||||||
package com.ruoyi.ai.service.impl;
|
package com.ruoyi.ai.service.impl;
|
||||||
|
|
||||||
import com.ruoyi.ai.domain.AiVideoReportData;
|
import java.util.List;
|
||||||
import com.ruoyi.ai.mapper.AiVideoReportDataMapper;
|
import java.math.BigDecimal;
|
||||||
import com.ruoyi.ai.service.IAiVideoReportDataService;
|
import java.text.SimpleDateFormat;
|
||||||
import com.ruoyi.common.constant.RedisKey;
|
import java.util.Date;
|
||||||
import com.ruoyi.common.core.dto.DeptSummaryDTO;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import com.ruoyi.ai.mapper.AiVideoReportDataMapper;
|
||||||
import java.time.LocalDateTime;
|
import com.ruoyi.ai.domain.AiVideoReportData;
|
||||||
import java.time.ZoneId;
|
import com.ruoyi.ai.service.IAiVideoReportDataService;
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视频报表数据 Service 实现
|
* AI视频生成统计数据,作为其他统计报的数据源Service业务层处理
|
||||||
|
*
|
||||||
|
* @author shi
|
||||||
|
* @date 2026-04-17
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class AiVideoReportDataServiceImpl implements IAiVideoReportDataService {
|
public class AiVideoReportDataServiceImpl implements IAiVideoReportDataService {
|
||||||
|
|
||||||
/** 与表字段 date_key 一致:yyyy-MM-dd HH(线程安全) */
|
|
||||||
private static final DateTimeFormatter DATE_KEY_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH");
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AiVideoReportDataMapper videoReportDataMapper;
|
private AiVideoReportDataMapper aiVideoReportDataMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*
|
||||||
|
* @param id AI视频生成统计数据,作为其他统计报的数据源主键
|
||||||
|
* @return AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public AiVideoReportData selectById(Long id) {
|
public AiVideoReportData selectAiVideoReportDataById(String id) {
|
||||||
return videoReportDataMapper.selectById(id);
|
return aiVideoReportDataMapper.selectById(id);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int insert(AiVideoReportData entity) {
|
|
||||||
return videoReportDataMapper.insert(entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门近七日汇总数据
|
* 查询AI视频生成统计数据,作为其他统计报的数据源列表
|
||||||
|
*
|
||||||
|
* @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
* @return AI视频生成统计数据,作为其他统计报的数据源
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Cacheable(cacheNames = RedisKey.CACHE_DEPT_SUMMARY, key = "#deptId")
|
public List<AiVideoReportData> selectAiVideoReportDataList(AiVideoReportData aiVideoReportData) {
|
||||||
public DeptSummaryDTO getSevenDayDeptSummaryData(Long deptId) {
|
LambdaQueryWrapper<AiVideoReportData> query = Wrappers.lambdaQuery(aiVideoReportData);
|
||||||
Date endTime = new Date();
|
query.orderByDesc(AiVideoReportData::getId);
|
||||||
// 获取今天的0点,再减去7天
|
return aiVideoReportDataMapper.selectList(query);
|
||||||
Date todayZero = DateUtils.truncate(endTime, Calendar.DAY_OF_MONTH);
|
|
||||||
Date startTime = DateUtils.addDays(todayZero, -7);
|
|
||||||
|
|
||||||
String startHour = formatDateKey(startTime);
|
|
||||||
String endHour = formatDateKey(endTime);
|
|
||||||
return videoReportDataMapper.selectOneDeptSummaryData(deptId, startHour, endHour);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatDateKey(Date date) {
|
/**
|
||||||
LocalDateTime ldt = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
|
* 分页查询AI视频生成统计数据,作为其他统计报的数据源列表
|
||||||
return DATE_KEY_FORMAT.format(ldt);
|
*
|
||||||
|
* @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
* @return AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public IPage<AiVideoReportData> selectAiVideoReportDataPage(Page page, AiVideoReportData aiVideoReportData) {
|
||||||
|
LambdaQueryWrapper<AiVideoReportData> query = Wrappers.lambdaQuery(aiVideoReportData);
|
||||||
|
return aiVideoReportDataMapper.selectPage(page, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*
|
||||||
|
* @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int insertAiVideoReportData(AiVideoReportData aiVideoReportData) {
|
||||||
|
aiVideoReportData.setCreateTime(DateUtils.getNowDate());
|
||||||
|
return aiVideoReportDataMapper.insert(aiVideoReportData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*
|
||||||
|
* @param aiVideoReportData AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int updateAiVideoReportData(AiVideoReportData aiVideoReportData) {
|
||||||
|
aiVideoReportData.setUpdateTime(DateUtils.getNowDate());
|
||||||
|
return aiVideoReportDataMapper.updateById(aiVideoReportData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除AI视频生成统计数据,作为其他统计报的数据源
|
||||||
|
*
|
||||||
|
* @param ids 需要删除的AI视频生成统计数据,作为其他统计报的数据源主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int deleteAiVideoReportDataByIds(String[] ids)
|
||||||
|
{
|
||||||
|
return aiVideoReportDataMapper.deleteBatchIds(java.util.Arrays.asList(ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除AI视频生成统计数据,作为其他统计报的数据源信息
|
||||||
|
*
|
||||||
|
* @param id AI视频生成统计数据,作为其他统计报的数据源主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int deleteAiVideoReportDataById(String id)
|
||||||
|
{
|
||||||
|
return aiVideoReportDataMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AiVideoReportData> selectTeamDailyConsumeList(String statDate, Long deptId) {
|
||||||
|
return aiVideoReportDataMapper.selectTeamDailyConsumeList(statDate, deptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AiVideoReportData> selectTeamDailyConsumeByDeptId(String statDate, Long deptId) {
|
||||||
|
return aiVideoReportDataMapper.selectTeamDailyConsumeByDeptId(statDate, deptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syncVideoConsumeIncrement(Date createTime, Long deptId, Long userId, BigDecimal score, Long useTokens) {
|
||||||
|
if (createTime == null || deptId == null || userId == null || score == null || useTokens == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String dateKey = new SimpleDateFormat("yyyyMMddHH").format(createTime);
|
||||||
|
aiVideoReportDataMapper.upsertVideoConsumeIncrement(dateKey, deptId, userId, score, 1L, useTokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syncRechargeScoreIncrement(Date createTime, Long deptId, BigDecimal rechargeScore) {
|
||||||
|
if (createTime == null || deptId == null || rechargeScore == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String dateKey = new SimpleDateFormat("yyyyMMddHH").format(createTime);
|
||||||
|
aiVideoReportDataMapper.upsertRechargeScoreIncrement(dateKey, deptId, rechargeScore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.ruoyi.common.constant.BalanceChangerConstants;
|
|
||||||
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 org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
@ -60,19 +59,19 @@ public class DeptChargeRefundServiceImpl implements IDeptChargeRefundService {
|
||||||
// 1) 手工入账订单,状态直接为已完成
|
// 1) 手工入账订单,状态直接为已完成
|
||||||
AiChargeRefundOrder order = new AiChargeRefundOrder();
|
AiChargeRefundOrder order = new AiChargeRefundOrder();
|
||||||
order.setDelFlag("0");
|
order.setDelFlag("0");
|
||||||
order.setCreateBy(SecurityUtils.getUserId());
|
order.setCreateBy(SecurityUtils.getUsername());
|
||||||
order.setCreateTime(now);
|
order.setCreateTime(now);
|
||||||
order.setUpdateTime(now);
|
order.setUpdateTime(now);
|
||||||
order.setOrderNum(orderNum);
|
order.setOrderNum(orderNum);
|
||||||
order.setDeptId(request.getDeptId());
|
order.setDeptId(request.getDeptId());
|
||||||
order.setOrderType(request.getOrderType());
|
order.setOrderType(Long.valueOf(request.getOrderType()));
|
||||||
// 金额两位小数:向零截断(非四舍五入),避免入账金额被抬高
|
// 金额两位小数:向零截断(非四舍五入),避免入账金额被抬高
|
||||||
order.setMoney(request.getMoney().setScale(2, RoundingMode.DOWN));
|
order.setMoney(request.getMoney().setScale(2, RoundingMode.DOWN));
|
||||||
order.setAmount(amountBd);
|
order.setAmount(amountBd);
|
||||||
order.setRemark(request.getRemark());
|
order.setRemark(request.getRemark());
|
||||||
order.setStatus(ChargeRefundOrderStatusType.SUCCESS.getCode());
|
order.setStatus(ChargeRefundOrderStatusType.SUCCESS.getCode());
|
||||||
|
|
||||||
aiChargeRefundOrderService.insert(order);
|
aiChargeRefundOrderService.insertAiChargeRefundOrder(order);
|
||||||
|
|
||||||
// 2) 原子更新部门积分;退款时 rows==0 表示余额不足或部门无效,依赖事务回滚撤销上一 INSERT
|
// 2) 原子更新部门积分;退款时 rows==0 表示余额不足或部门无效,依赖事务回滚撤销上一 INSERT
|
||||||
int rows;
|
int rows;
|
||||||
|
|
@ -102,22 +101,22 @@ public class DeptChargeRefundServiceImpl implements IDeptChargeRefundService {
|
||||||
record.setRelationOrderNo(orderNum);
|
record.setRelationOrderNo(orderNum);
|
||||||
record.setDeptId(request.getDeptId());
|
record.setDeptId(request.getDeptId());
|
||||||
record.setType(orderType == ChargeRefundOrderType.CHARGE
|
record.setType(orderType == ChargeRefundOrderType.CHARGE
|
||||||
? GroupBalanceChangeType.RECHARGE.getCode()
|
? Long.valueOf(GroupBalanceChangeType.RECHARGE.getCode())
|
||||||
: GroupBalanceChangeType.REFUND.getCode());
|
: Long.valueOf(GroupBalanceChangeType.REFUND.getCode()));
|
||||||
record.setChangeAmount(signedChange);
|
record.setChangeAmount(signedChange);
|
||||||
record.setResultAmount(dept.getBalance());
|
record.setResultAmount(dept.getBalance());
|
||||||
record.setRemark(request.getRemark());
|
record.setRemark(request.getRemark());
|
||||||
record.setCreateBy(SecurityUtils.getUserId());
|
record.setCreateBy(SecurityUtils.getUsername());
|
||||||
record.setCreateTime(now);
|
record.setCreateTime(now);
|
||||||
record.setUpdateTime(now);
|
record.setUpdateTime(now);
|
||||||
|
|
||||||
aiGroupBalanceChangeRecordService.insert(record);
|
aiGroupBalanceChangeRecordService.insertAiGroupBalanceChangeRecord(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 业务单号前缀 + 日序 + 随机后缀,保证与流水 relation_order_no 一致。 */
|
/** 业务单号前缀 + 日序 + 随机后缀,保证与流水 relation_order_no 一致。 */
|
||||||
private static String buildOrderNum() {
|
private static String buildOrderNum() {
|
||||||
String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
|
String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
|
||||||
String dateTime = new SimpleDateFormat("yyyyMMdd").format(new Date());
|
String dateTime = new SimpleDateFormat("yyyyMMdd").format(new Date());
|
||||||
return BalanceChangerConstants.OrderNoPrefix.RECHARGE_REFUND_PREFIX + dateTime + uuid;
|
return "CG" + dateTime + uuid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import com.ruoyi.common.core.domain.entity.SysDept;
|
||||||
import com.ruoyi.common.core.request.ai.AiUserDeptScoreRequest;
|
import com.ruoyi.common.core.request.ai.AiUserDeptScoreRequest;
|
||||||
import com.ruoyi.common.enums.GroupBalanceChangeType;
|
import com.ruoyi.common.enums.GroupBalanceChangeType;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.system.service.ISysDeptService;
|
import com.ruoyi.system.service.ISysDeptService;
|
||||||
|
|
@ -78,7 +77,9 @@ public class DeptUserScoreTransferTxService {
|
||||||
}
|
}
|
||||||
|
|
||||||
String orderNum = buildOrderNum();
|
String orderNum = buildOrderNum();
|
||||||
aiUserService.addUserBalance(orderNum, user.getId(), amount.negate(), BalanceChangerConstants.DEPT_SCORE_RECLAIM, request.getRemark());
|
String remark = buildRemark(request.getRemark(), "用户积分回收至部门");
|
||||||
|
|
||||||
|
aiUserService.addUserBalance(orderNum, user.getId(), amount.negate(), BalanceChangerConstants.DEPT_SCORE_RECLAIM, remark);
|
||||||
|
|
||||||
int rows = deptService.addDeptBalance(deptId, amount);
|
int rows = deptService.addDeptBalance(deptId, amount);
|
||||||
if (rows == 0) {
|
if (rows == 0) {
|
||||||
|
|
@ -86,7 +87,7 @@ public class DeptUserScoreTransferTxService {
|
||||||
}
|
}
|
||||||
|
|
||||||
BigDecimal deptBalAfter = getDeptBalance(deptId);
|
BigDecimal deptBalAfter = getDeptBalance(deptId);
|
||||||
insertGroupRecord(orderNum, deptId, GroupBalanceChangeType.RECLAIM.getCode(), amount, deptBalAfter, request.getRemark());
|
insertGroupRecord(orderNum, deptId, GroupBalanceChangeType.RECLAIM.getCode(), amount, deptBalAfter, remark);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AiUser requireUserWithDept(Long id) {
|
private AiUser requireUserWithDept(Long id) {
|
||||||
|
|
@ -131,17 +132,17 @@ public class DeptUserScoreTransferTxService {
|
||||||
AiGroupBalanceChangeRecord record = new AiGroupBalanceChangeRecord();
|
AiGroupBalanceChangeRecord record = new AiGroupBalanceChangeRecord();
|
||||||
record.setRelationOrderNo(orderNum);
|
record.setRelationOrderNo(orderNum);
|
||||||
record.setDeptId(deptId);
|
record.setDeptId(deptId);
|
||||||
record.setType(type);
|
record.setType(Long.valueOf(type));
|
||||||
record.setChangeAmount(signedChange);
|
record.setChangeAmount(signedChange);
|
||||||
record.setResultAmount(resultBalance);
|
record.setResultAmount(resultBalance);
|
||||||
record.setRemark(remark);
|
record.setRemark(remark);
|
||||||
record.setCreateBy(SecurityUtils.getUserId());
|
record.setCreateBy(SecurityUtils.getUsername());
|
||||||
aiGroupBalanceChangeRecordService.insert(record);
|
aiGroupBalanceChangeRecordService.insertAiGroupBalanceChangeRecord(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildOrderNum() {
|
private static String buildOrderNum() {
|
||||||
String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
|
String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
|
||||||
String dateTime = new SimpleDateFormat("yyyyMMdd").format(new Date());
|
String dateTime = new SimpleDateFormat("yyyyMMdd").format(new Date());
|
||||||
return BalanceChangerConstants.OrderNoPrefix.ISSUE_RECLAIM_PREFIX + dateTime + uuid;
|
return "DU" + dateTime + uuid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.ruoyi.system.domain.subteam;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 团队后台首页概览
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SubteamOverviewVO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
/** 团队积分余额(sys_dept.balance) */
|
||||||
|
private BigDecimal balance;
|
||||||
|
|
||||||
|
/** AI 用户数量(ai_user,实时) */
|
||||||
|
private Integer aiUserCount;
|
||||||
|
|
||||||
|
/** 近七日消耗积分(ai_video_report_data,可能来自缓存) */
|
||||||
|
private BigDecimal last7DaysConsumeScore;
|
||||||
|
|
||||||
|
/** 近七日成功订单数(ai_video_report_data,可能来自缓存) */
|
||||||
|
private Long last7DaysOrderCount;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.ruoyi.system.domain.subteam;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 团队视频统计汇总(近七日消耗/订单数)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SubteamVideoMetrics implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private BigDecimal consumeScore;
|
||||||
|
|
||||||
|
private Long orderCount;
|
||||||
|
}
|
||||||
|
|
@ -421,13 +421,13 @@ public class SysDeptServiceImpl implements ISysDeptService
|
||||||
AiGroupBalanceChangeRecord record = new AiGroupBalanceChangeRecord();
|
AiGroupBalanceChangeRecord record = new AiGroupBalanceChangeRecord();
|
||||||
record.setRelationOrderNo(null);
|
record.setRelationOrderNo(null);
|
||||||
record.setDeptId(request.getDeptId());
|
record.setDeptId(request.getDeptId());
|
||||||
record.setType(GroupBalanceChangeType.MANUAL_ADJUST.getCode());
|
record.setType(Long.valueOf(GroupBalanceChangeType.MANUAL_ADJUST.getCode()));
|
||||||
record.setChangeAmount(delta);
|
record.setChangeAmount(delta);
|
||||||
record.setResultAmount(dept.getBalance());
|
record.setResultAmount(dept.getBalance());
|
||||||
record.setRemark(request.getRemark());
|
record.setRemark(request.getRemark());
|
||||||
record.setCreateBy(SecurityUtils.getUserId());
|
record.setCreateBy(SecurityUtils.getUsername());
|
||||||
|
|
||||||
aiGroupBalanceChangeRecordService.insert(record);
|
aiGroupBalanceChangeRecordService.insertAiGroupBalanceChangeRecord(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.ruoyi.system.service.subteam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.ruoyi.ai.domain.AiBalanceChangeRecord;
|
||||||
|
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
||||||
|
import com.ruoyi.ai.domain.AiGroupBalanceChangeRecord;
|
||||||
|
import com.ruoyi.ai.domain.AiOrder;
|
||||||
|
import com.ruoyi.ai.domain.AiVideoReportData;
|
||||||
|
|
||||||
|
public interface ISubteamDataQueryService {
|
||||||
|
|
||||||
|
List<AiOrder> selectVideoOrders(AiOrder query);
|
||||||
|
|
||||||
|
List<AiChargeRefundOrder> selectChargeRefundOrders(AiChargeRefundOrder query);
|
||||||
|
|
||||||
|
List<AiBalanceChangeRecord> selectUserBalanceRecords(AiBalanceChangeRecord query);
|
||||||
|
|
||||||
|
List<AiGroupBalanceChangeRecord> selectGroupBalanceRecords(AiGroupBalanceChangeRecord query);
|
||||||
|
|
||||||
|
List<AiVideoReportData> selectTeamDailyConsume(String statDate);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.ruoyi.system.service.subteam;
|
||||||
|
|
||||||
|
import com.ruoyi.system.domain.subteam.SubteamOverviewVO;
|
||||||
|
|
||||||
|
public interface ISubteamOverviewService {
|
||||||
|
|
||||||
|
SubteamOverviewVO loadOverview();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.ruoyi.system.service.subteam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 团队后台数据范围:当前登录人所属部门(团队)
|
||||||
|
*/
|
||||||
|
public interface ISubteamScopeService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前账号所属团队部门 ID(sys_user.dept_id)
|
||||||
|
*/
|
||||||
|
Long currentTeamDeptId();
|
||||||
|
|
||||||
|
void assertSysUserInTeam(Long sysUserId);
|
||||||
|
|
||||||
|
void assertAiUserInTeam(Long aiUserId);
|
||||||
|
|
||||||
|
void assertAiOrderBelongsToTeam(Long orderId);
|
||||||
|
|
||||||
|
void assertChargeRefundBelongsToTeam(Long orderPkId);
|
||||||
|
|
||||||
|
void assertGroupBalanceRecordBelongsToTeam(String recordId);
|
||||||
|
|
||||||
|
void assertAiBalanceRecordVisible(Long recordId, Long teamDeptId);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
package com.ruoyi.system.service.subteam.impl;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.ruoyi.ai.domain.AiBalanceChangeRecord;
|
||||||
|
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
||||||
|
import com.ruoyi.ai.domain.AiGroupBalanceChangeRecord;
|
||||||
|
import com.ruoyi.ai.domain.AiOrder;
|
||||||
|
import com.ruoyi.ai.domain.AiVideoReportData;
|
||||||
|
import com.ruoyi.ai.mapper.AiBalanceChangeRecordMapper;
|
||||||
|
import com.ruoyi.ai.mapper.AiChargeRefundOrderMapper;
|
||||||
|
import com.ruoyi.ai.mapper.AiGroupBalanceChangeRecordMapper;
|
||||||
|
import com.ruoyi.ai.mapper.AiOrderMapper;
|
||||||
|
import com.ruoyi.ai.service.IAiVideoReportDataService;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamDataQueryService;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamScopeService;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SubteamDataQueryServiceImpl implements ISubteamDataQueryService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamScopeService subteamScopeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AiOrderMapper aiOrderMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AiChargeRefundOrderMapper aiChargeRefundOrderMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AiBalanceChangeRecordMapper aiBalanceChangeRecordMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AiGroupBalanceChangeRecordMapper aiGroupBalanceChangeRecordMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAiVideoReportDataService aiVideoReportDataService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AiOrder> selectVideoOrders(AiOrder query) {
|
||||||
|
Long deptId = subteamScopeService.currentTeamDeptId();
|
||||||
|
query.setDeptId(deptId);
|
||||||
|
return aiOrderMapper.selectAiOrderList(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AiChargeRefundOrder> selectChargeRefundOrders(AiChargeRefundOrder query) {
|
||||||
|
Long deptId = subteamScopeService.currentTeamDeptId();
|
||||||
|
query.setDeptId(deptId);
|
||||||
|
return aiChargeRefundOrderMapper.selectAiChargeRefundOrderList(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AiBalanceChangeRecord> selectUserBalanceRecords(AiBalanceChangeRecord query) {
|
||||||
|
Long deptId = subteamScopeService.currentTeamDeptId();
|
||||||
|
return aiBalanceChangeRecordMapper.selectAiBalanceChangeRecordListByAiUserDept(query, deptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AiGroupBalanceChangeRecord> selectGroupBalanceRecords(AiGroupBalanceChangeRecord query) {
|
||||||
|
Long deptId = subteamScopeService.currentTeamDeptId();
|
||||||
|
query.setDeptId(deptId);
|
||||||
|
return aiGroupBalanceChangeRecordMapper.selectList(
|
||||||
|
Wrappers.lambdaQuery(query).orderByDesc(AiGroupBalanceChangeRecord::getId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AiVideoReportData> selectTeamDailyConsume(String statDate) {
|
||||||
|
if (StringUtils.isEmpty(statDate)) {
|
||||||
|
return java.util.Collections.emptyList();
|
||||||
|
}
|
||||||
|
Long deptId = subteamScopeService.currentTeamDeptId();
|
||||||
|
return aiVideoReportDataService.selectTeamDailyConsumeByDeptId(statDate, deptId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.ruoyi.system.service.subteam.impl;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import com.ruoyi.ai.mapper.AiVideoReportDataMapper;
|
||||||
|
import com.ruoyi.ai.service.IAiUserService;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||||
|
import com.ruoyi.system.domain.subteam.SubteamOverviewVO;
|
||||||
|
import com.ruoyi.system.domain.subteam.SubteamVideoMetrics;
|
||||||
|
import com.ruoyi.system.mapper.SysDeptMapper;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamOverviewService;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamScopeService;
|
||||||
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SubteamOverviewServiceImpl implements ISubteamOverviewService {
|
||||||
|
|
||||||
|
private static final int METRICS_CACHE_MINUTES = 5;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISubteamScopeService subteamScopeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SysDeptMapper sysDeptMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAiUserService aiUserService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AiVideoReportDataMapper aiVideoReportDataMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisCache redisCache;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubteamOverviewVO loadOverview() {
|
||||||
|
Long deptId = subteamScopeService.currentTeamDeptId();
|
||||||
|
SysDept dept = sysDeptMapper.selectDeptById(deptId);
|
||||||
|
SubteamOverviewVO vo = new SubteamOverviewVO();
|
||||||
|
vo.setDeptId(deptId);
|
||||||
|
vo.setDeptName(dept != null ? dept.getDeptName() : "");
|
||||||
|
vo.setBalance(dept != null && dept.getBalance() != null ? dept.getBalance() : BigDecimal.ZERO);
|
||||||
|
vo.setAiUserCount(aiUserService.countAiUserByDeptId(deptId));
|
||||||
|
|
||||||
|
LocalDate end = LocalDate.now();
|
||||||
|
LocalDate start = end.minusDays(6);
|
||||||
|
String startDay = start.format(DateTimeFormatter.BASIC_ISO_DATE);
|
||||||
|
String endDay = end.format(DateTimeFormatter.BASIC_ISO_DATE);
|
||||||
|
String cacheKey = "subteam:videoMetrics:" + deptId + ":" + startDay + ":" + endDay;
|
||||||
|
SubteamVideoMetrics metrics = redisCache.getCacheObject(cacheKey);
|
||||||
|
if (metrics == null) {
|
||||||
|
metrics = aiVideoReportDataMapper.selectDeptVideoMetricsBetween(deptId, startDay, endDay);
|
||||||
|
if (metrics == null) {
|
||||||
|
metrics = new SubteamVideoMetrics();
|
||||||
|
}
|
||||||
|
if (metrics.getConsumeScore() == null) {
|
||||||
|
metrics.setConsumeScore(BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
if (metrics.getOrderCount() == null) {
|
||||||
|
metrics.setOrderCount(0L);
|
||||||
|
}
|
||||||
|
redisCache.setCacheObject(cacheKey, metrics, METRICS_CACHE_MINUTES, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
vo.setLast7DaysConsumeScore(metrics.getConsumeScore());
|
||||||
|
vo.setLast7DaysOrderCount(metrics.getOrderCount());
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
package com.ruoyi.system.service.subteam.impl;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import com.ruoyi.ai.domain.AiChargeRefundOrder;
|
||||||
|
import com.ruoyi.ai.domain.AiGroupBalanceChangeRecord;
|
||||||
|
import com.ruoyi.ai.domain.AiOrder;
|
||||||
|
import com.ruoyi.ai.domain.AiBalanceChangeRecord;
|
||||||
|
import com.ruoyi.ai.mapper.AiChargeRefundOrderMapper;
|
||||||
|
import com.ruoyi.ai.mapper.AiGroupBalanceChangeRecordMapper;
|
||||||
|
import com.ruoyi.ai.mapper.AiOrderMapper;
|
||||||
|
import com.ruoyi.ai.mapper.AiBalanceChangeRecordMapper;
|
||||||
|
import com.ruoyi.common.core.domain.entity.AiUser;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.system.mapper.SysUserMapper;
|
||||||
|
import com.ruoyi.system.service.subteam.ISubteamScopeService;
|
||||||
|
import com.ruoyi.ai.mapper.AiUserMapper;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SubteamScopeServiceImpl implements ISubteamScopeService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SysUserMapper sysUserMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AiOrderMapper aiOrderMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AiChargeRefundOrderMapper aiChargeRefundOrderMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AiGroupBalanceChangeRecordMapper aiGroupBalanceChangeRecordMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AiBalanceChangeRecordMapper aiBalanceChangeRecordMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AiUserMapper aiUserMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long currentTeamDeptId() {
|
||||||
|
Long deptId = SecurityUtils.getDeptId();
|
||||||
|
if (deptId == null || deptId <= 0) {
|
||||||
|
throw new ServiceException("当前账号未绑定团队,无法使用团队后台");
|
||||||
|
}
|
||||||
|
return deptId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void assertSysUserInTeam(Long sysUserId) {
|
||||||
|
Long teamDeptId = currentTeamDeptId();
|
||||||
|
SysUser u = sysUserMapper.selectUserById(sysUserId);
|
||||||
|
if (u == null || u.getDeptId() == null || !teamDeptId.equals(u.getDeptId())) {
|
||||||
|
throw new ServiceException("无权操作该用户");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void assertAiUserInTeam(Long aiUserId) {
|
||||||
|
Long teamDeptId = currentTeamDeptId();
|
||||||
|
AiUser user = aiUserMapper.selectById(aiUserId);
|
||||||
|
if (user == null || user.getDeptId() == null || !teamDeptId.equals(user.getDeptId())) {
|
||||||
|
throw new ServiceException("无权操作该用户");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void assertAiOrderBelongsToTeam(Long orderId) {
|
||||||
|
Long teamDeptId = currentTeamDeptId();
|
||||||
|
AiOrder o = aiOrderMapper.selectById(orderId);
|
||||||
|
if (o == null || o.getDeptId() == null || !teamDeptId.equals(o.getDeptId())) {
|
||||||
|
throw new ServiceException("无权查看该订单");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void assertChargeRefundBelongsToTeam(Long orderPkId) {
|
||||||
|
Long teamDeptId = currentTeamDeptId();
|
||||||
|
AiChargeRefundOrder o = aiChargeRefundOrderMapper.selectAiChargeRefundOrderById(orderPkId);
|
||||||
|
if (o == null || o.getDeptId() == null || !teamDeptId.equals(o.getDeptId())) {
|
||||||
|
throw new ServiceException("无权查看该充值记录");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void assertGroupBalanceRecordBelongsToTeam(String recordId) {
|
||||||
|
Long teamDeptId = currentTeamDeptId();
|
||||||
|
AiGroupBalanceChangeRecord r = aiGroupBalanceChangeRecordMapper.selectById(recordId);
|
||||||
|
if (r == null || r.getDeptId() == null || !teamDeptId.equals(r.getDeptId())) {
|
||||||
|
throw new ServiceException("无权查看该记录");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void assertAiBalanceRecordVisible(Long recordId, Long teamDeptId) {
|
||||||
|
AiBalanceChangeRecord r = aiBalanceChangeRecordMapper.selectById(recordId);
|
||||||
|
if (r == null) {
|
||||||
|
throw new ServiceException("记录不存在");
|
||||||
|
}
|
||||||
|
AiUser u = aiUserMapper.selectAiUserById(r.getUserId());
|
||||||
|
if (u == null || u.getDeptId() == null || !teamDeptId.equals(u.getDeptId())) {
|
||||||
|
throw new ServiceException("无权查看该余额变动");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ruoyi.ai.mapper.AiChargeRefundOrderMapper">
|
||||||
|
|
||||||
|
<resultMap type="AiChargeRefundOrder" id="AiChargeRefundOrderResult">
|
||||||
|
<result property="id" column="id" />
|
||||||
|
<result property="delFlag" column="del_flag" />
|
||||||
|
<result property="createBy" column="create_by" />
|
||||||
|
<result property="createTime" column="create_time" />
|
||||||
|
<result property="updateTime" column="update_time" />
|
||||||
|
<result property="orderNum" column="order_num" />
|
||||||
|
<result property="thirdPartyOrderNum" column="third_party_order_num" />
|
||||||
|
<result property="deptId" column="dept_id" />
|
||||||
|
<result property="deptName" column="dept_name" />
|
||||||
|
<result property="orderType" column="order_type" />
|
||||||
|
<result property="money" column="money" />
|
||||||
|
<result property="amount" column="amount" />
|
||||||
|
<result property="remark" column="remark" />
|
||||||
|
<result property="status" column="status" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="selectAiChargeRefundOrderVo">
|
||||||
|
select o.id, o.del_flag, o.create_by, o.create_time, o.update_time, o.order_num, o.third_party_order_num, o.dept_id,
|
||||||
|
d.dept_name as dept_name, o.order_type, o.money, o.amount, o.remark, o.status
|
||||||
|
from ai_charge_refund_order o
|
||||||
|
left join sys_dept d on d.dept_id = o.dept_id and d.del_flag = '0'
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectAiChargeRefundOrderList" parameterType="AiChargeRefundOrder" resultMap="AiChargeRefundOrderResult">
|
||||||
|
<include refid="selectAiChargeRefundOrderVo"/>
|
||||||
|
<where>
|
||||||
|
and o.del_flag = '0'
|
||||||
|
<if test="orderNum != null and orderNum != ''"> and o.order_num = #{orderNum}</if>
|
||||||
|
<if test="thirdPartyOrderNum != null and thirdPartyOrderNum != ''"> and o.third_party_order_num = #{thirdPartyOrderNum}</if>
|
||||||
|
<if test="deptId != null "> and o.dept_id = #{deptId}</if>
|
||||||
|
<if test="deptName != null and deptName != ''"> and d.dept_name like concat('%', #{deptName}, '%')</if>
|
||||||
|
<if test="orderType != null "> and o.order_type = #{orderType}</if>
|
||||||
|
<if test="money != null "> and o.money = #{money}</if>
|
||||||
|
<if test="amount != null "> and o.amount = #{amount}</if>
|
||||||
|
<if test="status != null "> and o.status = #{status}</if>
|
||||||
|
</where>
|
||||||
|
order by o.id desc
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectAiChargeRefundOrderById" parameterType="Long" resultMap="AiChargeRefundOrderResult">
|
||||||
|
<include refid="selectAiChargeRefundOrderVo"/>
|
||||||
|
where o.id = #{id}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertAiChargeRefundOrder" parameterType="AiChargeRefundOrder" useGeneratedKeys="true" keyProperty="id">
|
||||||
|
insert into ai_charge_refund_order
|
||||||
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="delFlag != null and delFlag != ''">del_flag,</if>
|
||||||
|
<if test="createBy != null">create_by,</if>
|
||||||
|
<if test="createTime != null">create_time,</if>
|
||||||
|
<if test="updateTime != null">update_time,</if>
|
||||||
|
<if test="orderNum != null and orderNum != ''">order_num,</if>
|
||||||
|
<if test="thirdPartyOrderNum != null">third_party_order_num,</if>
|
||||||
|
<if test="deptId != null">dept_id,</if>
|
||||||
|
<if test="orderType != null">order_type,</if>
|
||||||
|
<if test="money != null">money,</if>
|
||||||
|
<if test="amount != null">amount,</if>
|
||||||
|
<if test="remark != null">remark,</if>
|
||||||
|
<if test="status != null">status,</if>
|
||||||
|
</trim>
|
||||||
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="delFlag != null and delFlag != ''">#{delFlag},</if>
|
||||||
|
<if test="createBy != null">#{createBy},</if>
|
||||||
|
<if test="createTime != null">#{createTime},</if>
|
||||||
|
<if test="updateTime != null">#{updateTime},</if>
|
||||||
|
<if test="orderNum != null and orderNum != ''">#{orderNum},</if>
|
||||||
|
<if test="thirdPartyOrderNum != null">#{thirdPartyOrderNum},</if>
|
||||||
|
<if test="deptId != null">#{deptId},</if>
|
||||||
|
<if test="orderType != null">#{orderType},</if>
|
||||||
|
<if test="money != null">#{money},</if>
|
||||||
|
<if test="amount != null">#{amount},</if>
|
||||||
|
<if test="remark != null">#{remark},</if>
|
||||||
|
<if test="status != null">#{status},</if>
|
||||||
|
</trim>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="updateAiChargeRefundOrder" parameterType="AiChargeRefundOrder">
|
||||||
|
update ai_charge_refund_order
|
||||||
|
<trim prefix="SET" suffixOverrides=",">
|
||||||
|
<if test="delFlag != null and delFlag != ''">del_flag = #{delFlag},</if>
|
||||||
|
<if test="createBy != null">create_by = #{createBy},</if>
|
||||||
|
<if test="createTime != null">create_time = #{createTime},</if>
|
||||||
|
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||||
|
<if test="orderNum != null and orderNum != ''">order_num = #{orderNum},</if>
|
||||||
|
<if test="thirdPartyOrderNum != null">third_party_order_num = #{thirdPartyOrderNum},</if>
|
||||||
|
<if test="deptId != null">dept_id = #{deptId},</if>
|
||||||
|
<if test="orderType != null">order_type = #{orderType},</if>
|
||||||
|
<if test="money != null">money = #{money},</if>
|
||||||
|
<if test="amount != null">amount = #{amount},</if>
|
||||||
|
<if test="remark != null">remark = #{remark},</if>
|
||||||
|
<if test="status != null">status = #{status},</if>
|
||||||
|
</trim>
|
||||||
|
where id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<delete id="deleteAiChargeRefundOrderById" parameterType="Long">
|
||||||
|
delete from ai_charge_refund_order where id = #{id}
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
<delete id="deleteAiChargeRefundOrderByIds" parameterType="String">
|
||||||
|
delete from ai_charge_refund_order where id in
|
||||||
|
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</delete>
|
||||||
|
</mapper>
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ruoyi.ai.mapper.AiDeptArkConfigMapper">
|
||||||
|
|
||||||
|
<resultMap type="AiDeptArkConfig" id="AiDeptArkConfigResult">
|
||||||
|
<result property="id" column="id" />
|
||||||
|
<result property="deptId" column="dept_id" />
|
||||||
|
<result property="modelParm" column="model_parm" />
|
||||||
|
<result property="project" column="project" />
|
||||||
|
<result property="byteApiKey" column="byte_api_key" />
|
||||||
|
<result property="createBy" column="create_by" />
|
||||||
|
<result property="createTime" column="create_time" />
|
||||||
|
<result property="updateBy" column="update_by" />
|
||||||
|
<result property="updateTime" column="update_time" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="selectAiDeptArkConfigVo">
|
||||||
|
select id, dept_id, model_parm, project, byte_api_key, create_by, create_time, update_by, update_time from ai_dept_ark_config
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectAiDeptArkConfigList" parameterType="AiDeptArkConfig" resultMap="AiDeptArkConfigResult">
|
||||||
|
<include refid="selectAiDeptArkConfigVo"/>
|
||||||
|
<where>
|
||||||
|
<if test="deptId != null "> and dept_id = #{deptId}</if>
|
||||||
|
<if test="modelParm != null and modelParm != ''"> and model_parm = #{modelParm}</if>
|
||||||
|
<if test="project != null and project != ''"> and project = #{project}</if>
|
||||||
|
<if test="byteApiKey != null and byteApiKey != ''"> and byte_api_key = #{byteApiKey}</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectAiDeptArkConfigById" parameterType="String" resultMap="AiDeptArkConfigResult">
|
||||||
|
<include refid="selectAiDeptArkConfigVo"/>
|
||||||
|
where id = #{id}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertAiDeptArkConfig" parameterType="AiDeptArkConfig" useGeneratedKeys="true" keyProperty="id">
|
||||||
|
insert into ai_dept_ark_config
|
||||||
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="deptId != null">dept_id,</if>
|
||||||
|
<if test="modelParm != null">model_parm,</if>
|
||||||
|
<if test="project != null">project,</if>
|
||||||
|
<if test="byteApiKey != null">byte_api_key,</if>
|
||||||
|
<if test="createBy != null">create_by,</if>
|
||||||
|
<if test="createTime != null">create_time,</if>
|
||||||
|
<if test="updateBy != null">update_by,</if>
|
||||||
|
<if test="updateTime != null">update_time,</if>
|
||||||
|
</trim>
|
||||||
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="deptId != null">#{deptId},</if>
|
||||||
|
<if test="modelParm != null">#{modelParm},</if>
|
||||||
|
<if test="project != null">#{project},</if>
|
||||||
|
<if test="byteApiKey != null">#{byteApiKey},</if>
|
||||||
|
<if test="createBy != null">#{createBy},</if>
|
||||||
|
<if test="createTime != null">#{createTime},</if>
|
||||||
|
<if test="updateBy != null">#{updateBy},</if>
|
||||||
|
<if test="updateTime != null">#{updateTime},</if>
|
||||||
|
</trim>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="updateAiDeptArkConfig" parameterType="AiDeptArkConfig">
|
||||||
|
update ai_dept_ark_config
|
||||||
|
<trim prefix="SET" suffixOverrides=",">
|
||||||
|
<if test="deptId != null">dept_id = #{deptId},</if>
|
||||||
|
<if test="modelParm != null">model_parm = #{modelParm},</if>
|
||||||
|
<if test="project != null">project = #{project},</if>
|
||||||
|
<if test="byteApiKey != null">byte_api_key = #{byteApiKey},</if>
|
||||||
|
<if test="createBy != null">create_by = #{createBy},</if>
|
||||||
|
<if test="createTime != null">create_time = #{createTime},</if>
|
||||||
|
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||||
|
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||||
|
</trim>
|
||||||
|
where id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<delete id="deleteAiDeptArkConfigById" parameterType="String">
|
||||||
|
delete from ai_dept_ark_config where id = #{id}
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
<delete id="deleteAiDeptArkConfigByIds" parameterType="String">
|
||||||
|
delete from ai_dept_ark_config where id in
|
||||||
|
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</delete>
|
||||||
|
</mapper>
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ruoyi.ai.mapper.AiGroupBalanceChangeRecordMapper">
|
||||||
|
|
||||||
|
<resultMap type="AiGroupBalanceChangeRecord" id="AiGroupBalanceChangeRecordResult">
|
||||||
|
<result property="id" column="id" />
|
||||||
|
<result property="relationOrderNo" column="relation_order_no" />
|
||||||
|
<result property="deptId" column="dept_id" />
|
||||||
|
<result property="type" column="type" />
|
||||||
|
<result property="changeAmount" column="change_amount" />
|
||||||
|
<result property="resultAmount" column="result_amount" />
|
||||||
|
<result property="remark" column="remark" />
|
||||||
|
<result property="createTime" column="create_time" />
|
||||||
|
<result property="updateTime" column="update_time" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="selectAiGroupBalanceChangeRecordVo">
|
||||||
|
select id, relation_order_no, dept_id, type, change_amount, result_amount, remark, create_time, update_time from ai_group_balance_change_record
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectAiGroupBalanceChangeRecordList" parameterType="AiGroupBalanceChangeRecord" resultMap="AiGroupBalanceChangeRecordResult">
|
||||||
|
<include refid="selectAiGroupBalanceChangeRecordVo"/>
|
||||||
|
<where>
|
||||||
|
<if test="relationOrderNo != null and relationOrderNo != ''"> and relation_order_no = #{relationOrderNo}</if>
|
||||||
|
<if test="deptId != null "> and dept_id = #{deptId}</if>
|
||||||
|
<if test="type != null "> and type = #{type}</if>
|
||||||
|
<if test="changeAmount != null "> and change_amount = #{changeAmount}</if>
|
||||||
|
<if test="resultAmount != null "> and result_amount = #{resultAmount}</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectAiGroupBalanceChangeRecordById" parameterType="String" resultMap="AiGroupBalanceChangeRecordResult">
|
||||||
|
<include refid="selectAiGroupBalanceChangeRecordVo"/>
|
||||||
|
where id = #{id}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertAiGroupBalanceChangeRecord" parameterType="AiGroupBalanceChangeRecord" useGeneratedKeys="true" keyProperty="id">
|
||||||
|
insert into ai_group_balance_change_record
|
||||||
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="relationOrderNo != null">relation_order_no,</if>
|
||||||
|
<if test="deptId != null">dept_id,</if>
|
||||||
|
<if test="type != null">type,</if>
|
||||||
|
<if test="changeAmount != null">change_amount,</if>
|
||||||
|
<if test="resultAmount != null">result_amount,</if>
|
||||||
|
<if test="remark != null">remark,</if>
|
||||||
|
<if test="createTime != null">create_time,</if>
|
||||||
|
<if test="updateTime != null">update_time,</if>
|
||||||
|
</trim>
|
||||||
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="relationOrderNo != null">#{relationOrderNo},</if>
|
||||||
|
<if test="deptId != null">#{deptId},</if>
|
||||||
|
<if test="type != null">#{type},</if>
|
||||||
|
<if test="changeAmount != null">#{changeAmount},</if>
|
||||||
|
<if test="resultAmount != null">#{resultAmount},</if>
|
||||||
|
<if test="remark != null">#{remark},</if>
|
||||||
|
<if test="createTime != null">#{createTime},</if>
|
||||||
|
<if test="updateTime != null">#{updateTime},</if>
|
||||||
|
</trim>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="updateAiGroupBalanceChangeRecord" parameterType="AiGroupBalanceChangeRecord">
|
||||||
|
update ai_group_balance_change_record
|
||||||
|
<trim prefix="SET" suffixOverrides=",">
|
||||||
|
<if test="relationOrderNo != null">relation_order_no = #{relationOrderNo},</if>
|
||||||
|
<if test="deptId != null">dept_id = #{deptId},</if>
|
||||||
|
<if test="type != null">type = #{type},</if>
|
||||||
|
<if test="changeAmount != null">change_amount = #{changeAmount},</if>
|
||||||
|
<if test="resultAmount != null">result_amount = #{resultAmount},</if>
|
||||||
|
<if test="remark != null">remark = #{remark},</if>
|
||||||
|
<if test="createTime != null">create_time = #{createTime},</if>
|
||||||
|
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||||
|
</trim>
|
||||||
|
where id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<delete id="deleteAiGroupBalanceChangeRecordById" parameterType="String">
|
||||||
|
delete from ai_group_balance_change_record where id = #{id}
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
<delete id="deleteAiGroupBalanceChangeRecordByIds" parameterType="String">
|
||||||
|
delete from ai_group_balance_change_record where id in
|
||||||
|
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</delete>
|
||||||
|
</mapper>
|
||||||
|
|
@ -0,0 +1,161 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ruoyi.ai.mapper.AiVideoReportDataMapper">
|
||||||
|
|
||||||
|
<resultMap type="AiVideoReportData" id="AiVideoReportDataResult">
|
||||||
|
<result property="id" column="id" />
|
||||||
|
<result property="dateKey" column="date_key" />
|
||||||
|
<result property="deptId" column="dept_id" />
|
||||||
|
<result property="userId" column="user_id" />
|
||||||
|
<result property="score" column="score" />
|
||||||
|
<result property="orderCount" column="order_count" />
|
||||||
|
<result property="useTokens" column="use_tokens" />
|
||||||
|
<result property="rechargeScore" column="recharge_score" />
|
||||||
|
<result property="deptName" column="dept_name" />
|
||||||
|
<result property="createTime" column="create_time" />
|
||||||
|
<result property="updateTime" column="update_time" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="selectAiVideoReportDataVo">
|
||||||
|
select id, date_key, dept_id, user_id, score, order_count, use_tokens, recharge_score, create_time, update_time from ai_video_report_data
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectAiVideoReportDataList" parameterType="AiVideoReportData" resultMap="AiVideoReportDataResult">
|
||||||
|
<include refid="selectAiVideoReportDataVo"/>
|
||||||
|
<where>
|
||||||
|
<if test="dateKey != null and dateKey != ''"> and date_key = #{dateKey}</if>
|
||||||
|
<if test="deptId != null "> and dept_id = #{deptId}</if>
|
||||||
|
<if test="userId != null "> and user_id = #{userId}</if>
|
||||||
|
<if test="score != null "> and score = #{score}</if>
|
||||||
|
<if test="orderCount != null "> and order_count = #{orderCount}</if>
|
||||||
|
<if test="useTokens != null "> and use_tokens = #{useTokens}</if>
|
||||||
|
<if test="rechargeScore != null "> and recharge_score = #{rechargeScore}</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectAiVideoReportDataById" parameterType="String" resultMap="AiVideoReportDataResult">
|
||||||
|
<include refid="selectAiVideoReportDataVo"/>
|
||||||
|
where id = #{id}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertAiVideoReportData" parameterType="AiVideoReportData" useGeneratedKeys="true" keyProperty="id">
|
||||||
|
insert into ai_video_report_data
|
||||||
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="dateKey != null and dateKey != ''">date_key,</if>
|
||||||
|
<if test="deptId != null">dept_id,</if>
|
||||||
|
<if test="userId != null">user_id,</if>
|
||||||
|
<if test="score != null">score,</if>
|
||||||
|
<if test="orderCount != null">order_count,</if>
|
||||||
|
<if test="useTokens != null">use_tokens,</if>
|
||||||
|
<if test="rechargeScore != null">recharge_score,</if>
|
||||||
|
<if test="createTime != null">create_time,</if>
|
||||||
|
<if test="updateTime != null">update_time,</if>
|
||||||
|
</trim>
|
||||||
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="dateKey != null and dateKey != ''">#{dateKey},</if>
|
||||||
|
<if test="deptId != null">#{deptId},</if>
|
||||||
|
<if test="userId != null">#{userId},</if>
|
||||||
|
<if test="score != null">#{score},</if>
|
||||||
|
<if test="orderCount != null">#{orderCount},</if>
|
||||||
|
<if test="useTokens != null">#{useTokens},</if>
|
||||||
|
<if test="rechargeScore != null">#{rechargeScore},</if>
|
||||||
|
<if test="createTime != null">#{createTime},</if>
|
||||||
|
<if test="updateTime != null">#{updateTime},</if>
|
||||||
|
</trim>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="updateAiVideoReportData" parameterType="AiVideoReportData">
|
||||||
|
update ai_video_report_data
|
||||||
|
<trim prefix="SET" suffixOverrides=",">
|
||||||
|
<if test="dateKey != null and dateKey != ''">date_key = #{dateKey},</if>
|
||||||
|
<if test="deptId != null">dept_id = #{deptId},</if>
|
||||||
|
<if test="userId != null">user_id = #{userId},</if>
|
||||||
|
<if test="score != null">score = #{score},</if>
|
||||||
|
<if test="orderCount != null">order_count = #{orderCount},</if>
|
||||||
|
<if test="useTokens != null">use_tokens = #{useTokens},</if>
|
||||||
|
<if test="rechargeScore != null">recharge_score = #{rechargeScore},</if>
|
||||||
|
<if test="createTime != null">create_time = #{createTime},</if>
|
||||||
|
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||||
|
</trim>
|
||||||
|
where id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<select id="selectTeamDailyConsumeList" resultMap="AiVideoReportDataResult">
|
||||||
|
select
|
||||||
|
concat(substr(vrd.date_key, 1, 4), '-', substr(vrd.date_key, 5, 2), '-', substr(vrd.date_key, 7, 2)) 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
|
||||||
|
where vrd.date_key like concat(#{statDate}, '%')
|
||||||
|
and vrd.dept_id = #{deptId}
|
||||||
|
group by substr(vrd.date_key, 1, 8), vrd.dept_id, d.dept_name
|
||||||
|
order by substr(vrd.date_key, 1, 8) desc, vrd.dept_id desc
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectTeamDailyConsumeByDeptId" resultMap="AiVideoReportDataResult">
|
||||||
|
select
|
||||||
|
concat(substr(vrd.date_key, 1, 4), '-', substr(vrd.date_key, 5, 2), '-', substr(vrd.date_key, 7, 2)) 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
|
||||||
|
where vrd.date_key like concat(#{statDate}, '%')
|
||||||
|
and vrd.dept_id = #{deptId}
|
||||||
|
group by substr(vrd.date_key, 1, 8), vrd.dept_id, d.dept_name
|
||||||
|
order by substr(vrd.date_key, 1, 8) desc, vrd.dept_id desc
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectDeptVideoMetricsBetween" resultType="com.ruoyi.system.domain.subteam.SubteamVideoMetrics">
|
||||||
|
select
|
||||||
|
coalesce(sum(vrd.score), 0) as consumeScore,
|
||||||
|
coalesce(sum(vrd.order_count), 0) as orderCount
|
||||||
|
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>
|
||||||
|
|
||||||
|
<insert id="upsertVideoConsumeIncrement">
|
||||||
|
insert into ai_video_report_data
|
||||||
|
(date_key, dept_id, user_id, score, order_count, use_tokens, recharge_score, create_time, update_time)
|
||||||
|
values
|
||||||
|
(#{dateKey}, #{deptId}, #{userId}, #{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, user_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>
|
||||||
|
|
||||||
|
<delete id="deleteAiVideoReportDataById" parameterType="String">
|
||||||
|
delete from ai_video_report_data where id = #{id}
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
<delete id="deleteAiVideoReportDataByIds" parameterType="String">
|
||||||
|
delete from ai_video_report_data where id in
|
||||||
|
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</delete>
|
||||||
|
</mapper>
|
||||||
|
|
@ -43,6 +43,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
</where>
|
</where>
|
||||||
order by r.id desc
|
order by r.id desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectAiBalanceChangeRecordListByAiUserDept" resultMap="AiBalanceChangeRecordResult">
|
||||||
|
<include refid="selectAiBalanceChangeRecordVo"/>
|
||||||
|
<where>
|
||||||
|
and u.dept_id = #{deptId}
|
||||||
|
<if test="q.nickname != null and q.nickname != '' "> and u.nickname like concat('%', #{q.nickname}, '%') </if>
|
||||||
|
<if test="q.userId != null "> and r.user_id = #{q.userId}</if>
|
||||||
|
<if test="q.uuid != null "> and u.user_id = #{q.uuid}</if>
|
||||||
|
<if test="q.type != null "> and r.type = #{q.type}</if>
|
||||||
|
<if test="q.changeAmount != null "> and r.change_amount = #{q.changeAmount}</if>
|
||||||
|
<if test="q.resultAmount != null "> and r.result_amount = #{q.resultAmount}</if>
|
||||||
|
<if test="q.params != null and q.params.beginTime != null and q.params.beginTime != ''">
|
||||||
|
AND date_format(r.create_time,'%Y%m%d') >= date_format(#{q.params.beginTime},'%Y%m%d')
|
||||||
|
</if>
|
||||||
|
<if test="q.params != null and q.params.endTime != null and q.params.endTime != ''">
|
||||||
|
AND date_format(r.create_time,'%Y%m%d') <= date_format(#{q.params.endTime},'%Y%m%d')
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
order by r.id desc
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectAiBalanceChangeRecordById" parameterType="Long" resultMap="AiBalanceChangeRecordResult">
|
<select id="selectAiBalanceChangeRecordById" parameterType="Long" resultMap="AiBalanceChangeRecordResult">
|
||||||
<include refid="selectAiBalanceChangeRecordVo"/>
|
<include refid="selectAiBalanceChangeRecordVo"/>
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,4 @@ CREATE TABLE `ai_charge_refund_order` (
|
||||||
)
|
)
|
||||||
COMMENT='团队(部门)充值退款订单表'
|
COMMENT='团队(部门)充值退款订单表'
|
||||||
COLLATE='utf8mb4_unicode_ci'
|
COLLATE='utf8mb4_unicode_ci'
|
||||||
ENGINE=InnoDB;
|
ENGINE=InnoDB;
|
||||||
|
|
||||||
ALTER TABLE `ai_user`
|
|
||||||
ADD INDEX `dept_id` (`dept_id`);
|
|
||||||
|
|
@ -193,3 +193,5 @@ values('团队(部门)对应火山引擎配置删除', @parentId, '4', '#',
|
||||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||||
values('团队(部门)对应火山引擎配置导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', 'ai:config:export', '#', 'admin', sysdate(), '', null, '');
|
values('团队(部门)对应火山引擎配置导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', 'ai:config:export', '#', 'admin', sysdate(), '', null, '');
|
||||||
|
|
||||||
|
ALTER TABLE `byteai`.`ai_balance_change_record`
|
||||||
|
ADD COLUMN `dept_id` bigint NULL COMMENT '部门ID' AFTER `remark`;
|
||||||
Loading…
Reference in New Issue