feat: 团队后台 - 团队用户,增加下放、回收积分

This commit is contained in:
yys 2026-04-23 12:31:37 +08:00
parent ba675ce0e0
commit 9eb8514fdf
6 changed files with 120 additions and 9 deletions

View File

@ -33,6 +33,16 @@ export function changeSubteamUserStatus(data) {
return request({ url: '/subteam/user/changeStatus', method: 'put', data }) return request({ url: '/subteam/user/changeStatus', method: 'put', data })
} }
/** 团队后台:部门积分下放至本团队用户 */
export function issueSubteamUserDeptScore(data) {
return request({ url: '/subteam/user/dept-score/issue', method: 'put', data })
}
/** 团队后台:本团队用户积分回收至部门 */
export function reclaimSubteamUserDeptScore(data) {
return request({ url: '/subteam/user/dept-score/reclaim', method: 'put', data })
}
export function listSubteamVideoOrder(query) { export function listSubteamVideoOrder(query) {
return request({ url: '/subteam/video-order/list', method: 'get', params: query }) return request({ url: '/subteam/video-order/list', method: 'get', params: query })
} }

View File

@ -17,10 +17,10 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="用户账号" prop="username"> <el-form-item label="账号" prop="username">
<el-input <el-input
v-model="queryParams.username" v-model="queryParams.username"
placeholder="请输入用户账号" placeholder="请输入账号"
clearable clearable
style="width: 150px" style="width: 150px"
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
@ -82,7 +82,7 @@
<el-table-column type="selection" width="50" align="center" /> <el-table-column type="selection" width="50" align="center" />
<el-table-column label="主键ID" align="center" prop="id" width="60" /> <el-table-column label="主键ID" align="center" prop="id" width="60" />
<el-table-column label="用户ID" align="center" prop="userId" /> <el-table-column label="用户ID" align="center" prop="userId" />
<el-table-column label="用户账号" align="center" prop="username" /> <el-table-column label="账号" align="center" prop="username" />
<!-- <!--
<el-table-column label="上级ID" align="center" prop="superiorUuid" /> <el-table-column label="上级ID" align="center" prop="superiorUuid" />
<el-table-column label="上级账号" align="center" prop="superiorName" /> <el-table-column label="上级账号" align="center" prop="superiorName" />
@ -160,6 +160,13 @@
v-hasPermi="['ai:user:remove']" v-hasPermi="['ai:user:remove']"
>修改余额</el-button> >修改余额</el-button>
--> -->
<el-button
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleUpdate(scope.row)"
v-hasPermi="['ai:user:edit']"
>修改</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"

View File

@ -48,7 +48,11 @@
<el-table-column label="主键ID" prop="id" width="80" /> <el-table-column label="主键ID" prop="id" width="80" />
<el-table-column label="账号" prop="username" /> <el-table-column label="账号" prop="username" />
<el-table-column label="昵称" prop="nickname" /> <el-table-column label="昵称" prop="nickname" />
<el-table-column label="团队" prop="deptName" /> <el-table-column label="剩余积分" prop="balance" width="120" align="center" header-align="center">
<template slot-scope="scope">
<span>{{ formatThousands(scope.row.balance) }}</span>
</template>
</el-table-column>
<el-table-column label="手机" prop="phone" width="120" /> <el-table-column label="手机" prop="phone" width="120" />
<el-table-column label="状态" width="80"> <el-table-column label="状态" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
@ -62,14 +66,14 @@
type="text" type="text"
icon="el-icon-download" icon="el-icon-download"
@click="openDeptScoreDialog(scope.row, 'issue')" @click="openDeptScoreDialog(scope.row, 'issue')"
v-hasPermi="['ai:user:deptScoreIssue']" v-hasPermi="['subteam:user:deptScoreIssue']"
>下放积分</el-button> >下放积分</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-upload2" icon="el-icon-upload2"
@click="openDeptScoreDialog(scope.row, 'reclaim')" @click="openDeptScoreDialog(scope.row, 'reclaim')"
v-hasPermi="['ai:user:deptScoreReclaim']" v-hasPermi="['subteam:user:deptScoreReclaim']"
>回收积分</el-button> >回收积分</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: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:resetPwd']" size="mini" type="text" icon="el-icon-key" @click="handleResetPwd(scope.row)">密码</el-button>
@ -148,9 +152,8 @@
<script> <script>
import { import {
listSubteamUser, getSubteamUser, addSubteamUser, updateSubteamUser, delSubteamUser, listSubteamUser, getSubteamUser, addSubteamUser, updateSubteamUser, delSubteamUser,
resetSubteamUserPwd resetSubteamUserPwd, issueSubteamUserDeptScore, reclaimSubteamUserDeptScore
} from '@/api/subteam' } from '@/api/subteam'
import { issueDeptScore, reclaimDeptScore } from '@/api/ai/user'
export default { export default {
name: 'SubteamUser', name: 'SubteamUser',
@ -203,6 +206,16 @@ export default {
this.getList() this.getList()
}, },
methods: { methods: {
formatThousands(value) {
if (value === null || value === undefined || value === '') {
return '—'
}
const n = Number(value)
if (Number.isNaN(n)) {
return String(value)
}
return n.toLocaleString('en-US', { maximumFractionDigits: 0 })
},
getList() { getList() {
this.loading = true this.loading = true
listSubteamUser(this.addDateRange(this.queryParams, this.dateRange, 'CreateTime')).then(res => { listSubteamUser(this.addDateRange(this.queryParams, this.dateRange, 'CreateTime')).then(res => {
@ -301,7 +314,7 @@ export default {
amount, amount,
remark: this.deptScoreForm.remark || undefined remark: this.deptScoreForm.remark || undefined
} }
const req = this.deptScoreMode === 'issue' ? issueDeptScore : reclaimDeptScore const req = this.deptScoreMode === 'issue' ? issueSubteamUserDeptScore : reclaimSubteamUserDeptScore
req(payload).then(() => { req(payload).then(() => {
this.$modal.msgSuccess('操作成功') this.$modal.msgSuccess('操作成功')
this.deptScoreOpen = false this.deptScoreOpen = false

View File

@ -1,6 +1,7 @@
package com.ruoyi.web.controller.subteam; package com.ruoyi.web.controller.subteam;
import java.util.List; import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -19,7 +20,9 @@ import com.ruoyi.common.core.domain.entity.AiUser;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.request.ai.AiUserDeptScoreRequest;
import com.ruoyi.ai.service.IAiUserService; import com.ruoyi.ai.service.IAiUserService;
import com.ruoyi.ai.service.IDeptUserScoreTransferService;
import com.ruoyi.system.service.subteam.ISubteamScopeService; import com.ruoyi.system.service.subteam.ISubteamScopeService;
@RestController @RestController
@ -32,6 +35,9 @@ public class SubteamUserController extends BaseController {
@Autowired @Autowired
private ISubteamScopeService subteamScopeService; private ISubteamScopeService subteamScopeService;
@Autowired
private IDeptUserScoreTransferService deptUserScoreTransferService;
@PreAuthorize("@ss.hasPermi('subteam:user:list')") @PreAuthorize("@ss.hasPermi('subteam:user:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(AiUser aiUser) { public TableDataInfo list(AiUser aiUser) {
@ -115,4 +121,22 @@ public class SubteamUserController extends BaseController {
aiUser.setUpdateBy(getUsername()); aiUser.setUpdateBy(getUsername());
return toAjax(aiUserService.updateUserStatus(aiUser)); return toAjax(aiUserService.updateUserStatus(aiUser));
} }
@PreAuthorize("@ss.hasPermi('subteam:user:deptScoreIssue')")
@Log(title = "团队后台用户部门积分下放", businessType = BusinessType.UPDATE)
@PutMapping("/dept-score/issue")
public AjaxResult issueDeptScore(@Valid @RequestBody AiUserDeptScoreRequest request) {
subteamScopeService.assertAiUserInTeam(request.getUserId());
deptUserScoreTransferService.issueDeptScore(request);
return success();
}
@PreAuthorize("@ss.hasPermi('subteam:user:deptScoreReclaim')")
@Log(title = "团队后台用户部门积分回收", businessType = BusinessType.UPDATE)
@PutMapping("/dept-score/reclaim")
public AjaxResult reclaimDeptScore(@Valid @RequestBody AiUserDeptScoreRequest request) {
subteamScopeService.assertAiUserInTeam(request.getUserId());
deptUserScoreTransferService.reclaimDeptScore(request);
return success();
}
} }

View File

@ -61,6 +61,10 @@ insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame
values('用户删除', @m1, '4', '#', '', 1, 0, 'F', '0', '0', 'subteam:user:remove', '#', 'admin', sysdate(), '', null, ''); values('用户删除', @m1, '4', '#', '', 1, 0, 'F', '0', '0', 'subteam:user:remove', '#', 'admin', sysdate(), '', null, '');
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('重置密码', @m1, '5', '#', '', 1, 0, 'F', '0', '0', 'subteam:user:resetPwd', '#', 'admin', sysdate(), '', null, ''); values('重置密码', @m1, '5', '#', '', 1, 0, 'F', '0', '0', 'subteam:user:resetPwd', '#', 'admin', sysdate(), '', null, '');
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('下放积分', @m1, '6', '#', '', 1, 0, 'F', '0', '0', 'subteam:user:deptScoreIssue', '#', 'admin', sysdate(), '', null, '');
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('回收积分', @m1, '7', '#', '', 1, 0, 'F', '0', '0', 'subteam:user:deptScoreReclaim', '#', 'admin', sysdate(), '', null, '');
-- 视频订单 -- 视频订单
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)

View File

@ -0,0 +1,53 @@
-- =============================================================================
-- 团队后台「用户管理」下级权限:下放积分、回收积分(菜单类型 F
-- 可重复执行:已存在相同 perms 时跳过插入
-- =============================================================================
SET @subteam_user_menu_id := (
SELECT menu_id FROM sys_menu
WHERE menu_type = 'C'
AND perms = 'subteam:user:list'
AND component = 'subteam/user/index'
ORDER BY menu_id
LIMIT 1
);
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
)
SELECT
'下放积分', @subteam_user_menu_id, 6, '#', '', 1, 0, 'F', '0', '0', 'subteam:user:deptScoreIssue', '#',
'admin', sysdate(), '', null, '团队后台:部门积分下放至本团队用户'
FROM (SELECT 1) AS _x
WHERE @subteam_user_menu_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'subteam:user:deptScoreIssue');
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
)
SELECT
'回收积分', @subteam_user_menu_id, 7, '#', '', 1, 0, 'F', '0', '0', 'subteam:user:deptScoreReclaim', '#',
'admin', sysdate(), '', null, '团队后台:本团队用户积分回收至部门'
FROM (SELECT 1) AS _y
WHERE @subteam_user_menu_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = 'subteam:user:deptScoreReclaim');
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT DISTINCT rm.role_id, m.menu_id
FROM sys_role_menu rm
JOIN sys_menu m ON m.perms = 'subteam:user:deptScoreIssue'
WHERE rm.menu_id = @subteam_user_menu_id
AND NOT EXISTS (
SELECT 1 FROM sys_role_menu x WHERE x.role_id = rm.role_id AND x.menu_id = m.menu_id
);
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT DISTINCT rm.role_id, m.menu_id
FROM sys_role_menu rm
JOIN sys_menu m ON m.perms = 'subteam:user:deptScoreReclaim'
WHERE rm.menu_id = @subteam_user_menu_id
AND NOT EXISTS (
SELECT 1 FROM sys_role_menu x WHERE x.role_id = rm.role_id AND x.menu_id = m.menu_id
);