feat: support charge for user

This commit is contained in:
Rogee
2025-05-15 10:15:05 +08:00
parent 3a23d4b4b3
commit 5d35e977fb
3 changed files with 43 additions and 10 deletions

View File

@@ -41,3 +41,16 @@ func (ctl *users) Show(ctx fiber.Ctx, id int64) (*model.Users, error) {
func (ctl *users) Articles(ctx fiber.Ctx, id int64, pagination *requests.Pagination) (*requests.Pager, error) { func (ctl *users) Articles(ctx fiber.Ctx, id int64, pagination *requests.Pagination) (*requests.Pager, error) {
return models.Posts.Bought(ctx.Context(), id, pagination) return models.Posts.Bought(ctx.Context(), id, pagination)
} }
type UserBalance struct {
Balance int64 `json:"balance"`
}
// Balance
//
// @Router /admin/users/:id/balance [post]
// @Bind id path
// @Bind balance body
func (ctl *users) Balance(ctx fiber.Ctx, id int64, balance *UserBalance) error {
return models.Users.AddBalance(ctx.Context(), id, balance.Balance)
}

View File

@@ -13,6 +13,11 @@ export const userService = {
searchUser(id) { searchUser(id) {
return httpClient.get(`/admin/users/${id}`); return httpClient.get(`/admin/users/${id}`);
}, },
userBalance(id, balance) {
return httpClient.post(`/admin/users/${id}/balance`, {
balance
});
},
getUser(id) { getUser(id) {
return httpClient.get(`/admin/users/${id}`); return httpClient.get(`/admin/users/${id}`);
}, },

View File

@@ -72,20 +72,29 @@ const onSearch = (event) => {
}, 300); }, 300);
}; };
const handleDelete = (user) => { const handleRecharge = (user) => {
confirm.require({ confirm.require({
message: `确定要删除用户 "${user.username}" 吗?`, message: `确定要为用户ID ${user.id} "${user.username}" 充值吗?`,
header: '确认删除', header: '确认充值',
icon: 'pi pi-exclamation-triangle', icon: 'pi pi-exclamation-triangle',
acceptClass: 'p-button-danger', acceptClass: 'p-button-success',
accept: async () => { accept: async () => {
try { try {
await userService.deleteUser(user.id);
toast.add({ severity: 'success', summary: '成功', detail: '用户已删除', life: 3000 }); const amount = prompt('请输入充值金额(元):');
if (!amount) return;
const amountInCents = Math.floor(parseFloat(amount) * 100);
if (isNaN(amountInCents) || amountInCents <= 0) {
toast.add({ severity: 'error', summary: '错误', detail: '请输入有效的金额', life: 3000 });
return;
}
await userService.userBalance(user.id, amountInCents);
toast.add({ severity: 'success', summary: '成功', detail: '用户已充值', life: 3000 });
fetchUsers(); fetchUsers();
} catch (error) { } catch (error) {
console.error('Failed to delete user:', error); console.error('Failed to recharge user:', error);
toast.add({ severity: 'error', summary: '错误', detail: '删除用户失败', life: 3000 }); toast.add({ severity: 'error', summary: '错误', detail: '充值用户失败', life: 3000 });
} }
} }
}); });
@@ -131,6 +140,12 @@ onMounted(() => {
<Column field="id" header="ID" sortable></Column> <Column field="id" header="ID" sortable></Column>
<Column field="balance" header="余额" sortable>
<template #body="{ data }">
¥{{ (data.balance / 100).toFixed(2) }}
</template>
</Column>
<Column field="username" header="用户名" sortable> <Column field="username" header="用户名" sortable>
<template #body="{ data }"> <template #body="{ data }">
<div class="flex items-center space-x-3"> <div class="flex items-center space-x-3">
@@ -170,8 +185,8 @@ onMounted(() => {
<Column header="操作" :exportable="false" style="min-width:8rem"> <Column header="操作" :exportable="false" style="min-width:8rem">
<template #body="{ data }"> <template #body="{ data }">
<div class="flex justify-center space-x-2"> <div class="flex justify-center space-x-2">
<Button icon="pi pi-trash" rounded text severity="danger" @click="handleDelete(data)" <Button icon="pi pi-refresh" rounded text severity="success" @click="handleRecharge(data)"
aria-label="删除" /> aria-label="充值" />
</div> </div>
</template> </template>
</Column> </Column>