Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions docs/user-stories.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
> **本文档以中文撰写**(用户故事主体、验收标准、流程说明均为中文;关键术语保留中英对照)。
>
> **v1.13(2026-08-17)· UI 演化约束:尽量少用弹窗 / modal.** 新增「UI 约定」章节(§1.1):优先行内(inline)交互(行内展开表单 / 可折叠面板 / 就地编辑),弹窗仅限真正需要聚焦 / 阻塞的场景(如删除确认),**禁止弹窗嵌套**;存量 modal(充值 topup-modal、申请加额 raise-modal、模型消费 chat-modal)标记改造优先级,后续迭代分批改为行内形态。部门添加/编辑已由弹层改为**行内展开表单**(`#dept-form-card`)。
>
> **v1.14(2026-08-17)· 充值 / 加额改行内(P1 完成).** 按 UI 美化与 UE 优化 rant(`2026-08-17T15:50:05`)「少弹窗改造(优先)」:充值(原 topup-modal)与申请加额(原 raise-modal)改为钱包页**行内展开卡片**(`#topup-card` / `#raise-card`,点按钮原地展开、两卡互斥、取消即收起),替代弹层;P1 存量 modal 清零,仅剩 P2 模型消费聊天(chat-modal)。
> **v1.12(2026-08-17)· 移除「组织设置 Organization settings」表单.** 组织管理页只保留部门列表(部门 CRUD + 每月点数分配),删除底部「组织设置」表单(组织名称 / 默认成员配额 / 开关)。「关闭外部注册」属**部署配置项,不在 UI 中设置**(US-16 标注);「成员自助申请加额需管理员审批」开关移除后,申请加额流程**默认需审批**(US-20 说明)。
> **v1.11(2026-08-17)· 管理视图移除独立「Key 池」管理,统一走「上架 key」.** 管理员与普通用户一样通过**共享管理页「上架新 key」**(选厂商 → Plan → 模型、填 key、声明额度、可用时间段)配置上游 key——企业场景下管理员上架、员工消费,本质上就是 key 池;不再有独立的管理员 Key 池界面。移除 Admin「Key 池」tab(成员管理 / 用量报表 / 组织管理 / 平台运营保留)。「Key 池」保留为**数据层概念**(平台持有的上游 key 集合,见 docs/architecture.md 4.2)。更新 US-12 / 企业流程 / 对齐表。
> **v1.10(2026-08-17)· 上架表单"可用时间段"结构化.** 上架 key 的可用时间段改为**正式字段**(星期多选 + 起止时间,可多选;留空 = 全天不限),后端可解析生效;**备注只作纯文本**,不承载任何逻辑。共享列表展示可用时间段(如「周一~周五 09:00-18:00」),未设置显示「全天」。更新 US-8 / US-9 AC。
Expand Down Expand Up @@ -36,10 +38,10 @@
- **优先行内(inline)交互**:表单、编辑、确认等操作优先在当前页面 / 区域内展开(行内展开表单、可折叠面板、就地编辑),而非弹窗;
- **弹窗仅限真正需要聚焦 / 阻塞的场景**:如必须确认的重要操作(删除)、需要专注输入的少量场景;**禁止弹窗嵌套**(弹窗内不得再开弹窗);
- **替代形态**:表单 / 编辑 → 行内展开、抽屉(drawer / 侧滑)、或就地编辑;确认 → 行内二次确认(按钮变「确认?」态)或轻量 toast + 撤销;选择 / 搜索 → 行内下拉或独立页面;
- **存量 modal 改造优先级**(后续迭代分批处理):
- **P0 高频**:上架表单(已行内卡片 ✓)、部门添加/编辑(已行内 ✓)
- **P1**:充值(topup-modal → 行内 / 独立页)、申请加额(raise-modal → 行内)
- **P2**:模型消费聊天(chat-modal → 独立页或行内面板)
- **存量 modal 改造进度**(rant `2026-08-17T15:50:05` 系统性 UI/UE 优化波,分批推进):
- **P0 高频 ✓**:上架表单(`#share-form-card` 行内卡片)、部门添加/编辑(`#dept-form-card` 行内卡片)
- **P1 ✓(2026-08-17)**:充值(`#topup-card` 行内卡片,替代 topup-modal)、申请加额(`#raise-card` 行内卡片,替代 raise-modal)——钱包页点按钮原地展开,两卡互斥
- **P2**:模型消费聊天(chat-modal → 独立页或行内面板,待后续迭代)
- 该原则约束后续所有 UI 演化;与 UI 原型(`ui/`)对齐。

### 核心机制(Core mechanism)
Expand Down
2 changes: 1 addition & 1 deletion ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
- 替代形态:行内二次确认(按钮变「确认?」)、toast + 撤销、行内下拉 / 独立页;
- **存量 modal 改造优先级**:
- **P0 已行内**:上架表单(`#share-form-card` 行内卡片)、部门添加/编辑(`#dept-form-card` 行内卡片,v1.13 由弹层改造)
- **P1**:充值(topup-modal)、申请加额(raise-modal)→ 行内 / 独立页
- **P1 已行内(v1.14)**:充值(`#topup-card` 行内卡片)、申请加额(`#raise-card` 行内卡片)——钱包页点按钮原地展开、两卡互斥
- **P2**:模型消费聊天(chat-modal)→ 独立页 / 行内面板
- 本原则与 docs/user-stories.md §1.1 对齐。

Expand Down
1 change: 0 additions & 1 deletion ui/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,6 @@ select.input option { background: var(--bg-card); }
.modal-head h3 { font-size: 16px; margin: 0; }

/* 模态框操作行 / 充值预设(US-4) */
.modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 4px; }
.topup-presets { display: flex; gap: 8px; margin-top: 6px; }
.topup-presets .btn { min-width: 72px; }
.topup-presets .btn.active { background: var(--accent-soft); border-color: rgba(78,205,196,.5); color: var(--accent-text); }
Expand Down
88 changes: 38 additions & 50 deletions ui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,44 @@ <h3>点数余额 <span class="en">Points balance</span></h3>
<span class="muted wallet-note">充值(演示流程,真实支付后续接入) · 提现暂不支持</span>
</div>
</div>
<!-- 充值:行内展开卡片(US-4 · 少用弹窗原则 v1.13:充值改行内,替代原 topup-modal) -->
<div class="card" id="topup-card" hidden>
<h3>充值点数 <span class="en">Top up</span></h3>
<p class="muted" style="margin-bottom:12px">演示流程:真实支付通道后续接入。</p>
<div class="form">
<label>选择金额(点数)
<div class="topup-presets">
<button type="button" class="btn btn-ghost" data-topup-amt="100">100</button>
<button type="button" class="btn btn-ghost" data-topup-amt="500">500</button>
<button type="button" class="btn btn-ghost" data-topup-amt="1000">1000</button>
</div>
</label>
<label>或自定义金额
<input id="topup-custom" type="number" min="1" step="0.01" class="input" placeholder="如 300 或 25.5">
</label>
<div class="form-row">
<button type="button" class="btn btn-primary" id="topup-confirm">确认充值 <span class="en">(Confirm)</span></button>
<button type="button" class="btn btn-ghost" id="topup-cancel">取消 <span class="en">(Cancel)</span></button>
</div>
</div>
</div>
<!-- 申请加额:行内展开卡片(US-20 · 少用弹窗原则:替代原 raise-modal) -->
<div class="card" id="raise-card" hidden>
<h3>申请加额 <span class="en">Request more points</span></h3>
<p class="muted" style="margin-bottom:12px">余额低时可申请更多点数,提交后等待管理员审批(US-20)。</p>
<div class="form">
<label>申请点数
<input id="raise-amount" type="number" min="1" step="1" class="input" placeholder="如 5000">
</label>
<label>申请原因
<input id="raise-reason" class="input" placeholder="如:本月配额已用完,需要继续开发">
</label>
<div class="form-row">
<button type="button" class="btn btn-primary" id="raise-confirm">提交申请 <span class="en">(Submit)</span></button>
<button type="button" class="btn btn-ghost" id="raise-cancel">取消 <span class="en">(Cancel)</span></button>
</div>
</div>
</div>
<div class="card">
<h3>本月点数变化 <span class="en">Month point changes</span></h3>
<div class="mini-list" id="month-changes"></div>
Expand Down Expand Up @@ -401,56 +439,6 @@ <h3 id="chat-title">使用模型</h3>

<div id="toast" class="toast hidden"></div>

<!-- 充值模拟(US-4:钱包页充值入口 → 输入点数 → 余额增加 + topup 交易记录,永久有效点数) -->
<div id="topup-modal" class="modal-overlay hidden">
<div class="modal">
<div class="modal-head">
<h3>充值点数 <span class="en">Top up</span></h3>
<button type="button" class="btn btn-ghost" data-modal-close="topup-modal">✕</button>
</div>
<p class="muted">演示流程:真实支付通道后续接入。</p>
<div class="form">
<label>选择金额(点数)
<div class="topup-presets">
<button type="button" class="btn btn-ghost" data-topup-amt="100">100</button>
<button type="button" class="btn btn-ghost" data-topup-amt="500">500</button>
<button type="button" class="btn btn-ghost" data-topup-amt="1000">1000</button>
</div>
</label>
<label>或自定义金额
<input id="topup-custom" type="number" min="1" step="0.01" class="input" placeholder="如 300 或 25.5">
</label>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-primary" id="topup-confirm">确认充值 <span class="en">(Confirm)</span></button>
<button type="button" class="btn btn-ghost" data-modal-close="topup-modal">取消 <span class="en">(Cancel)</span></button>
</div>
</div>
</div>

<!-- 成员申请加额(US-20:余额低时申请更多点数 → 等待管理员审批) -->
<div id="raise-modal" class="modal-overlay hidden">
<div class="modal">
<div class="modal-head">
<h3>申请加额 <span class="en">Request more points</span></h3>
<button type="button" class="btn btn-ghost" data-modal-close="raise-modal">✕</button>
</div>
<p class="muted">余额低时可申请更多点数,提交后等待管理员审批(US-20)。</p>
<div class="form">
<label>申请点数
<input id="raise-amount" type="number" min="1" step="1" class="input" placeholder="如 5000">
</label>
<label>申请原因
<input id="raise-reason" class="input" placeholder="如:本月配额已用完,需要继续开发">
</label>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-primary" id="raise-confirm">提交申请 <span class="en">(Submit)</span></button>
<button type="button" class="btn btn-ghost" data-modal-close="raise-modal">取消 <span class="en">(Cancel)</span></button>
</div>
</div>
</div>

<script src="js/data.js"></script>
<script src="js/app.js"></script>
</body>
Expand Down
34 changes: 14 additions & 20 deletions ui/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,21 +360,22 @@
renderMonthChanges();
}

/* --- 充值模拟(US-4:钱包充值入口 → 模拟支付 → 余额增加 + topup 交易,永久有效点数) --- */
/* --- 充值模拟(US-4:钱包页行内卡片 → 输入点数 → 余额增加 + topup 交易,永久有效点数) --- */

function openTopup() {
$("#topup-custom").value = "";
$$("#topup-modal .topup-presets .btn").forEach((b) => b.classList.remove("active"));
$("#topup-modal").classList.remove("hidden");
$$("#topup-card .topup-presets .btn").forEach((b) => b.classList.remove("active"));
$("#topup-card").hidden = false;
$("#raise-card").hidden = true; // 互斥:开充值收起加额
$("#topup-custom").focus();
}

function closeTopup() {
$("#topup-modal").classList.add("hidden");
$("#topup-card").hidden = true;
}

function confirmTopup() {
const preset = document.querySelector("#topup-modal .topup-presets .btn.active");
const preset = document.querySelector("#topup-card .topup-presets .btn.active");
const customRaw = $("#topup-custom").value;
let amt;
if (preset && !customRaw) amt = Number(preset.dataset.topupAmt);
Expand All @@ -399,12 +400,13 @@
function openRaise() {
$("#raise-amount").value = "";
$("#raise-reason").value = "";
$("#raise-modal").classList.remove("hidden");
$("#raise-card").hidden = false;
$("#topup-card").hidden = true; // 互斥:开加额收起充值
$("#raise-amount").focus();
}

function closeRaise() {
$("#raise-modal").classList.add("hidden");
$("#raise-card").hidden = true;
}

function confirmRaise() {
Expand Down Expand Up @@ -1112,28 +1114,20 @@
if (d) deleteSharing(Number(d.dataset.shareDelete));
});

// 钱包按钮(充值:US-4 模拟流程;申请加额:US-20;提现仍 disabled)
// 钱包按钮(充值:US-4 行内卡片;申请加额:US-20 行内卡片;提现仍 disabled)
$("#topup-btn").addEventListener("click", openTopup);
$("#raise-btn").addEventListener("click", openRaise);
$("#topup-confirm").addEventListener("click", confirmTopup);
$("#raise-confirm").addEventListener("click", confirmRaise);
$$("#topup-modal .topup-presets .btn").forEach((b) =>
$("#topup-cancel").addEventListener("click", closeTopup);
$("#raise-cancel").addEventListener("click", closeRaise);
$$("#topup-card .topup-presets .btn").forEach((b) =>
b.addEventListener("click", () => {
$$("#topup-modal .topup-presets .btn").forEach((x) => x.classList.remove("active"));
$$("#topup-card .topup-presets .btn").forEach((x) => x.classList.remove("active"));
b.classList.add("active");
$("#topup-custom").value = "";
})
);
$$("[data-modal-close]").forEach((b) =>
b.addEventListener("click", () => {
const id = b.dataset.modalClose;
const m = document.getElementById(id);
if (m) m.classList.add("hidden");
})
);
["topup-modal", "raise-modal"].forEach((id) => {
document.getElementById(id).addEventListener("click", (e) => { if (e.target === document.getElementById(id)) document.getElementById(id).classList.add("hidden"); });
});
// 钱包页提示 → 跳转交易记录(明细统一入口)
$("#wallet-goto-tx").addEventListener("click", () => switchView("transactions"));

Expand Down
Loading