-
+
搜索
重置
-
-
-
-
-
导出
-
-
-
+
+
+
-
+
{{ typeLabel(scope.row.type) }}
-
-
+
+
@@ -116,6 +123,38 @@ export default {
this.getList()
},
methods: {
+ /** 西式千分位,积分为整数 */
+ formatPointsWestern(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 })
+ },
+ formatChangeAmount(row) {
+ const value = row.changeAmount
+ if (value === null || value === undefined || value === "") {
+ return ""
+ }
+ const n = Number(value)
+ if (Number.isNaN(n)) {
+ return String(value)
+ }
+ const formatted = Math.abs(n).toLocaleString("en-US", { maximumFractionDigits: 0 })
+ if (n > 0) {
+ return `+${formatted}`
+ }
+ if (n < 0) {
+ return `-${formatted}`
+ }
+ return "0"
+ },
+ formatResultAmount(row) {
+ return this.formatPointsWestern(row.resultAmount)
+ },
typeLabel(type) {
const n = type !== undefined && type !== null ? Number(type) : null
const hit = this.typeOptions.find(item => item.value === n)
diff --git a/admin-ui/src/views/ai/user/index.vue b/admin-ui/src/views/ai/user/index.vue
index d5d61fd..608c0e2 100644
--- a/admin-ui/src/views/ai/user/index.vue
+++ b/admin-ui/src/views/ai/user/index.vue
@@ -116,7 +116,11 @@
{{ parseTime(scope.row.loginTime, '{y}-{m}-{d} {h}:{i}:{s}') }}
-
+
+
+ {{ formatThousands(scope.row.balance) }}
+
+
{
this.deptOptions = this.handleTree(res.data, "deptId");
diff --git a/admin-ui/src/views/index copy.vue b/admin-ui/src/views/index copy.vue
index 42c7a76..5dd0815 100644
--- a/admin-ui/src/views/index copy.vue
+++ b/admin-ui/src/views/index copy.vue
@@ -218,7 +218,7 @@
-
+
diff --git a/admin-ui/src/views/monitor/online/index.vue b/admin-ui/src/views/monitor/online/index.vue
index 048e51d..6065ccd 100644
--- a/admin-ui/src/views/monitor/online/index.vue
+++ b/admin-ui/src/views/monitor/online/index.vue
@@ -35,7 +35,7 @@
-
+
diff --git a/admin-ui/src/views/subteam/chargeOrder/index.vue b/admin-ui/src/views/subteam/chargeOrder/index.vue
index de285ac..56b7746 100644
--- a/admin-ui/src/views/subteam/chargeOrder/index.vue
+++ b/admin-ui/src/views/subteam/chargeOrder/index.vue
@@ -33,8 +33,12 @@
{{ typeLabel(s.row.orderType) }}
-
-
+
+ {{ formatMoney(s.row.money) }}
+
+
+ {{ formatAmount(s.row.amount) }}
+
{{ parseTime(s.row.createTime) }}
@@ -58,6 +62,18 @@ export default {
},
created() { this.getList() },
methods: {
+ formatMoney(value) {
+ if (value == null || value === '') return '—'
+ const n = Number(value)
+ if (Number.isNaN(n)) return '—'
+ return n.toLocaleString('en-US', { maximumFractionDigits: 2, minimumFractionDigits: 0 })
+ },
+ formatAmount(value) {
+ if (value == null || value === '') return '—'
+ const n = Number(value)
+ if (Number.isNaN(n)) return '—'
+ return n.toLocaleString('en-US', { maximumFractionDigits: 0 })
+ },
typeLabel(t) {
const m = { 0: '充值', 1: '退款', 2: '手动修改' }
return m[t] != null ? m[t] : '—'
diff --git a/admin-ui/src/views/subteam/groupBalance/index.vue b/admin-ui/src/views/subteam/groupBalance/index.vue
index ed84c1d..08a56e9 100644
--- a/admin-ui/src/views/subteam/groupBalance/index.vue
+++ b/admin-ui/src/views/subteam/groupBalance/index.vue
@@ -34,8 +34,12 @@
{{ typeLabel(s.row.type) }}
-
-
+
+ {{ formatChangeAmount(s.row) }}
+
+
+ {{ formatResultAmount(s.row) }}
+
{{ parseTime(s.row.createTime) }}
@@ -65,6 +69,33 @@ export default {
},
created() { this.getList() },
methods: {
+ formatPointsWestern(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 })
+ },
+ formatChangeAmount(row) {
+ const value = row.changeAmount
+ if (value === null || value === undefined || value === '') {
+ return ''
+ }
+ const n = Number(value)
+ if (Number.isNaN(n)) {
+ return String(value)
+ }
+ const formatted = Math.abs(n).toLocaleString('en-US', { maximumFractionDigits: 0 })
+ if (n > 0) return `+${formatted}`
+ if (n < 0) return `-${formatted}`
+ return '0'
+ },
+ formatResultAmount(row) {
+ return this.formatPointsWestern(row.resultAmount)
+ },
typeLabel(type) {
const n = type !== undefined && type !== null ? Number(type) : null
const hit = this.typeOptions.find(item => item.value === n)
diff --git a/admin-ui/src/views/subteam/overview/index.vue b/admin-ui/src/views/subteam/overview/index.vue
index 02e9925..9733710 100644
--- a/admin-ui/src/views/subteam/overview/index.vue
+++ b/admin-ui/src/views/subteam/overview/index.vue
@@ -18,7 +18,7 @@
- AI用户数(实时)
{{ info.aiUserCount }}
+ AI用户数(实时)
{{ aiUserCountText }}
近 7 日消耗积分 (5 分钟缓存)
{{ info.last7DaysConsumeScore }}
@@ -44,6 +44,17 @@ export default {
created() {
this.load()
},
+ computed: {
+ aiUserCountText() {
+ const cur = this.info.aiUserCount
+ const max = this.info.aiUserMaxCount
+ const left = cur != null && cur !== '' ? cur : 0
+ if (max == null || max <= 0) {
+ return left + '/无限制'
+ }
+ return left + '/' + max
+ }
+ },
methods: {
load() {
this.loading = true
diff --git a/admin-ui/src/views/subteam/user/index.vue b/admin-ui/src/views/subteam/user/index.vue
index 56238b3..d46122b 100644
--- a/admin-ui/src/views/subteam/user/index.vue
+++ b/admin-ui/src/views/subteam/user/index.vue
@@ -48,7 +48,7 @@
-
+
diff --git a/admin-ui/src/views/system/dept/index.vue b/admin-ui/src/views/system/dept/index.vue
index d596436..cec682c 100644
--- a/admin-ui/src/views/system/dept/index.vue
+++ b/admin-ui/src/views/system/dept/index.vue
@@ -50,7 +50,7 @@
- {{ scope.row.balance != null ? scope.row.balance : '—' }}
+ {{ formatDeptBalance(scope.row.balance) }}
@@ -177,14 +177,14 @@
:max="999999"
:precision="0"
controls-position="right"
- placeholder="0=不限制"
+ placeholder="0 表示不限制"
style="width: 100%"
:disabled="isFirstLevelEditForm"
/>
- 限制本团队下「启用」状态账号数量;0 或不填表示不限制。
+ 限制本团队下「启用」状态账号数量;0 表示不限制。
@@ -322,15 +322,12 @@
>
-
@@ -380,7 +377,7 @@
color: #e6a23c;
font-size: 12px;
}
-.edit-score-input-number {
+.edit-score-input {
width: 100%;
}
@@ -395,7 +392,10 @@ import {
formatMoneyWesternFinal,
sanitizeIntDigits,
formatIntWesternDisplay,
- intStringToNumber
+ intStringToNumber,
+ sanitizeSignedIntDigits,
+ formatSignedIntDisplay,
+ signedIntStringToNumber
} from "@/utils/westernNumberFormat"
import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
@@ -454,6 +454,7 @@ export default {
]
},
editScoreOpen: false,
+ editScoreScoreDisplay: "",
editScoreForm: {
deptId: undefined,
deptName: "",
@@ -531,6 +532,16 @@ export default {
message: "请输入正确的手机号码",
trigger: "blur"
}
+ ],
+ maxUserCount: [
+ { required: true, message: "账号上限不能为空", trigger: "change" },
+ {
+ type: "number",
+ min: 0,
+ max: 999999,
+ message: "账号上限须为 0–999999 的整数,0 表示不限制",
+ trigger: "change"
+ }
]
}
}
@@ -544,6 +555,22 @@ export default {
}
},
methods: {
+ /** 列表「剩余积分」:西式千分位,与业务积分展示一致;空为 — */
+ formatDeptBalance(value) {
+ if (value == null || value === "") {
+ return "—"
+ }
+ const n = Number(value)
+ if (Number.isNaN(n)) {
+ return "—"
+ }
+ return n.toLocaleString("en-US", { maximumFractionDigits: 2, minimumFractionDigits: 0 })
+ },
+ onEditScoreInput(val) {
+ const s = sanitizeSignedIntDigits(val)
+ this.editScoreScoreDisplay = s === "" ? "" : s === "-" ? "-" : formatSignedIntDisplay(s)
+ this.editScoreForm.score = signedIntStringToNumber(s)
+ },
isFirstLevelRow(row) {
if (!row) {
return false
@@ -711,6 +738,7 @@ export default {
})
},
resetEditScore() {
+ this.editScoreScoreDisplay = ""
this.editScoreForm = {
deptId: undefined,
deptName: "",
@@ -727,6 +755,7 @@ export default {
if (!this.isFirstLevelRow(row) && !this.isSecondLevelRow(row)) {
return
}
+ this.editScoreScoreDisplay = ""
this.editScoreForm = {
deptId: row.deptId,
deptName: row.deptName,
@@ -807,7 +836,7 @@ export default {
leader: undefined,
phone: undefined,
email: undefined,
- maxUserCount: undefined,
+ maxUserCount: 0,
status: "0"
}
this.originalForm = {}
@@ -832,6 +861,7 @@ export default {
}
this.form.parentId = row.deptId
}
+ this.form.maxUserCount = 0
this.open = true
this.title = "添加二级团队"
listDept().then(response => {
@@ -850,8 +880,11 @@ export default {
handleUpdate(row) {
this.reset()
getDept(row.deptId).then(response => {
- this.form = response.data
+ this.form = { ...response.data }
this.originalForm = { ...response.data }
+ if (this.form.maxUserCount == null) {
+ this.form.maxUserCount = 0
+ }
this.open = true
this.title = "修改团队"
listDeptExcludeChild(row.deptId).then(response => {
diff --git a/admin-ui/src/views/system/role/index.vue b/admin-ui/src/views/system/role/index.vue
index ab01a4a..d39b5a0 100644
--- a/admin-ui/src/views/system/role/index.vue
+++ b/admin-ui/src/views/system/role/index.vue
@@ -298,11 +298,11 @@ export default {
},
{
value: "3",
- label: "本部门数据权限"
+ label: "本团队数据权限"
},
{
value: "4",
- label: "本部门及以下数据权限"
+ label: "本团队及以下数据权限"
},
{
value: "5",
diff --git a/admin-ui/src/views/system/user/index.vue b/admin-ui/src/views/system/user/index.vue
index 6ed32d6..9a3f5ad 100644
--- a/admin-ui/src/views/system/user/index.vue
+++ b/admin-ui/src/views/system/user/index.vue
@@ -6,7 +6,7 @@
-
+
@@ -61,7 +61,7 @@
-
+
@@ -236,7 +236,7 @@ export default {
enabledDeptOptions: undefined,
// 是否显示弹出层
open: false,
- // 部门名称
+ // 团队名称
deptName: undefined,
// 默认密码
initPassword: undefined,
diff --git a/admin-ui/src/views/system/user/profile/index.vue b/admin-ui/src/views/system/user/profile/index.vue
index c070cd1..a4a5acf 100644
--- a/admin-ui/src/views/system/user/profile/index.vue
+++ b/admin-ui/src/views/system/user/profile/index.vue
@@ -24,7 +24,7 @@
{{ user.email }}
- 所属部门
+ 所属团队
{{ user.dept.deptName }} / {{ postGroup }}
diff --git a/portal-ui/src/views/GeneratedAssets.vue b/portal-ui/src/views/GeneratedAssets.vue
index 0ab9319..4485525 100644
--- a/portal-ui/src/views/GeneratedAssets.vue
+++ b/portal-ui/src/views/GeneratedAssets.vue
@@ -6,7 +6,7 @@
@@ -303,7 +303,7 @@ export default {
beginTime: '',
endTime: ''
},
- activeTab: 'personal', // 'personal'个人, 'department'部门
+ activeTab: 'personal', // 'personal'个人, 'department'团队
pagination: {
total: 0,
pageNum: 1,
@@ -331,7 +331,7 @@ export default {
pageSize: this.pagination.pageSize
}
console.log("this.activeTab", this.activeTab)
- // 视图模式参数:personal = 个人, department = 部门视图(传 dept=true)
+ // 视图模式参数:personal = 个人, department = 团队视图(传 dept=true)
if (this.activeTab === 'department') {
params.dept = true
}
diff --git a/web-api/ruoyi-admin/src/main/java/com/ruoyi/ai/controller/AiChargeRefundOrderController.java b/web-api/ruoyi-admin/src/main/java/com/ruoyi/ai/controller/AiChargeRefundOrderController.java
index a9570b5..c4402ce 100644
--- a/web-api/ruoyi-admin/src/main/java/com/ruoyi/ai/controller/AiChargeRefundOrderController.java
+++ b/web-api/ruoyi-admin/src/main/java/com/ruoyi/ai/controller/AiChargeRefundOrderController.java
@@ -47,13 +47,13 @@ public class AiChargeRefundOrderController extends BaseController
* 导出团队(部门)充值退款订单列表
*/
@PreAuthorize("@ss.hasPermi('ai:groupChargeOrder:export')")
- @Log(title = "团队(部门)充值退款订单", businessType = BusinessType.EXPORT)
+ @Log(title = "团队充值退款订单", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, AiChargeRefundOrder aiChargeRefundOrder)
{
List list = aiChargeRefundOrderService.selectAiChargeRefundOrderList(aiChargeRefundOrder);
ExcelUtil util = new ExcelUtil(AiChargeRefundOrder.class);
- util.exportExcel(response, list, "团队(部门)充值退款订单数据");
+ util.exportExcel(response, list, "团队充值退款订单数据");
}
/**
diff --git a/web-api/ruoyi-admin/src/main/java/com/ruoyi/ai/controller/AiDeptArkConfigController.java b/web-api/ruoyi-admin/src/main/java/com/ruoyi/ai/controller/AiDeptArkConfigController.java
index aef8ced..3e4b87c 100644
--- a/web-api/ruoyi-admin/src/main/java/com/ruoyi/ai/controller/AiDeptArkConfigController.java
+++ b/web-api/ruoyi-admin/src/main/java/com/ruoyi/ai/controller/AiDeptArkConfigController.java
@@ -47,20 +47,20 @@ public class AiDeptArkConfigController extends BaseController
}
/**
- * 导出团队(部门)对应火山引擎配置列表
+ * 导出团队对应火山引擎配置列表
*/
@PreAuthorize("@ss.hasPermi('ai:config:export')")
- @Log(title = "团队(部门)对应火山引擎配置", businessType = BusinessType.EXPORT)
+ @Log(title = "团队对应火山引擎配置", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, AiDeptArkConfig aiDeptArkConfig)
{
List list = aiDeptArkConfigService.selectAiDeptArkConfigList(aiDeptArkConfig);
ExcelUtil util = new ExcelUtil(AiDeptArkConfig.class);
- util.exportExcel(response, list, "团队(部门)对应火山引擎配置数据");
+ util.exportExcel(response, list, "团队对应火山引擎配置数据");
}
/**
- * 获取团队(部门)对应火山引擎配置详细信息
+ * 获取团队对应火山引擎配置详细信息
*/
@PreAuthorize("@ss.hasPermi('ai:config:query')")
@GetMapping(value = "/{id}")
@@ -73,7 +73,7 @@ public class AiDeptArkConfigController extends BaseController
* 新增团队(部门)对应火山引擎配置
*/
@PreAuthorize("@ss.hasPermi('ai:config:add')")
- @Log(title = "团队(部门)对应火山引擎配置", businessType = BusinessType.INSERT)
+ @Log(title = "团队对应火山引擎配置", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody AiDeptArkConfig aiDeptArkConfig)
{
@@ -84,7 +84,7 @@ public class AiDeptArkConfigController extends BaseController
* 修改团队(部门)对应火山引擎配置
*/
@PreAuthorize("@ss.hasPermi('ai:config:edit')")
- @Log(title = "团队(部门)对应火山引擎配置", businessType = BusinessType.UPDATE)
+ @Log(title = "团队对应火山引擎配置", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody AiDeptArkConfig aiDeptArkConfig)
{
@@ -95,7 +95,7 @@ public class AiDeptArkConfigController extends BaseController
* 删除团队(部门)对应火山引擎配置
*/
@PreAuthorize("@ss.hasPermi('ai:config:remove')")
- @Log(title = "团队(部门)对应火山引擎配置", businessType = BusinessType.DELETE)
+ @Log(title = "团队对应火山引擎配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
diff --git a/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiBalanceChangeRecordController.java b/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiBalanceChangeRecordController.java
index 95ca326..863fd62 100644
--- a/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiBalanceChangeRecordController.java
+++ b/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiBalanceChangeRecordController.java
@@ -1,6 +1,7 @@
package com.ruoyi.web.controller.ai;
import com.ruoyi.ai.domain.AiBalanceChangeRecord;
+import com.ruoyi.ai.domain.vo.AiBalanceChangeRecordListVo;
import com.ruoyi.ai.service.IAiBalanceChangeRecordService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
@@ -14,6 +15,7 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
+import java.util.stream.Collectors;
/**
* 余额使用记录Controller
@@ -37,7 +39,10 @@ public class AiBalanceChangeRecordController extends BaseController
{
startPage();
List list = aiBalanceChangeRecordService.selectAiBalanceChangeRecordList(aiBalanceChangeRecord);
- return getDataTable(list);
+ List rows = list.stream().map(AiBalanceChangeRecordListVo::from).collect(Collectors.toList());
+ TableDataInfo rsp = getDataTable(list);
+ rsp.setRows(rows);
+ return rsp;
}
/**
@@ -49,8 +54,9 @@ public class AiBalanceChangeRecordController extends BaseController
public void export(HttpServletResponse response, AiBalanceChangeRecord aiBalanceChangeRecord)
{
List list = aiBalanceChangeRecordService.selectAiBalanceChangeRecordList(aiBalanceChangeRecord);
- ExcelUtil util = new ExcelUtil(AiBalanceChangeRecord.class);
- util.exportExcel(response, list, "余额使用记录数据");
+ List rows = list.stream().map(AiBalanceChangeRecordListVo::from).collect(Collectors.toList());
+ ExcelUtil util = new ExcelUtil(AiBalanceChangeRecordListVo.class);
+ util.exportExcel(response, rows, "余额使用记录数据");
}
/**
diff --git a/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiDeptController.java b/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiDeptController.java
index 8593912..d73b859 100644
--- a/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiDeptController.java
+++ b/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiDeptController.java
@@ -98,21 +98,21 @@ public class AiDeptController extends BaseController
}
@PreAuthorize("@ss.hasPermi('ai:dept:remove')")
- @Log(title = "AI部门管理", businessType = BusinessType.DELETE)
+ @Log(title = "AI团队管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{deptId}")
public AjaxResult remove(@PathVariable Long deptId)
{
if (deptService.hasChildByDeptId(deptId))
{
- return warn("存在下级部门,不允许删除");
+ return warn("存在下级团队,不允许删除");
}
if (deptService.checkDeptExistUser(deptId))
{
- return warn("部门存在系统用户,不允许删除");
+ return warn("团队存在系统用户,不允许删除");
}
if (aiUserService.countAiUserByDeptId(deptId) > 0)
{
- return warn("部门存在 AI 用户,不允许删除");
+ return warn("团队存在 AI 用户,不允许删除");
}
deptService.checkDeptDataScope(deptId);
return toAjax(deptService.deleteDeptById(deptId));
diff --git a/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiUserController.java b/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiUserController.java
index 48c5b3c..f75bff4 100644
--- a/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiUserController.java
+++ b/web-api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/ai/AiUserController.java
@@ -167,9 +167,9 @@ public class AiUserController extends BaseController {
/**
* 用户余额回收至部门积分池
*/
- @ApiOperation("用户积分回收至部门")
+ @ApiOperation("用户积分回收至团队")
@PreAuthorize("@ss.hasPermi('ai:user:deptScoreReclaim')")
- @Log(title = "AI用户部门积分回收", businessType = BusinessType.UPDATE)
+ @Log(title = "AI用户团队积分回收", businessType = BusinessType.UPDATE)
@PutMapping("/dept-score/reclaim")
public AjaxResult reclaimDeptScore(@Valid @RequestBody AiUserDeptScoreRequest request) {
deptUserScoreTransferService.reclaimDeptScore(request);
diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiBalanceChangeRecord.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiBalanceChangeRecord.java
index fd1fda6..a6ee865 100644
--- a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiBalanceChangeRecord.java
+++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/AiBalanceChangeRecord.java
@@ -1,15 +1,14 @@
package com.ruoyi.ai.domain;
+import java.math.BigDecimal;
+
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
-import java.math.BigDecimal;
-
/**
* 余额使用记录对象 ai_balance_change_record
*
@@ -36,7 +35,6 @@ public class AiBalanceChangeRecord extends BaseEntity {
/**
* 关联订单号
*/
- @Excel(name = "关联订单号")
private String orderNo;
/**
@@ -45,34 +43,30 @@ public class AiBalanceChangeRecord extends BaseEntity {
private Long userId;
/**
- * 用户ID
+ * 用户对外标识(查询结果来自关联 ai_user.user_id)
*/
@TableField(exist = false)
private String uuid;
/**
- * 操作类型:0-充值 1-返佣 2-充值赠送 3-体验金赠送 4-体验金回收 5-图生图 6-一键换脸 7-快捷生图 8-快捷生视频 9-退款 10-系统操作 12-部门下放积分 13-回收至部门
+ * 操作类型
*/
- @Excel(name = "操作类型")
private Integer type;
/**
* 变更积分
*/
- @Excel(name = "变更积分")
private BigDecimal changeAmount;
/**
- * 变更后金额
+ * 变更后积分
*/
- @Excel(name = "变更后积分")
private BigDecimal resultAmount;
/**
- * 用户昵称
+ * 用户昵称(关联查询)
*/
@TableField(exist = false)
- @Excel(name = "用户昵称")
private String nickname;
}
diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/vo/AiBalanceChangeRecordListVo.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/vo/AiBalanceChangeRecordListVo.java
new file mode 100644
index 0000000..3faed9e
--- /dev/null
+++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/domain/vo/AiBalanceChangeRecordListVo.java
@@ -0,0 +1,65 @@
+package com.ruoyi.ai.domain.vo;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.ai.domain.AiBalanceChangeRecord;
+import com.ruoyi.ai.handler.BalanceChangeAmountExcelHandler;
+import com.ruoyi.common.annotation.Excel;
+import lombok.Data;
+
+/**
+ * 余额使用记录列表 / 导出展示(与 ORM 实体分离,避免在实体上堆展示字段与 Excel 注解)。
+ */
+@Data
+public class AiBalanceChangeRecordListVo implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Excel(name = "主键ID", sort = 1)
+ private Long id;
+
+ @Excel(name = "用户ID", sort = 2)
+ private String uuid;
+
+ @Excel(name = "用户昵称", sort = 3)
+ private String nickname;
+
+ @Excel(name = "关联订单号", sort = 4)
+ private String orderNo;
+
+ @Excel(name = "操作类型", sort = 5, readConverterExp = "0=充值,1=返佣,2=充值赠送,3=体验金赠送,4=体验金回收,5=一键换衣,6=图生图2,7=一键换脸,8=快捷生图,9=快捷生视频,10=退款,11=系统操作,12=团队下发,13=团队收回")
+ private Integer type;
+
+ @Excel(name = "变更积分", sort = 6, handler = BalanceChangeAmountExcelHandler.class)
+ private BigDecimal changeAmount;
+
+ @Excel(name = "变更后积分", sort = 7)
+ private BigDecimal resultAmount;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Excel(name = "操作时间", sort = 8, width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+ private Date createTime;
+
+ @Excel(name = "备注", sort = 9)
+ private String remark;
+
+ public static AiBalanceChangeRecordListVo from(AiBalanceChangeRecord e) {
+ if (e == null) {
+ return null;
+ }
+ AiBalanceChangeRecordListVo v = new AiBalanceChangeRecordListVo();
+ v.setId(e.getId());
+ v.setUuid(e.getUuid());
+ v.setNickname(e.getNickname());
+ v.setOrderNo(e.getOrderNo());
+ v.setType(e.getType());
+ v.setChangeAmount(e.getChangeAmount());
+ v.setResultAmount(e.getResultAmount());
+ v.setCreateTime(e.getCreateTime());
+ v.setRemark(e.getRemark());
+ return v;
+ }
+}
diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/handler/BalanceChangeAmountExcelHandler.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/handler/BalanceChangeAmountExcelHandler.java
new file mode 100644
index 0000000..3127b54
--- /dev/null
+++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/ai/handler/BalanceChangeAmountExcelHandler.java
@@ -0,0 +1,42 @@
+package com.ruoyi.ai.handler;
+
+import java.math.BigDecimal;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
+
+/**
+ * 导出「变更积分」列:正数前加「+」,与前端列表展示一致。
+ */
+public class BalanceChangeAmountExcelHandler implements ExcelHandlerAdapter
+{
+ @Override
+ public Object format(Object value, String[] args, Cell cell, Workbook wb)
+ {
+ if (value == null)
+ {
+ return "";
+ }
+ BigDecimal amount;
+ if (value instanceof BigDecimal)
+ {
+ amount = (BigDecimal) value;
+ }
+ else if (value instanceof Number)
+ {
+ amount = BigDecimal.valueOf(((Number) value).doubleValue());
+ }
+ else
+ {
+ return value.toString();
+ }
+ String plain = amount.stripTrailingZeros().toPlainString();
+ if (amount.compareTo(BigDecimal.ZERO) > 0)
+ {
+ return "+" + plain;
+ }
+ return plain;
+ }
+}
diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/system/domain/subteam/SubteamOverviewVO.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/system/domain/subteam/SubteamOverviewVO.java
index 69a2c0b..e4dab3f 100644
--- a/web-api/ruoyi-system/src/main/java/com/ruoyi/system/domain/subteam/SubteamOverviewVO.java
+++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/system/domain/subteam/SubteamOverviewVO.java
@@ -22,6 +22,9 @@ public class SubteamOverviewVO implements Serializable {
/** AI 用户数量(ai_user,实时) */
private Integer aiUserCount;
+ /** AI 账号上限,与部门 max_user_count 一致;null 或小于等于 0 表示不限制 */
+ private Integer aiUserMaxCount;
+
/** 近七日消耗积分(ai_video_report_data,可能来自缓存) */
private BigDecimal last7DaysConsumeScore;
diff --git a/web-api/ruoyi-system/src/main/java/com/ruoyi/system/service/subteam/impl/SubteamOverviewServiceImpl.java b/web-api/ruoyi-system/src/main/java/com/ruoyi/system/service/subteam/impl/SubteamOverviewServiceImpl.java
index c574541..4571a96 100644
--- a/web-api/ruoyi-system/src/main/java/com/ruoyi/system/service/subteam/impl/SubteamOverviewServiceImpl.java
+++ b/web-api/ruoyi-system/src/main/java/com/ruoyi/system/service/subteam/impl/SubteamOverviewServiceImpl.java
@@ -49,6 +49,7 @@ public class SubteamOverviewServiceImpl implements ISubteamOverviewService {
vo.setDeptName(dept != null ? dept.getDeptName() : "");
vo.setBalance(dept != null && dept.getBalance() != null ? dept.getBalance() : BigDecimal.ZERO);
vo.setAiUserCount(aiUserService.countAiUserByDeptId(deptId));
+ vo.setAiUserMaxCount(dept != null ? dept.getMaxUserCount() : null);
LocalDate end = LocalDate.now();
LocalDate start = end.minusDays(6);
diff --git a/web-api/ruoyi-system/src/main/resources/mapper/system/AiBalanceChangeRecordMapper.xml b/web-api/ruoyi-system/src/main/resources/mapper/system/AiBalanceChangeRecordMapper.xml
index a416b5f..0107d6c 100644
--- a/web-api/ruoyi-system/src/main/resources/mapper/system/AiBalanceChangeRecordMapper.xml
+++ b/web-api/ruoyi-system/src/main/resources/mapper/system/AiBalanceChangeRecordMapper.xml
@@ -12,6 +12,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+
@@ -21,7 +22,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- select r.id, r.del_flag, r.create_by, r.create_time, r.update_by, r.update_time, r.remark, r.user_id, r.type, r.change_amount, r.result_amount, u.nickname, u.user_id uuid from ai_balance_change_record r
+ select r.id, r.del_flag, r.create_by, r.create_time, r.update_by, r.update_time, r.remark, r.order_no, r.user_id, r.type, r.change_amount, r.result_amount, u.nickname, u.user_id uuid from ai_balance_change_record r
left join ai_user u on u.id = r.user_id