feat(opc): 算力中心页加「我的用量」(余额+本月按模型 token/费用)
- Compute.tsx 新增用量卡片: 余额/已用(¥), 总token/费用, 按模型表(请求/token/费用, quota→¥) - authApi 增 getOpcComputeBalance/Usage; i18n zh 补充
This commit is contained in:
@@ -252,6 +252,9 @@ export const authApi = {
|
||||
getOpcComputeTokens: () => request<{ items: { id: number; name: string; key: string; created_time: number; remain_quota?: number }[] }>("/opc/compute/tokens"),
|
||||
createOpcComputeToken: () => request<{ id: number; name: string; key: string }>("/opc/compute/tokens", { method: "POST", body: "{}" }),
|
||||
deleteOpcComputeToken: (id: number) => request<Record<string, unknown>>(`/opc/compute/tokens/${id}`, { method: "DELETE" }),
|
||||
// ---- 计量:余额 / 本月用量(按模型) ----
|
||||
getOpcComputeBalance: () => request<{ id: number; quota: number; used_quota: number }>("/opc/compute/balance"),
|
||||
getOpcComputeUsage: () => request<{ month: string; cost_quota: number; input_tokens: number; output_tokens: number; items: { model_name: string; requests: number; input_tokens: number; output_tokens: number; cost_quota: number }[] }>("/opc/compute/usage"),
|
||||
|
||||
// ---- 各业务端口工作台 ----
|
||||
getEnterpriseDashboard: () => request<PortDashboardData>("/enterprise/dashboard"),
|
||||
|
||||
@@ -3751,6 +3751,13 @@
|
||||
"computeInput": "输入(¥/百万)",
|
||||
"computeOutput": "输出(¥/百万)",
|
||||
"computeUnit": "计价",
|
||||
"computeUsage": "我的用量(本月)",
|
||||
"computeBalance": "当前余额",
|
||||
"computeUsed": "已用",
|
||||
"computeTokensTotal": "总token: {{total}}",
|
||||
"computeRequests": "请求",
|
||||
"computeCost": "费用",
|
||||
"computeNoUsage": "本月暂无用量,使用模型后显示",
|
||||
"profile": "个人资料",
|
||||
"username": "用户名",
|
||||
"nickname": "昵称",
|
||||
|
||||
@@ -16,6 +16,8 @@ export default function OpcCompute() {
|
||||
const [models, setModels] = useState<Model[]>([]);
|
||||
const [prices, setPrices] = useState<Price[]>([]);
|
||||
const [tokens, setTokens] = useState<Token[]>([]);
|
||||
const [balance, setBalance] = useState<{ quota: number; used_quota: number } | null>(null);
|
||||
const [usage, setUsage] = useState<{ month: string; cost_quota: number; input_tokens: number; output_tokens: number; items: any[] } | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const load = useCallback(() => {
|
||||
@@ -23,6 +25,8 @@ export default function OpcCompute() {
|
||||
authApi.getOpcComputeModels().then((r) => setModels(r.items ?? [])).catch(() => {});
|
||||
authApi.getOpcComputePrices().then((r) => setPrices(r.items ?? [])).catch(() => {});
|
||||
authApi.getOpcComputeTokens().then((r) => setTokens(r.items ?? [])).catch(() => {});
|
||||
authApi.getOpcComputeBalance().then(setBalance).catch(() => {});
|
||||
authApi.getOpcComputeUsage().then(setUsage).catch(() => {});
|
||||
}, []);
|
||||
|
||||
useEffect(() => { load(); }, [load]);
|
||||
@@ -82,6 +86,26 @@ export default function OpcCompute() {
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card title={t("role.opc.computeUsage")} style={{ marginTop: 12 }} size="small">
|
||||
<Space size={24} wrap>
|
||||
<div><Typography.Text type="secondary">{t("role.opc.computeBalance")}</Typography.Text>
|
||||
<div className={styles.itemTitle}>¥{((balance?.quota ?? 0) / 1000000).toFixed(4)}</div></div>
|
||||
<div><Typography.Text type="secondary">{t("role.opc.computeUsed")}</Typography.Text>
|
||||
<div className={styles.itemTitle}>¥{((balance?.used_quota ?? 0) / 1000000).toFixed(4)}</div></div>
|
||||
<div><Typography.Text type="secondary">{t("role.opc.computeTokensTotal", { total: usage?.input_tokens ?? 0 })}</Typography.Text>
|
||||
<div className={styles.itemTitle}>{usage?.cost_quota != null ? `¥${(usage.cost_quota / 1000000).toFixed(4)}` : "-"}</div></div>
|
||||
</Space>
|
||||
{usage?.items?.length ? (
|
||||
<Table size="small" rowKey="model_name" pagination={false} style={{ marginTop: 8 }} columns={[
|
||||
{ title: t("role.opc.computeModel"), dataIndex: "model_name" },
|
||||
{ title: t("role.opc.computeRequests"), dataIndex: "requests" },
|
||||
{ title: t("role.opc.computeInput"), dataIndex: "input_tokens" },
|
||||
{ title: t("role.opc.computeOutput"), dataIndex: "output_tokens" },
|
||||
{ title: t("role.opc.computeCost"), dataIndex: "cost_quota", render: (v: number) => `¥${(v / 1000000).toFixed(4)}` },
|
||||
]} dataSource={usage.items} />
|
||||
) : <Typography.Paragraph type="secondary" style={{ marginTop: 8 }}>{t("role.opc.computeNoUsage")}</Typography.Paragraph>}
|
||||
</Card>
|
||||
|
||||
<Row gutter={[12, 12]} style={{ marginTop: 12 }}>
|
||||
<Col span={12}>
|
||||
<Card title={t("role.opc.computeModels")} size="small">
|
||||
|
||||
Reference in New Issue
Block a user