diff --git a/admin-v2/src/pages/Accounts.tsx b/admin-v2/src/pages/Accounts.tsx index 480ed96..9ce0081 100644 --- a/admin-v2/src/pages/Accounts.tsx +++ b/admin-v2/src/pages/Accounts.tsx @@ -9,6 +9,7 @@ import type { ProColumns } from '@ant-design/pro-components' import { ProTable } from '@ant-design/pro-components' import { accountService } from '@/services/accounts' import { industryService } from '@/services/industries' +import { billingService } from '@/services/billing' import { PageHeader } from '@/components/PageHeader' import type { AccountPublic } from '@/types' @@ -70,6 +71,12 @@ export default function Accounts() { } }, [accountIndustries, editingId, form]) + // 获取所有活跃计划(用于管理员切换) + const { data: plansData } = useQuery({ + queryKey: ['billing-plans'], + queryFn: ({ signal }) => billingService.listPlans(signal), + }) + const updateMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: Partial }) => accountService.update(id, data), @@ -101,6 +108,14 @@ export default function Accounts() { onError: (err: Error) => message.error(err.message || '行业授权更新失败'), }) + // 管理员切换用户计划 + const switchPlanMutation = useMutation({ + mutationFn: ({ accountId, planId }: { accountId: string; planId: string }) => + billingService.adminSwitchPlan(accountId, planId), + onSuccess: () => message.success('计划切换成功'), + onError: (err: Error) => message.error(err.message || '计划切换失败'), + }) + const columns: ProColumns[] = [ { title: '用户名', dataIndex: 'username', width: 120, tooltip: '搜索用户名、邮箱或显示名' }, { title: '显示名', dataIndex: 'display_name', width: 120, hideInSearch: true }, @@ -186,7 +201,7 @@ export default function Accounts() { try { // 更新基础信息 - const { industry_ids, ...accountData } = values + const { industry_ids, plan_id, ...accountData } = values await updateMutation.mutateAsync({ id: editingId, data: accountData }) // 更新行业授权(如果变更了) @@ -201,6 +216,11 @@ export default function Accounts() { queryClient.invalidateQueries({ queryKey: ['account-industries'] }) } + // 切换订阅计划(如果选择了新计划) + if (plan_id) { + await switchPlanMutation.mutateAsync({ accountId: editingId, planId: plan_id }) + } + handleClose() } catch { // Errors handled by mutation onError callbacks @@ -218,6 +238,11 @@ export default function Accounts() { label: `${item.icon} ${item.name}`, })) + const planOptions = (plansData || []).map((plan) => ({ + value: plan.id, + label: `${plan.display_name} (¥${(plan.price_cents / 100).toFixed(0)}/月)`, + })) + return (
@@ -256,7 +281,7 @@ export default function Accounts() { open={modalOpen} onOk={handleSave} onCancel={handleClose} - confirmLoading={updateMutation.isPending || setIndustriesMutation.isPending} + confirmLoading={updateMutation.isPending || setIndustriesMutation.isPending || switchPlanMutation.isPending} width={560} >
@@ -280,6 +305,21 @@ export default function Accounts() { ]} /> + 订阅计划 + + +