会员积分改版V7

This commit is contained in:
2026-08-11 13:23:22 +08:00
parent 809ff47120
commit a49ed802f4
14 changed files with 137 additions and 29 deletions
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -28,7 +28,7 @@
}
})();
</script>
<script type="module" crossorigin src="/assets/index-C0AXQCDm.js"></script>
<script type="module" crossorigin src="/assets/index-DWWJqJI6.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-D3fwIbOp.css">
</head>
<body>
@@ -70,6 +70,7 @@ const AdminCreditProducts: React.FC = () => {
renewalEnabled: nextRenewalEnabled,
price: item.price,
grantCredits: item.grantCredits,
validityMonths: item.validityMonths ?? 1,
sortOrder: item.sortOrder,
isActive: item.isActive,
});
@@ -85,6 +86,7 @@ const AdminCreditProducts: React.FC = () => {
billingCycle: 'monthly',
tierRank: 1,
renewalEnabled: nextRenewalEnabled,
validityMonths: 1,
});
};
@@ -124,6 +126,7 @@ const AdminCreditProducts: React.FC = () => {
Object.assign(payload, {
price: values.price,
grant_credits: values.grantCredits,
validity_months: values.validityMonths,
});
}
const savedProduct = editing
@@ -273,7 +276,7 @@ const AdminCreditProducts: React.FC = () => {
},
{ title: '积分', dataIndex: 'grantCredits', render: (value?: number) => Number(value || 0).toLocaleString() },
{ title: '价格', dataIndex: 'price', render: (value?: number | null) => formatMoney(value) },
{ title: '有效期', render: () => '1 个自然月' },
{ title: '有效期', dataIndex: 'validityMonths', render: (value?: number | null) => `${Number(value || 1)} 个月` },
{ title: '状态', dataIndex: 'isActive', render: (enabled: boolean) => <Tag color={enabled ? 'green' : 'default'}>{enabled ? '上架' : '下架'}</Tag> },
{
title: '操作',
@@ -377,7 +380,12 @@ const AdminCreditProducts: React.FC = () => {
<Form.Item name="price" label="价格" rules={[{ required: true }]}>
<InputNumber min={0} precision={2} />
</Form.Item>
<Form.Item label="有效期"><Input value="1 个自然月" disabled /></Form.Item>
<Form.Item name="validityMonths" label="有效期" rules={[{ required: true, message: '请选择有效期' }]}>
<Select
style={{ width: 140 }}
options={Array.from({ length: 36 }, (_, index) => ({ value: index + 1, label: `${index + 1} 个月` }))}
/>
</Form.Item>
</Space>}
<Form.Item name="description" label="说明"><Input.TextArea rows={2} /></Form.Item>
<Form.Item name="featuresText" label="权益说明(每行一项)"><Input.TextArea rows={4} /></Form.Item>
@@ -291,8 +291,7 @@ const AdminCreditRecords: React.FC = () => {
{ title: '模块步骤', maxWidth: 22, render: (r) => r.sourceStepCodeLabel || '-' },
{ title: '计费场景', maxWidth: 32, render: (r) => r.sceneNameSnapshot || r.billingSceneLabel || '-' },
{ title: '媒体类型', maxWidth: 12, align: 'center', render: (r) => r.mediaTypeLabel || '-' },
{ title: '业务积分', minWidth: 12, maxWidth: 14, align: 'right', numFmt: '#,##0.00', render: (r) => r.amount },
{ title: '有效余额变动', minWidth: 14, maxWidth: 16, align: 'right', numFmt: '#,##0.00', render: (r) => r.balanceDelta ?? r.amount },
{ title: '变动积分', minWidth: 12, maxWidth: 14, align: 'right', numFmt: '#,##0.00', render: (r) => r.amount },
{ title: '已过期积分', minWidth: 13, maxWidth: 15, align: 'right', numFmt: '#,##0.00', render: (r) => r.expiredAmount || 0 },
{ title: '变动后余额', minWidth: 12, maxWidth: 14, align: 'right', numFmt: '#,##0.00', render: (r) => r.balanceAfter },
{ title: 'LLM调用', minWidth: 12, maxWidth: 15, align: 'right', render: (r) => `${r.llmCallCount || 0}(成${r.llmSuccessCallCount || 0}/败${r.llmFailedCallCount || 0}` },
@@ -365,8 +364,7 @@ const AdminCreditRecords: React.FC = () => {
{ title: '模块', dataIndex: 'sourceModuleLabel', width: 130, render: (v: string) => v || '-' },
{ title: '步骤/场景', key: 'scene', width: 210, render: (_: any, r: AdminCreditRecord) => <div><div>{r.sceneNameSnapshot || r.billingSceneLabel || '-'}</div><div style={{ fontSize: 12, color: '#94a3b8' }}>{r.sourceStepCodeLabel || '-'}</div></div> },
{ title: '媒体', dataIndex: 'mediaTypeLabel', width: 80, render: (v: string) => v ? <Tag color="purple">{v}</Tag> : '-' },
{ title: '业务积分', dataIndex: 'amount', width: 120, sorter: (a: AdminCreditRecord, b: AdminCreditRecord) => a.amount - b.amount, render: (v: number) => <Typography.Text strong>{n(v)}</Typography.Text> },
{ title: '有效变动', dataIndex: 'balanceDelta', width: 120, render: (v: number | undefined, r: AdminCreditRecord) => { const value = v ?? r.amount; return <Typography.Text strong style={{ color: value > 0 ? '#10b981' : value < 0 ? '#ef4444' : '#64748b' }}>{value > 0 ? '+' : ''}{n(value)}</Typography.Text>; } },
{ title: '变动积分', dataIndex: 'amount', width: 120, sorter: (a: AdminCreditRecord, b: AdminCreditRecord) => a.amount - b.amount, render: (value: number) => <Typography.Text strong style={{ color: value > 0 ? '#10b981' : value < 0 ? '#ef4444' : '#64748b' }}>{value > 0 ? '+' : ''}{n(value)}</Typography.Text> },
{ title: '过期积分', dataIndex: 'expiredAmount', width: 110, render: (v: number) => v ? <Tag color="orange">{n(v)}</Tag> : '-' },
{ title: '余额', dataIndex: 'balanceAfter', width: 110, render: (v: number) => n(v) },
{ title: 'LLM调用', key: 'llmCalls', width: 130, render: (_: any, r: AdminCreditRecord) => <div>{n(r.llmCallCount || 0)} <div style={{ fontSize: 12, color: '#94a3b8' }}> {n(r.llmSuccessCallCount || 0)} / {n(r.llmFailedCallCount || 0)}</div></div> },