# 面板设计(设置 → stash) > 本文收纳面板的逐条说明。README 只给结构图与要点;这里的细节改面板时要一起改。 > 面板代码在 `client/client.js`(手写 bundle,无构建步骤),host 的数据整理在 `lib/library-view.js`。 ## 一、三层结构 ``` 首页 ──点任一格──▶ 类层 ──点任一行──▶ 详情 / 编辑 ◀──「← 概览」── ◀──「取消」── ``` 面板名就是插件名:**stash**。落地页是首页,面包屑从 `stash` 起。 ## 二、首页:数字优先 一页回答"我有多少、坏了几条"。 ``` + 新建条目 数据源 13 个数据源 ● 12 就绪 ● 1 有阻塞 6 6 1 远端接口 本机服务 本机文件 2 个账号·1 把钥匙未配置 依赖本机在跑 7 个路径 台账 取数台账 29 条(失败 6) · 经验库 10 条 · 覆盖 4 个库 有 2 条数据源失败过却没记经验 —— 进对应的类里看是哪条 ▸ 迁移(导出 / 导入 / 清空) ``` - **用词分两层**:首页数的是**数据源**(三类合计,读作"N 个数据源"),类层列的是**这一类里的资源**。同一个词只在一个地方出现,避免"资源到底指什么"。 - **三类是唯一一级分类**:`远端接口` / `本机服务` / `本机文件`。按"东西怎么进来的"分,人话优先;技术细节(MCP、S3/WebDAV、SQLite、声明式 HTTP…)只在**登记时**出现。 - 归类**自动派生**,不需要人填:`files` 与 SQLite → 本机文件;MCP 走 stdio、以及**回环地址**(`127.0.0.1` / `localhost` / `::1`)→ 本机服务;其余 → 远端接口。回环判定的反例(本地反向代理把远端伪装成 `127.0.0.1`)由注册表字段 `bucket` 覆盖。 - `0 条`的那一类**照常显示**——空本身是信息,三格也才是稳定的一套。 - 「有阻塞」旁的数字**可点**,直达该类的阻塞筛选。 ## 三、类层:账号在前,资源在后 点任一格进入那一类。标题是类名,回退走「← 概览」。 ``` 账号 2 个 · 3 把钥匙 · 1 把未配置 [全部 ▾] 某赔率服务 [API 密钥] odds_service 1 把钥匙 · 已配置 › 某数据库 [数据库] example_db 2 把钥匙 · 1 把未配置 › 资源 6 条 · 6 就绪 [全部 ▾] ● 就绪 某赔率服务… odds_service [声明式 HTTP] [官方 API / 需授权] [代写] 用过 4 次 ▾ ``` - **钥匙跟着资源走**:账号块只列**这一类资源用到的账号**(按引用名交叉认领)。今天账号全落在「远端接口」;将来本机服务需要 token 时,它会自己出现在那一类里。 - 两个块**各有自己的数字与状态下拉**(账号:全部 / 已配置 / 有未配置;资源:全部 / 就绪 / 有阻塞),数字只在标题行出现一次。 - 账号超过 4 个折叠,块内自带展开/收起。 - 筛选到 0 条时**表头与下拉仍在**,空态写明"把下拉改回「全部」,或清空搜索框"——否则选完状态就再也改不回来。 - **整行点开就是详情**(没有单独的「详情」按钮):详情里有禁止边界 / 动作 / 路径 / 命令,以及「编辑」「删除」。 - **改与删只对代写条目开放**:手写条目(`sources.mjs`)没有这两个按钮,卡上写明"程序不改写它"。 - 删除只要**一次二次确认**(不像清空整库那样要输校验码),并说清后果:台账只追加不删;该库的经验仍在 `lessons.json`,但界面按已登记库聚合,所以不再显示。 ## 四、新建 / 编辑:一个页面 + 三级下拉 ``` + 新建条目 新建什么 [ 远端接口 ▾ ] ← 就是首页那三类(资源的一级分类) 形态 [ 声明式 HTTP 接口(http)▾ ] ← 按类自动收窄 ID / 名称 / 接口地址 / 方法 / 使用边界 / 钥匙引用名 … ▸ 高级设置(请求头 / 查询参数 / 取哪一段 / 请求体 / 必填参数 / 条数上限 / 覆盖范围 / 摘要 / 禁止边界 / 注意事项) 要新建的不是数据源,而是账号? 新建账号 → ``` **形态按类收窄**(选完类只看得到这一类能有的): | 新建什么 | 形态 | |---|---| | 远端接口 | 声明式 HTTP 接口 / 内置处理器 / 对象存储·文件传输 / MCP 服务 | | 本机服务 | 本机端口(即回环上的 `http`)/ MCP 服务 | | 本机文件 | 文档与数据文件 / 本地数据库(SQLite) | **字段按类给,不多问**:本机文件那一类既不上网取数、也不需要凭据,所以**不问「使用边界」与「钥匙引用名」**,提交时也不带 `access`。其余形态问,因为网络上的东西确实有"允许怎么取"和"要不要钥匙"两件事。 **账号不是资源的一类**,所以不占「新建什么」的位置——它是页面底部的次要入口。 - 校验**与模型侧 `stash_source_add` 是同一套代码**:面板的写端点直接调用那个工具本体,不会这边放行、那边失败。 - 报错落到具体字段上:顶部一条汇总(`⚠ …(共 N 处需要改)`),字段就地标红,并说清怎么改。 - 表单里**永远没有"值"的输入框**:只登记引用名;值只能由人在账号详情里贴。 - 边界那组下面写明:**只有 ◇ 只能人工导出 / ◇ 明确不做会被硬拒绝**(取数工具不取数、只留痕),另外两个是声明。 ## 五、排版与字号(改动前先读) 一屏里字号只有一套,定义在 `client/client.js` 的 `TYPE` 常量里: | 用途 | 值 | 说明 | |---|---|---| | 页面标题 | `19px` | | | **行标签** | `14px` | 比框里的值大一档,主导视觉;固定 `104px` 且右对齐 | | **控件里的值** | `13px` | 输入框 / 下拉 / 按钮同号 | | 元信息 | `12px` | 用量、钥匙状态、计数 | | 说明文字 | `11px` | 与方框同一左边缘 | | 展示级数字 | `52 / 34 / 28 / 20px` | 只在首页用 | 三条硬约束,测试钉住: 1. **字号只从 `TYPE` 取**,不写字面量; 2. 输入框与按钮的字号用 `!important` 钉死——宿主样式表同优先级且后加载会盖过来; 3. 标签列固定宽度 + `nowrap`,需要让步时让控件让;对象里**不许出现重复键**(同名键取后者,曾把一个 14px 覆盖成 13px,表现是标签折行、方框起点参差)。