From d3cf460b6eb87d50a09367d087b27815e2002026 Mon Sep 17 00:00:00 2001 From: argszero Date: Mon, 17 Aug 2026 13:56:52 +0800 Subject: [PATCH] feat(ui): replace dashboard point sources with month point changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dashboard's "点数来源 Point sources" card showed a static point composition, which users don't find intuitive. Replace it (dashboard and wallet) with a "本月点数变化 Month point changes" card that aggregates the last month's point movements by type (gift/expire/earn/consume/ topup/withdraw) with a net change summary. Signs are colored (positive accent, negative red). Data now comes from D.TRANSACTIONS aggregation instead of the static D.POINT_SOURCES array (removed). No mechanism wording (validity, priority) is shown. Refs: rant 2026-08-17T10:45:27 (仪表盘"点数来源"改为"近 1 月点数变化明细") --- ui/README.md | 4 ++-- ui/css/style.css | 3 +++ ui/index.html | 8 ++++---- ui/js/app.js | 42 +++++++++++++++++++++++++++++------------- ui/js/data.js | 7 ------- 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/ui/README.md b/ui/README.md index d0274d2..e589a74 100644 --- a/ui/README.md +++ b/ui/README.md @@ -37,10 +37,10 @@ python3 -m http.server 8000 --directory ui 同一套界面(角色视图): -1. 仪表盘 Dashboard — 点数余额、本月用量、共享收益、点数来源(点数构成分组) +1. 仪表盘 Dashboard — 点数余额、本月用量、共享收益、**本月点数变化(近 1 月按类型汇总收支:赠送/过期/收益/消费/充值/提现 + 净变化,取代静态"点数来源"分组)** 2. 模型市场 Marketplace — 模型浏览、搜索、厂商筛选、排序(按价格/上下文);可用性标注「多 key · 自动故障转移」(该模型配置多个上游 key,架构 v0.2 路由策略);每行「使用 / 消费」入口 → 聊天 Mock 模拟调用(按模型输出参考价扣小数点数,如 -0.38 点,产生消费交易;余额不足时阻断并提示) 3. 共享管理 Sharing — 默认只显示统计 + 我的共享列表(key 脱敏展示,可暂停/恢复/重新上架/彻底删除);点击"+ 添加 / 上架新 key"展开上架表单(须填 API Key,平台加密托管;分享者只填声明额度,单价由平台按模型定价自动计算并展示参考价),提交成功或取消后自动收起 -4. 钱包 Wallet — 点数余额、点数来源(点数构成分组)、**充值入口(US-4:模拟流程——输入点数 → 余额增加 → topup 交易记录;文案注明"演示,真实支付后续接入";提现仍 disabled)**、**申请加额(US-20:企业成员余额低时申请更多点数 → 提交后等待管理员审批,与组织设置开关联动)**;收支明细已去重,统一到【交易记录】(页内提供跳转提示) +4. 钱包 Wallet — 点数余额、**本月点数变化(近 1 月按类型汇总收支 + 净变化,与仪表盘一致)**、**充值入口(US-4:模拟流程——输入点数 → 余额增加 → topup 交易记录;文案注明"演示,真实支付后续接入";提现仍 disabled)**、**申请加额(US-20:企业成员余额低时申请更多点数 → 提交后等待管理员审批,与组织设置开关联动)**;收支明细已去重,统一到【交易记录】(页内提供跳转提示) 5. 交易记录 Transactions — 消费/收益/充值/提现/赠送(gift)唯一明细入口,Tab 筛选 + MRT 风格表格(列排序/列筛选/分页,与 Tab 叠加生效) 6. 设置 Settings — 账户、API Key 管理(完整增删改查:生成带名字、改名、删除需确认「删除后该 key 立即失效」、按名字搜索、一键复制完整 key——列表脱敏展示 atk_live_****xxxx,复制为完整值;file:// 下 clipboard API 受限时降级为选中+Ctrl/Cmd+C)、通知、偏好 7. 管理视图 Admin(管理员 / 运营者角色专属)— Key 池管理(添加/撤销)、成员管理(改部门:下拉可选部门或"未分配";任意金额充值,正整数校验;新注册成员默认未分配部门;**加额申请审批(US-20:待审批列表 → 批准=成员余额+申请点数 / 驳回)**)、用量报表(按模型/成员)、组织管理(部门列表 + 部门增删改查 + 每月点数分配,含部门汇总统计,未分配成员不计入任何部门;保留组织设置卡片,含"关闭外部注册"企业部署开关与"成员自助申请加额需管理员审批"开关——关掉后成员申请直接生效)、平台运营(运营者 = 宿主本人,职责最小化:① 运行概览——运行状态 / 用户数 / 共享 key 数 / 交易量 / 点数流入流出;② 用户充值——按用户名 / 邮箱搜索定位,输入点数金额(可为小数)确认后余额增加永久有效点数并产生一条交易记录) diff --git a/ui/css/style.css b/ui/css/style.css index ad51322..ed99c08 100644 --- a/ui/css/style.css +++ b/ui/css/style.css @@ -259,6 +259,9 @@ select.input option { background: var(--bg-card); } .mini-item .d { color: var(--text-mute); font-size: 12px; } .mini-item .r { text-align: right; } .mini-item .r .pts { color: var(--accent-text); font-weight: 700; } +.mini-item .r .pts.neg { color: var(--danger); } +.mini-item.net { background: var(--accent-soft); border-color: var(--accent); } +.mini-item.net .t { color: var(--accent-text); } .bar-list { display: flex; flex-direction: column; gap: 12px; } .bar-row .bar-label { display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 4px; } diff --git a/ui/index.html b/ui/index.html index d383bfa..4e14d7d 100644 --- a/ui/index.html +++ b/ui/index.html @@ -75,8 +75,8 @@

我的共享 My sharings

-

点数来源 Point sources

-
+

本月点数变化 Month point changes

+
@@ -185,8 +185,8 @@

点数余额 Points balance

-

点数来源 Point sources

-
+

本月点数变化 Month point changes

+

收支明细已统一到 diff --git a/ui/js/app.js b/ui/js/app.js index a5be5c0..e41ba57 100644 --- a/ui/js/app.js +++ b/ui/js/app.js @@ -163,7 +163,7 @@ '

已用 ' + D.fmt(s.used) + " / " + D.fmt(s.quota) + " 点 · 单价 " + D.fmt(s.price) + " 点/1M
" + '
+' + D.fmt(s.earned) + "
累计收益
" ).join("") + (on.length ? "" : '

还没有上架的 key

'); - renderPointSources(); + renderMonthChanges(); } function stat(label, value, sub, cls) { @@ -266,18 +266,36 @@ if (activeView === "dashboard") renderDashboard(); } - /* --- 点数来源(G2:钱包 / 仪表盘统一展示点数构成) --- */ + /* --- 本月点数变化(rant 10:45:27:近 1 月按类型汇总收支,取代静态"点数来源"分组) --- */ - function pointSourceItem(s) { - return '
' + esc(s.label) + "
" + - '
' + (s.pts > 0 ? "+" : "") + D.fmt(s.pts) + "
"; + const MONTH_TYPE_LABELS = [ + ["gift", "赠送"], + ["expire", "过期"], + ["earn", "收益"], + ["consume", "消费"], + ["topup", "充值"], + ["withdraw", "提现"], + ]; + + function monthChangeItem(label, pts, isNet) { + const sign = pts > 0 ? "+" : ""; + const neg = pts < 0 ? " neg" : ""; + return '
' + esc(label) + "
" + + '
' + sign + D.fmt(pts) + "
"; } - function renderPointSources() { - const html = D.POINT_SOURCES.map(pointSourceItem).join(""); - const walletEl = $("#points-sources"); + function renderMonthChanges() { + const sums = {}; + D.TRANSACTIONS.forEach((t) => { sums[t.type] = (sums[t.type] || 0) + t.pts; }); + const net = D.TRANSACTIONS.reduce((a, t) => a + t.pts, 0); + const rows = MONTH_TYPE_LABELS + .filter(([k]) => sums[k]) + .map(([k, label]) => monthChangeItem(label, sums[k], false)); + const html = monthChangeItem("本月净变化", net, true) + + (rows.length ? rows.join("") : '

本月暂无变动

'); + const walletEl = $("#month-changes"); if (walletEl) walletEl.innerHTML = html; - const dashEl = $("#dash-point-sources"); + const dashEl = $("#dash-month-changes"); if (dashEl) dashEl.innerHTML = html; } @@ -287,8 +305,8 @@ // 钱包只做余额与资金操作;收支明细统一到【交易记录】(见 index.html wallet-hint) $("#side-balance").textContent = D.fmt(D.USER.balance); $("#wallet-balance").textContent = D.fmt(D.USER.balance); - // 点数来源构成(v1.8:只展示构成,机制细节进 docs) - renderPointSources(); + // 本月点数变化(近 1 月按类型汇总收支,与仪表盘一致) + renderMonthChanges(); } /* --- 充值模拟(US-4:钱包充值入口 → 模拟支付 → 余额增加 + topup 交易,永久有效点数) --- */ @@ -315,8 +333,6 @@ if (!raw || isNaN(amt) || amt <= 0) { toast("请输入大于 0 的充值点数(未生效)"); return; } } D.USER.balance = Math.round((D.USER.balance + amt) * 100) / 100; - const top = D.POINT_SOURCES.find((s) => s.kind === "topup"); - if (top) top.pts = Math.round((top.pts + amt) * 100) / 100; D.TRANSACTIONS.unshift({ id: Date.now(), time: nowTime(), type: "topup", partner: "—", detail: "充值 · 模拟支付(演示,真实支付后续接入)", tokens: "—", pts: +amt, status: "成功", diff --git a/ui/js/data.js b/ui/js/data.js index b66539d..1889bf3 100644 --- a/ui/js/data.js +++ b/ui/js/data.js @@ -45,13 +45,6 @@ // 当前用户(公共版) USER: { name: "阿零", email: "demo@aitokenpool.local", balance: 12471 }, - // 点数来源(v1.8:面向用户只展示构成,机制细节进 docs) - POINT_SOURCES: [ - { kind: "gift", label: "赠送点数", pts: 1 }, - { kind: "earn", label: "收益点数", pts: 12470 }, - { kind: "topup", label: "充值点数", pts: 0 }, - ], - // 加额申请(US-20:企业成员申请 → 管理员批准 / 驳回;mock 内嵌数据) RAISE_REQUESTS: [ { id: 1, user: "苏航", email: "suhang@example.com", amount: 5000, reason: "本月开发任务增加,配额已用尽", status: "pending", time: "08-15 09:00" },