From c92f531f1bcf2528aaf359c969ad69a1abdc01b2 Mon Sep 17 00:00:00 2001
From: yys <47@gamerwa.com>
Date: Fri, 17 Apr 2026 17:47:25 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E9=83=A8=E9=97=A8=E4=BD=99=E9=A2=9D?=
=?UTF-8?q?=E5=8F=98=E6=9B=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
admin-ui/src/api/ai/dept.js | 8 +
admin-ui/src/api/system/dept.js | 9 +
admin-ui/src/utils/westernNumberFormat.js | 76 ++++++++
admin-ui/src/views/system/dept/index.vue | 184 +++++++++++++++++-
.../web/controller/ai/AiDeptController.java | 4 +-
.../controller/system/SysDeptController.java | 19 ++
.../system/DeptChargeRefundRequest.java | 47 +++++
.../ai/service/IDeptChargeRefundService.java | 16 ++
.../impl/DeptChargeRefundServiceImpl.java | 122 ++++++++++++
.../ruoyi/system/mapper/SysDeptMapper.java | 18 ++
.../ruoyi/system/service/ISysDeptService.java | 15 ++
.../service/impl/SysDeptServiceImpl.java | 15 ++
.../resources/mapper/system/SysDeptMapper.xml | 16 ++
13 files changed, 544 insertions(+), 5 deletions(-)
create mode 100644 admin-ui/src/utils/westernNumberFormat.js
create mode 100644 web-api/ruoyi-common/src/main/java/com/ruoyi/common/core/request/system/DeptChargeRefundRequest.java
create mode 100644 web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/IDeptChargeRefundService.java
create mode 100644 web-api/ruoyi-system/src/main/java/com/ruoyi/ai/service/impl/DeptChargeRefundServiceImpl.java
diff --git a/admin-ui/src/api/ai/dept.js b/admin-ui/src/api/ai/dept.js
index 415856b..c8a3b98 100644
--- a/admin-ui/src/api/ai/dept.js
+++ b/admin-ui/src/api/ai/dept.js
@@ -44,3 +44,11 @@ export function delDept(deptId) {
method: 'delete'
})
}
+
+export function chargeRefundDept(data) {
+ return request({
+ url: '/ai/dept/charge-refund',
+ method: 'post',
+ data: data
+ })
+}
diff --git a/admin-ui/src/api/system/dept.js b/admin-ui/src/api/system/dept.js
index fc943cd..1bed996 100644
--- a/admin-ui/src/api/system/dept.js
+++ b/admin-ui/src/api/system/dept.js
@@ -49,4 +49,13 @@ export function delDept(deptId) {
url: '/system/dept/' + deptId,
method: 'delete'
})
+}
+
+// 部门充值/退款
+export function chargeRefundDept(data) {
+ return request({
+ url: '/system/dept/charge-refund',
+ method: 'post',
+ data: data
+ })
}
\ No newline at end of file
diff --git a/admin-ui/src/utils/westernNumberFormat.js b/admin-ui/src/utils/westernNumberFormat.js
new file mode 100644
index 0000000..fd216df
--- /dev/null
+++ b/admin-ui/src/utils/westernNumberFormat.js
@@ -0,0 +1,76 @@
+/**
+ * 西式千分位(en-US):金额最多两位小数,积分为整数。
+ * 用于输入/粘贴后即时格式化展示。
+ */
+
+export const WESTERN_MONEY_MAX = 10000000
+export const WESTERN_INT_MAX = 100000000
+
+const MONEY_MAX = WESTERN_MONEY_MAX
+const INT_MAX = WESTERN_INT_MAX
+
+/** 只保留数字与至多一个小数点,小数位最多 2 位 */
+export function sanitizeMoneyDigits(raw) {
+ let s = String(raw == null ? '' : raw).replace(/,/g, '').replace(/[^\d.]/g, '')
+ const firstDot = s.indexOf('.')
+ if (firstDot !== -1) {
+ s = s.slice(0, firstDot + 1) + s.slice(firstDot + 1).replace(/\./g, '').slice(0, 2)
+ }
+ return s
+}
+
+/** 将规范化后的金额字符串格式化为 9,999,999.99 形式(输入过程中允许末尾为小数点) */
+export function formatMoneyWesternDisplay(sanitized) {
+ if (!sanitized) return ''
+ const s = sanitized
+ const dot = s.indexOf('.')
+ const intRaw = dot === -1 ? s : s.slice(0, dot)
+ const decRaw = dot === -1 ? '' : s.slice(dot + 1).slice(0, 2)
+ const intNum = intRaw === '' ? 0 : parseInt(intRaw, 10)
+ const intFmt = (isNaN(intNum) ? 0 : intNum).toLocaleString('en-US')
+ if (dot === -1) return intFmt
+ if (s.endsWith('.') && decRaw === '') return intFmt + '.'
+ return intFmt + '.' + decRaw
+}
+
+/** 规范化字符串 -> 金额数值(undefined 表示空) */
+export function moneyStringToNumber(sanitized) {
+ if (sanitized === '' || sanitized === '.' || sanitized == null) return undefined
+ const n = parseFloat(sanitized)
+ if (isNaN(n)) return undefined
+ const rounded = Math.round(n * 100) / 100
+ if (rounded > MONEY_MAX) return MONEY_MAX
+ if (rounded < 0) return 0
+ return rounded
+}
+
+/** 失焦时金额固定两位小数展示 */
+export function formatMoneyWesternFinal(n) {
+ if (n === undefined || n === null || isNaN(n)) return ''
+ const v = Math.min(MONEY_MAX, Math.max(0, Math.round(Number(n) * 100) / 100))
+ return v.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
+}
+
+/** 积分:仅数字,并限制范围 */
+export function sanitizeIntDigits(raw) {
+ let d = String(raw == null ? '' : raw).replace(/,/g, '').replace(/\D/g, '')
+ if (d === '') return ''
+ let n = parseInt(d, 10)
+ if (isNaN(n)) return ''
+ n = Math.min(INT_MAX, Math.max(0, n))
+ return String(n)
+}
+
+export function formatIntWesternDisplay(digits) {
+ if (!digits) return ''
+ const n = parseInt(digits, 10)
+ if (isNaN(n)) return ''
+ return n.toLocaleString('en-US')
+}
+
+export function intStringToNumber(digits) {
+ if (!digits) return undefined
+ const n = parseInt(digits, 10)
+ if (isNaN(n)) return undefined
+ return n
+}
diff --git a/admin-ui/src/views/system/dept/index.vue b/admin-ui/src/views/system/dept/index.vue
index b28b1c5..383c677 100644
--- a/admin-ui/src/views/system/dept/index.vue
+++ b/admin-ui/src/views/system/dept/index.vue
@@ -57,19 +57,31 @@
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
>
-
+
+
+
+ {{ scope.row.balance != null ? scope.row.balance : '—' }}
+
+
-
+
{{ parseTime(scope.row.createTime) }}
+ 充值/退款
取 消
+
+
+
+
+
+ 充值
+ 退款
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -244,7 +304,17 @@