Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
99cbfa15
Commit
99cbfa15
authored
Jan 14, 2026
by
shaw
Browse files
fix(admin): 修复退款金额精度问题
- 显示完整余额精度,避免四舍五入导致的退款失败 - 添加"全部"按钮,一键填入完整余额 - 移除最小金额限制,支持任意正数金额
parent
3f8c8d70
Changes
3
Show whitespace changes
Inline
Side-by-side
frontend/src/components/admin/user/UserBalanceModal.vue
View file @
99cbfa15
...
@@ -3,14 +3,17 @@
...
@@ -3,14 +3,17 @@
<form
v-if=
"user"
id=
"balance-form"
@
submit.prevent=
"handleBalanceSubmit"
class=
"space-y-5"
>
<form
v-if=
"user"
id=
"balance-form"
@
submit.prevent=
"handleBalanceSubmit"
class=
"space-y-5"
>
<div
class=
"flex items-center gap-3 rounded-xl bg-gray-50 p-4 dark:bg-dark-700"
>
<div
class=
"flex items-center gap-3 rounded-xl bg-gray-50 p-4 dark:bg-dark-700"
>
<div
class=
"flex h-10 w-10 items-center justify-center rounded-full bg-primary-100"
><span
class=
"text-lg font-medium text-primary-700"
>
{{
user
.
email
.
charAt
(
0
).
toUpperCase
()
}}
</span></div>
<div
class=
"flex h-10 w-10 items-center justify-center rounded-full bg-primary-100"
><span
class=
"text-lg font-medium text-primary-700"
>
{{
user
.
email
.
charAt
(
0
).
toUpperCase
()
}}
</span></div>
<div
class=
"flex-1"
><p
class=
"font-medium text-gray-900"
>
{{
user
.
email
}}
</p><p
class=
"text-sm text-gray-500"
>
{{
t
(
'
admin.users.currentBalance
'
)
}}
: $
{{
user
.
balance
.
toFixed
(
2
)
}}
</p></div>
<div
class=
"flex-1"
><p
class=
"font-medium text-gray-900"
>
{{
user
.
email
}}
</p><p
class=
"text-sm text-gray-500"
>
{{
t
(
'
admin.users.currentBalance
'
)
}}
: $
{{
formatBalance
(
user
.
balance
)
}}
</p></div>
</div>
</div>
<div>
<div>
<label
class=
"input-label"
>
{{
operation
===
'
add
'
?
t
(
'
admin.users.depositAmount
'
)
:
t
(
'
admin.users.withdrawAmount
'
)
}}
</label>
<label
class=
"input-label"
>
{{
operation
===
'
add
'
?
t
(
'
admin.users.depositAmount
'
)
:
t
(
'
admin.users.withdrawAmount
'
)
}}
</label>
<div
class=
"relative"
><div
class=
"absolute left-3 top-1/2 -translate-y-1/2 font-medium text-gray-500"
>
$
</div><input
v-model.number=
"form.amount"
type=
"number"
step=
"0.01"
min=
"0.01"
required
class=
"input pl-8"
/></div>
<div
class=
"relative flex gap-2"
>
<div
class=
"relative flex-1"
><div
class=
"absolute left-3 top-1/2 -translate-y-1/2 font-medium text-gray-500"
>
$
</div><input
v-model.number=
"form.amount"
type=
"number"
step=
"any"
min=
"0"
required
class=
"input pl-8"
/></div>
<button
v-if=
"operation === 'subtract'"
type=
"button"
@
click=
"fillAllBalance"
class=
"btn btn-secondary whitespace-nowrap"
>
{{
t
(
'
admin.users.withdrawAll
'
)
}}
</button>
</div>
</div>
</div>
<div><label
class=
"input-label"
>
{{
t
(
'
admin.users.notes
'
)
}}
</label><textarea
v-model=
"form.notes"
rows=
"3"
class=
"input"
></textarea></div>
<div><label
class=
"input-label"
>
{{
t
(
'
admin.users.notes
'
)
}}
</label><textarea
v-model=
"form.notes"
rows=
"3"
class=
"input"
></textarea></div>
<div
v-if=
"form.amount > 0"
class=
"rounded-xl border border-blue-200 bg-blue-50 p-4"
><div
class=
"flex items-center justify-between text-sm"
><span>
{{
t
(
'
admin.users.newBalance
'
)
}}
:
</span><span
class=
"font-bold"
>
$
{{
calculateNewBalance
()
.
toFixed
(
2
)
}}
</span></div></div>
<div
v-if=
"form.amount > 0"
class=
"rounded-xl border border-blue-200 bg-blue-50 p-4"
><div
class=
"flex items-center justify-between text-sm"
><span>
{{
t
(
'
admin.users.newBalance
'
)
}}
:
</span><span
class=
"font-bold"
>
$
{{
formatBalance
(
calculateNewBalance
())
}}
</span></div></div>
</form>
</form>
<template
#footer
>
<template
#footer
>
<div
class=
"flex justify-end gap-3"
>
<div
class=
"flex justify-end gap-3"
>
...
@@ -35,11 +38,30 @@ const emit = defineEmits(['close', 'success']); const { t } = useI18n(); const a
...
@@ -35,11 +38,30 @@ const emit = defineEmits(['close', 'success']); const { t } = useI18n(); const a
const
submitting
=
ref
(
false
);
const
form
=
reactive
({
amount
:
0
,
notes
:
''
})
const
submitting
=
ref
(
false
);
const
form
=
reactive
({
amount
:
0
,
notes
:
''
})
watch
(()
=>
props
.
show
,
(
v
)
=>
{
if
(
v
)
{
form
.
amount
=
0
;
form
.
notes
=
''
}
})
watch
(()
=>
props
.
show
,
(
v
)
=>
{
if
(
v
)
{
form
.
amount
=
0
;
form
.
notes
=
''
}
})
// 格式化余额:显示完整精度,去除尾部多余的0
const
formatBalance
=
(
value
:
number
)
=>
{
if
(
value
===
0
)
return
'
0.00
'
// 最多保留8位小数,去除尾部的0
const
formatted
=
value
.
toFixed
(
8
).
replace
(
/
\.?
0+$/
,
''
)
// 确保至少有2位小数
const
parts
=
formatted
.
split
(
'
.
'
)
if
(
parts
.
length
===
1
)
return
formatted
+
'
.00
'
if
(
parts
[
1
].
length
===
1
)
return
formatted
+
'
0
'
return
formatted
}
// 填入全部余额
const
fillAllBalance
=
()
=>
{
if
(
props
.
user
)
{
form
.
amount
=
props
.
user
.
balance
}
}
const
calculateNewBalance
=
()
=>
{
const
calculateNewBalance
=
()
=>
{
if
(
!
props
.
user
)
return
0
if
(
!
props
.
user
)
return
0
const
result
=
props
.
operation
===
'
add
'
?
props
.
user
.
balance
+
form
.
amount
:
props
.
user
.
balance
-
form
.
amount
const
result
=
props
.
operation
===
'
add
'
?
props
.
user
.
balance
+
form
.
amount
:
props
.
user
.
balance
-
form
.
amount
// 避免浮点数精度问题导致的 -0.00 显示
// 避免浮点数精度问题导致的 -0.00 显示
return
result
===
0
||
Object
.
is
(
result
,
-
0
)
?
0
:
result
return
Math
.
abs
(
result
)
<
1
e
-
10
?
0
:
result
}
}
const
handleBalanceSubmit
=
async
()
=>
{
const
handleBalanceSubmit
=
async
()
=>
{
if
(
!
props
.
user
)
return
if
(
!
props
.
user
)
return
...
@@ -47,10 +69,8 @@ const handleBalanceSubmit = async () => {
...
@@ -47,10 +69,8 @@ const handleBalanceSubmit = async () => {
appStore
.
showError
(
t
(
'
admin.users.amountRequired
'
))
appStore
.
showError
(
t
(
'
admin.users.amountRequired
'
))
return
return
}
}
// 使用小数点后两位精度比较,避免浮点数精度问题
// 退款时验证金额不超过实际余额
const
amount
=
Math
.
round
(
form
.
amount
*
100
)
/
100
if
(
props
.
operation
===
'
subtract
'
&&
form
.
amount
>
props
.
user
.
balance
)
{
const
balance
=
Math
.
round
(
props
.
user
.
balance
*
100
)
/
100
if
(
props
.
operation
===
'
subtract
'
&&
amount
>
balance
)
{
appStore
.
showError
(
t
(
'
admin.users.insufficientBalance
'
))
appStore
.
showError
(
t
(
'
admin.users.insufficientBalance
'
))
return
return
}
}
...
...
frontend/src/i18n/locales/en.ts
View file @
99cbfa15
...
@@ -724,6 +724,7 @@ export default {
...
@@ -724,6 +724,7 @@ export default {
withdraw
:
'
Withdraw
'
,
withdraw
:
'
Withdraw
'
,
depositAmount
:
'
Deposit Amount
'
,
depositAmount
:
'
Deposit Amount
'
,
withdrawAmount
:
'
Withdraw Amount
'
,
withdrawAmount
:
'
Withdraw Amount
'
,
withdrawAll
:
'
All
'
,
currentBalance
:
'
Current Balance
'
,
currentBalance
:
'
Current Balance
'
,
depositNotesPlaceholder
:
depositNotesPlaceholder
:
'
e.g., New user registration bonus, promotional credit, compensation, etc.
'
,
'
e.g., New user registration bonus, promotional credit, compensation, etc.
'
,
...
...
frontend/src/i18n/locales/zh.ts
View file @
99cbfa15
...
@@ -780,6 +780,7 @@ export default {
...
@@ -780,6 +780,7 @@ export default {
withdraw
:
'
退款
'
,
withdraw
:
'
退款
'
,
depositAmount
:
'
充值金额
'
,
depositAmount
:
'
充值金额
'
,
withdrawAmount
:
'
退款金额
'
,
withdrawAmount
:
'
退款金额
'
,
withdrawAll
:
'
全部
'
,
depositNotesPlaceholder
:
'
例如:新用户注册奖励、活动充值、补偿充值等
'
,
depositNotesPlaceholder
:
'
例如:新用户注册奖励、活动充值、补偿充值等
'
,
withdrawNotesPlaceholder
:
'
例如:服务问题退款、错误充值退回、账户注销退款等
'
,
withdrawNotesPlaceholder
:
'
例如:服务问题退款、错误充值退回、账户注销退款等
'
,
notesOptional
:
'
备注为可选项,有助于未来查账
'
,
notesOptional
:
'
备注为可选项,有助于未来查账
'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment