nx-sk 0.17.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +130 -1
- package/README.md +85 -5
- package/assets/nx-sk/SKILL.md +65 -15
- package/assets/nx-sk/references/00-design.md +3 -3
- package/assets/nx-sk/references/10-sections-entries.md +18 -3
- package/assets/nx-sk/references/15-special-fields.md +178 -0
- package/assets/nx-sk/references/40-files.md +44 -8
- package/assets/sk-needdo/SKILL.md +30 -3
- package/assets/sk-needdo/references/20-schema.md +5 -1
- package/assets/sk-needdo/references/30-fill.md +2 -2
- package/assets/sk-needdo/references/50-example.md +15 -9
- package/assets/sk-source/SKILL.md +12 -2
- package/assets/sk-source/references/20-intake.md +3 -0
- package/package.json +1 -1
- package/src/core/attachments.js +17 -4
- package/src/core/fields.js +160 -20
- package/src/core/render.js +58 -4
- package/src/core/store.js +10 -3
- package/src/core/vault.js +17 -8
- package/src/modules/entries/index.js +27 -0
- package/src/modules/entries/service.js +340 -21
- package/src/modules/sections/index.js +22 -0
- package/src/modules/sections/service.js +170 -7
- package/src/modules/sections/view.jsx +441 -56
- package/src/modules/settings/navManager.jsx +102 -67
- package/src/modules/settings/view.jsx +3 -1
- package/src/modules/transfer/service.js +13 -0
- package/src/shared/table.js +884 -0
- package/src/web/frontend/App.jsx +69 -22
- package/src/web/frontend/components/fieldEditor.jsx +8 -1
- package/src/web/frontend/components/navModel.js +64 -7
- package/src/web/frontend/components/tableField.jsx +451 -0
- package/src/web/frontend/styles.css +146 -2
- package/src/web/public/assets/{files-CYxBsvjL.js → files-vbBBJ5q_.js} +1 -1
- package/src/web/public/assets/index-CYX-3oPr.css +1 -0
- package/src/web/public/assets/index-Czcw5Khj.js +41 -0
- package/src/web/public/assets/view-B3IpBaPq.js +1 -0
- package/src/web/public/assets/{view-D9cY7JwZ.js → view-C2PCebaC.js} +1 -1
- package/src/web/public/assets/view-Dlnt7qN2.js +40 -0
- package/src/web/public/assets/{view-C_FrPQ-S.js → view-DzlhjD91.js} +1 -1
- package/src/web/public/assets/view-PNU16Ybm.js +3 -0
- package/src/web/public/index.html +2 -2
- package/src/web/public/assets/index-BhVJGdcz.js +0 -41
- package/src/web/public/assets/index-bNZkkcRr.css +0 -1
- package/src/web/public/assets/view-CssUSAY2.js +0 -1
- package/src/web/public/assets/view-dM2GLJ6q.js +0 -36
- package/src/web/public/assets/view-whlEu4sk.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,136 @@
|
|
|
2
2
|
|
|
3
3
|
本文件格式参考 [Keep a Changelog](https://keepachangelog.com/),中文正文。
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 0.20.0 (2026-10-30)
|
|
6
|
+
|
|
7
|
+
**栏目管理重构成树;初始化不再播种一堆场景栏目,改播一个「字段样例」说明书。**
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **栏目管理 = 栏目 → 条目的树**(`section tree`,HTTP `GET /api/sections/tree`):
|
|
12
|
+
可展开/收起(展开态记在面板设置里)、**多选 / 全选**(勾栏目 = 连条目一起,条目可单独勾)、
|
|
13
|
+
**批量删除**(`section remove-many` / `entry remove-many`,HTTP 同名 POST 路由)——
|
|
14
|
+
精确到条目,删栏目等同删文件夹(连带条目,需显式确认);找不到的跳过并报告(status: partial),
|
|
15
|
+
一个都找不到才报错。栏目多时的搜索:栏目命中整棵留下,只有条目命中时只留命中的并临时展开。
|
|
16
|
+
- **初始化只播种一个「字段样例」栏目**(`demo` 模板,连一条示例条目一起):
|
|
17
|
+
标量字段(文本/数字/是否/下拉/日期/标签)、组合字段(结构清单 + 表格:计算列与表尾统计)、
|
|
18
|
+
富内容(图文 / 附件 / 密钥)各来一份,外加自带的「原始资料」袋——
|
|
19
|
+
第一屏是说明书,不是别人的表格。求职 / 密钥 / 项目那 6 个场景模板仍是模板(`section add --template`)。
|
|
20
|
+
- **没有 KV 栏目时第一次 `key set` 自动补建**(与 `section add secret --template secret` 同形状;
|
|
21
|
+
读命令不建)。播种不再自带密钥栏目后,`key set` 的「我要存」不该被「先建栏目」挡住。
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- `settings.defaultSection` 缺省从 `job` 改为 `demo`(指向播种的那个栏目)。
|
|
26
|
+
- 面板「栏目」页整页重构:平铺列表 → 树 + 批量条 + 搜索;存量用户的 store 不受影响
|
|
27
|
+
(播种只发生在「store 文件不存在」时,文件在、栏目为空依旧不复活)。
|
|
28
|
+
|
|
29
|
+
## 0.19.0 (2026-10-30)
|
|
30
|
+
|
|
31
|
+
**新字段类型 `table`:结构写在数据里的表单表格。**
|
|
32
|
+
|
|
33
|
+
`entrylist` 是「变长的几列文本」;`table` 是它的进阶形态——每格有类型(勾选 / 下拉 / 数字 /
|
|
34
|
+
日期),带**计算列**与**表尾统计**。关键差别不在功能多少,在**结构归谁**:
|
|
35
|
+
`table` 的列定义、行、公式、统计配置全部存在**条目值里**,不在栏目字典里。
|
|
36
|
+
因此「这一条想多一列」不必改 schema,也不会波及同栏目的其它条目;
|
|
37
|
+
面板上直接加列 / 改类型 / 写公式,改完就是这份数据的一部分。
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- **`type: 'table'` 表格字段**(`src/shared/table.js` 为计算内核,前后端同一份实现):
|
|
42
|
+
- 值是一份**自描述文档**:`{v, columns, rows, totals?, summary?}`。三种输入都认——
|
|
43
|
+
行数组(列取字段的「初始列」或从行推断)、文档本身、以及它们的 JSON 串。
|
|
44
|
+
- 列有类型:`text / textarea / number / bool / select / date / month / tags`;
|
|
45
|
+
给 `formula` 就是**计算列**(不落盘,读时现算);`sensitive: true` 的列密文落盘。
|
|
46
|
+
- 公式是 **JS 表达式**(不发明语法),只包成 `return ( … )`:列 key 与**中文列名**
|
|
47
|
+
都能当变量,`row` 取原值、`rows` 取整表、`col("列名")` 取一列;
|
|
48
|
+
`sum / avg / min / max / count / countTrue / distinct / median / pct / round / isBlank …`
|
|
49
|
+
与 `Math`、`JSON` 等内建可用。求值作用域用 `with` + Proxy 封死,`window / process / fetch` 取不到。
|
|
50
|
+
- **统计两层**:列上的 `total` 决定表尾那一格(数字默认求和、勾选默认计是,
|
|
51
|
+
多种统计方式自动分组成「合计 / 平均…」多行);整表表达式写在数据的 `totals` 里
|
|
52
|
+
(如完成率 `pct(countTrue(col("done")), n)`)。统计不落盘,读时现算。
|
|
53
|
+
- 错误停在能看懂的那一层:「不存在的名字『qty』,可用的名字:a、b…」、
|
|
54
|
+
「计算列只能引用它前面的列」、「结果不是有限数字(除以 0)」——不吐 NaN。
|
|
55
|
+
- 新命令 `nx-sk entry table <条目> --field <表格字段>`(HTTP `GET /api/tables/:ref`):
|
|
56
|
+
只读地印出表头 / 数据 / 计算列 / 合计 / 公式报错。
|
|
57
|
+
- 面板:`tableField.jsx` 的表格控件——勾选框 / 下拉框 / 数字 / 日期就地编辑,
|
|
58
|
+
回车换下一行、Alt+↑↓ 跳上下格、行可上下移与删除;「列设置」里加列 / 改类型 /
|
|
59
|
+
写公式 / 指定统计方式 / 默认值 / 左右移 / 删列(连值一起删,改 key 会搬值)。
|
|
60
|
+
栏目编辑页新增字段时可直接配初始列。
|
|
61
|
+
- **写入即体检**:每条公式在保存前用一行空值当探针跑一遍,只拦**与数据无关**的错
|
|
62
|
+
(语法错 / 名字解析不到 / 结果不是单值),除零这类「这条数据不巧」留到渲染时逐格报。
|
|
63
|
+
列、行、默认值、下拉候选、`total`、`totals` 全走同一条校验,面板与 CLI 共用。
|
|
64
|
+
- 列可以带 `default`(新增行时的初值,按类型强转;`0` / `false` 都合法)。
|
|
65
|
+
- 新 reference `assets/nx-sk/references/15-special-fields.md`:值不是标量的字段
|
|
66
|
+
(`table` / `entrylist` / `md` / `file` / `source` / `secret`)的形状、规矩、
|
|
67
|
+
公式与统计口径、错误对照表;`10-sections-entries` 里那份表格说明改为指向它(不留两份)。
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- **空表现在是合法的**:`--set 表=` / `[]` / `{}` / `{"columns":[],"rows":[]}` 都能把表清空
|
|
72
|
+
(值存 `null`);有初始列时 `[]` 留下「列在、行空」的骨架;只有「有行却没列」才报错。
|
|
73
|
+
原先「必须给列」的硬校验会把「只想清空」和「新建一张空表」一起挡掉。
|
|
74
|
+
- `isBlank` 与 `isStoredEmpty` 分开了:前者判完整度(有列没行的表算没填),
|
|
75
|
+
后者判「值要不要输出」(骨架必须带出去,否则面板拿不到列,搭好的结构一保存就"消失")。
|
|
76
|
+
- `serializeEntry` 对表格字段永远输出**自描述文档**(列跟着数据走),
|
|
77
|
+
所以 `entry get` / `section dump` / 导出拿到的东西不需要再回查栏目字典。
|
|
78
|
+
- `sensitiveViewer` 现在也认表格的密文列(原先只探 entrylist 的 `fields`),
|
|
79
|
+
并且列存在数据里时按「任一格是密文」判定,不会再退化成「需要密钥才能解密」。
|
|
80
|
+
- **短值的打码占位现在也认得出**:`maskValue` 对 ≤10 字符的值返回全星(`***`),
|
|
81
|
+
而老判断只认「连续 6 个星」,于是 3 位密码的打码值会被当成新密码加密存进去(无声数据损坏)。
|
|
82
|
+
- 空表算「未填」:`isBlank` 认 `{rows: []}`,完整度不会被一张没有行的表撑满。
|
|
83
|
+
|
|
84
|
+
### Fixed
|
|
85
|
+
|
|
86
|
+
- 表格的密文列在**打码显示**时保存:打码占位优先按打码值反查原密文(行被拖动过也能认对),
|
|
87
|
+
认不出来才退回行号兜底;已知限制(两格打码值一模一样又拖了行)写进文档。
|
|
88
|
+
- `sections` 的「新增字段」表单里 `toast` 未定义(校验失败时会抛 ReferenceError),现按 props 传入。
|
|
89
|
+
|
|
90
|
+
## 0.18.0 (2026-10-28)
|
|
91
|
+
|
|
92
|
+
**拖拽不再闪,悬浮不再乱弹;「原始资料」袋对每个栏目都成立。**
|
|
93
|
+
|
|
94
|
+
这一版没有新栏目,都是「原来能用、但用起来别扭」的地方:设置页拖分组时列表自己
|
|
95
|
+
在动,于是闪;头部悬浮分组入口时一秒钟弹开又收起好几个;自定义栏目丢了资料袋。
|
|
96
|
+
|
|
97
|
+
### Changed
|
|
98
|
+
|
|
99
|
+
- **头部「分组入口」的悬浮展开加了意图延迟,并且同一时刻只开一个**:原先 `mouseenter`
|
|
100
|
+
立刻弹、`mouseleave` 140ms 就收,鼠标横穿导航栏去点右边的 tab 时,路过的分组会被
|
|
101
|
+
顺带弹开又收起(一眼看过去就是乱闪);各分组的展开态又各自持有,快速划过能同时
|
|
102
|
+
叠出两个菜单。现在:停住 130ms 才展开(路过不算)、离开 180ms 后收起(划进菜单就撤销)、
|
|
103
|
+
展开态交给 App 托管成「只开一个」、点击改为切换(触屏没有 hover,只能走这条路——
|
|
104
|
+
按 `(hover: hover)` 分流,避免 tap 时合成的 mouseenter 先把菜单开掉、click 又把它关掉)。
|
|
105
|
+
另加:展开时三角翻上去(只动 transform,不改布局)。
|
|
106
|
+
- **「原始资料」袋(`source` 字段)成为每个非 KV 栏目自带的结构**:此前只有模板实例
|
|
107
|
+
自带,自定义栏目一旦传了 `--fields`/`--groups`(sk-needdo 的常规路径),袋就被
|
|
108
|
+
整体覆盖掉了。现在内置规则收口为唯一函数 `ensureSourceBuiltin`,在 `instantiateTemplate`、
|
|
109
|
+
`section add`、`normalizeSection` 三处生效——存量栏目缺袋时读一次即自愈,
|
|
110
|
+
KV 表仍不加(形状固定)。sk-needdo 文档同步改为「杂乱输入先入袋、再整理」,
|
|
111
|
+
并去掉字段设计里重复的「来源」text 字段(与 `source` 键冲突)。
|
|
112
|
+
|
|
113
|
+
### Fixed
|
|
114
|
+
|
|
115
|
+
- **设置页「栏目管理」拖拽闪屏、边缘落点乱跳**:两处根因都在「拖的时候列表自己在动」。
|
|
116
|
+
- 闪屏:原先用**实时预览**(拖动中就把被拖的行挪到落点上)。行一挪,指针底下的元素
|
|
117
|
+
就换了、下方容器整体位移一行(28px),`dragover` 于是算出另一个落点,再挪再算——
|
|
118
|
+
自己推自己。现在拖动期间**列表静止**(被拖的那行半透明留在原地),落点用一条
|
|
119
|
+
**不占布局的指示线**(2px inset 压在行边上)表达:几何恒定 → 落点只随指针单调变化,
|
|
120
|
+
松手一次性提交,结果就是指示线指的位置。拖影也从 10px 的把手换成整行。
|
|
121
|
+
- 边缘乱跳:容器空白处(缝隙、内边距、说明文字)原先一律判成「追加到末尾」,
|
|
122
|
+
指针一进缝隙整列表就跳到队尾;现在整块容器都按**行中线**算插入位
|
|
123
|
+
(`navModel.slotAt`),边缘与缝隙都归到最近的一侧。
|
|
124
|
+
- 平铺区索引错位:`containerOf` 的平铺分支拿 `poolOrder`(含已归组 / 隐藏栏目的全量顺序)
|
|
125
|
+
当行号,与屏幕上第几行差好几格,落点因此偏——改为按**可见行**(`viewRows`)取索引。
|
|
126
|
+
- 分组换位从「交换」改成「挪」:0 拖到 2 时中间那组上移一格,不再把 B 留在原地。
|
|
127
|
+
- 顺带:拖回原位不再提示「有未保存的改动」(导航按 `sameStructure` 判脏,
|
|
128
|
+
`order` 里留下的序列脚印不参与比较)。
|
|
129
|
+
|
|
130
|
+
### 测试
|
|
131
|
+
|
|
132
|
+
- `nav-model.test.mjs` 新增 5 组用例:可见行口径(`viewRows` / 平铺区落点不偏格)、
|
|
133
|
+
行中线取位(`slotAt`,缝隙不跳)、结构等价(`sameStructure`,拖回原位不算脏)、
|
|
134
|
+
分组「挪」而非「交换」(`moveGroupTo`)。
|
|
6
135
|
|
|
7
136
|
## 0.17.0 (2026-10-25)
|
|
8
137
|
|
package/README.md
CHANGED
|
@@ -102,22 +102,35 @@ ln -s "$(pwd)/assets/nx-sk" "$HOME/.workbuddy/skills/nx-sk"
|
|
|
102
102
|
一个「本机工具类」项目的标准骨架实现(server-cli-web):**serve 驱动 CLI 与 Web,
|
|
103
103
|
CLI 与 API 同源,skill 驱动 agent**。落到具体功能上:
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
**首次运行只播种一个「字段样例」栏目**(`demo`),连一条示例条目一起——把能力直接摆给你看:
|
|
106
|
+
|
|
107
|
+
| 组 | 字段 |
|
|
108
|
+
| --- | --- |
|
|
109
|
+
| 基本字段(标量) | 单行文本 / 多行文本 / 数字 / 是否 / 下拉框 / 日期 / 月份 / 标签 |
|
|
110
|
+
| 组合字段(值有形状) | **结构清单**(变长行 + 密文列)、**表格**(列在数据里 + 计算列 + 表尾合计/平均/计数) |
|
|
111
|
+
| 富内容 | **图文**(markdown + 贴图 + 待办)、**附件**、**密钥**(AES-256-GCM 密文) |
|
|
112
|
+
|
|
113
|
+
外加每个栏目自带的「原始资料」袋。示例条目把这些都填好了——打开面板就能试,
|
|
114
|
+
改坏了自己删(`section remove demo`),或整栏重建(`section add demo --template demo`)。
|
|
115
|
+
|
|
116
|
+
**其它 8 个模板不再自动播种**,要用时建(模板只是**建议清单**,`--set 任意键=值` 直接写):
|
|
117
|
+
|
|
118
|
+
| 模板 | id | 内容 |
|
|
106
119
|
| --- | --- | --- |
|
|
107
|
-
| 求职 | `job` | 求职用的个人信息档案:10 个分组 / 80
|
|
120
|
+
| 求职 | `job` | 求职用的个人信息档案:10 个分组 / 80 个字段(姓名、学历、联系方式、求职意向、紧急联系人…) |
|
|
108
121
|
| 项目经历 | `projects` | 一个项目一个条目:名称 / 角色 / 时间 / 技术栈 / 职责与亮点 |
|
|
109
122
|
| 实习/工作经历 | `internships` | 一段经历一个条目:公司 / 岗位 / 时间 / 职责 |
|
|
110
123
|
| 校内职务/实践 | `campus` | 一条职务或实践一个条目:职务 / 组织 / 时间 / 职责 |
|
|
111
|
-
| 密钥 | `secret` | **一张 KV 表**(`kv: true`):面板上就是两列表格(名称 / 值),一行一个键。落盘是 **AES-256-GCM** 密文,读出来默认是原文(`--mask`
|
|
124
|
+
| 密钥 | `secret` | **一张 KV 表**(`kv: true`):面板上就是两列表格(名称 / 值),一行一个键。落盘是 **AES-256-GCM** 密文,读出来默认是原文(`--mask` 才打码)。第一次 `key set` 没有它时会自动补建 |
|
|
112
125
|
| 部署配置 | `deploy` | **一份配置文件一个条目**(Dockerfile / docker-compose / k8s 清单):正文即文件原文,外加「放哪 / 哪些值要替换 / **这个场景自己的凭据清单** / 何时用」,好让它在别的项目里照着用 |
|
|
113
126
|
|
|
114
|
-
|
|
127
|
+
栏目不是写死的——
|
|
115
128
|
字段字典是**数据**,加字段(`section update --add-field`,或 `entry update --set 任意键=值` 自动登记)、
|
|
116
129
|
加栏目(`section add`,不给模板就是空栏目全自定义)、删栏目都不用改代码。
|
|
117
130
|
模板在实例化时被**深拷贝**,此后各栏目独立演化;模板后来的新增用 `section sync` 补(只增不改不删,
|
|
118
131
|
有差异时会把「模板已改、栏目保留原值」的字段列出来提示)。
|
|
119
132
|
|
|
120
|
-
内置模板共 **
|
|
133
|
+
内置模板共 **9 个**——除 `demo` 与上面 6 个外还有 `platform`(容器平台:控制台链接 / 账号 / 密码 / 镜像)
|
|
121
134
|
与 `thesis`(毕业论文规范字段化),需要时 `section add <id> --template platform|thesis` 建。
|
|
122
135
|
|
|
123
136
|
## 三条核心不变量
|
|
@@ -150,6 +163,9 @@ CLI 与 API 同源,skill 驱动 agent**。落到具体功能上:
|
|
|
150
163
|
| `nx-sk routes [--module M] [--http "POST /api/entries"]` | 命令 ↔ 路由双向对照 |
|
|
151
164
|
| `nx-sk section list \| get \| add \| update \| remove` | 栏目 CRUD |
|
|
152
165
|
| `nx-sk section dump <id> [--mask]` | **一个栏目的全部信息**:字段台账 + 全部条目 + 每个条目的未填清单 |
|
|
166
|
+
| `nx-sk section tree` | **栏目树**:每个栏目 + 它的条目索引(名称 / 完整度)——面板「栏目管理」一次拿齐,不必逐个 dump |
|
|
167
|
+
| `nx-sk section remove-many <ids> [--force]` | 批量删栏目(等同删文件夹,连带条目;有非空栏目必须 `--force`)。找不到的跳过并报告 |
|
|
168
|
+
| `nx-sk entry remove-many <ids>` | 批量删条目(ids 逗号分隔);找不到的跳过并报告,一个都找不到才报错 |
|
|
153
169
|
| `nx-sk section templates` | 内置模板(job / secret / projects / internships / campus / deploy / platform / thesis) |
|
|
154
170
|
| `nx-sk section sync <id> [--dry-run]` | 按模板**补齐**本栏目缺的分组与字段(只增不改不删)——模板演进后让老栏目追上 |
|
|
155
171
|
| `nx-sk entry list \| get \| add \| update \| remove` | 条目 CRUD(PATCH 语义) |
|
|
@@ -293,6 +309,70 @@ nx-sk setting set --set 'navGroups=[]' # 清空 = 全部栏目恢复平铺
|
|
|
293
309
|
|
|
294
310
|
分组只是**显示配置**(存在 `settings.navGroups`):不动栏目与条目的数据,删掉栏目时头部自动略过。
|
|
295
311
|
|
|
312
|
+
### 表格字段(table):结构在**数据里**的表单表格
|
|
313
|
+
|
|
314
|
+
`entrylist`(结构清单)是「变长的几列文本」。**表格字段**再往前一步:每格有类型
|
|
315
|
+
(勾选 / 下拉 / 数字 / 日期),还能有**计算列**和**表尾统计**——但**列定义、行、公式、
|
|
316
|
+
统计配置全在条目数据里**,不在栏目字典里。所以「这条想多一列」不必改 schema,
|
|
317
|
+
也不会影响同一栏目下的其它条目。
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
# 建字段:只给类型 + **初始列**(新建条目时表格长什么样;初始列也可以不写)
|
|
321
|
+
nx-sk section update mysec --add-field '{"key":"tasks","label":"任务表","type":"table","group":"main","columns":[
|
|
322
|
+
{"key":"task","label":"任务"},
|
|
323
|
+
{"key":"done","label":"已办","type":"bool"},
|
|
324
|
+
{"key":"hours","label":"工时","type":"number","total":"sum"},
|
|
325
|
+
{"key":"rate","label":"单价","type":"number","total":"none"},
|
|
326
|
+
{"key":"cost","label":"费用","formula":"hours * rate","unit":"元"}]}'
|
|
327
|
+
|
|
328
|
+
# 写入:值是一份自描述文档(列 + 行)。计算列不用给值——给了也不落盘,读的时候现算
|
|
329
|
+
nx-sk entry update 周报 --data '{"任务表":{"columns":[…],"rows":[
|
|
330
|
+
{"task":"写文档","done":true,"hours":2,"rate":100},
|
|
331
|
+
{"task":"评审","done":false,"hours":3,"rate":100}]}}'
|
|
332
|
+
|
|
333
|
+
# 只看这张表:表头 + 数据 + 合计 + 公式报错(只读,现算)
|
|
334
|
+
nx-sk entry table 周报 --field 任务表
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
任务 已办 工时 单价 费用(算)
|
|
339
|
+
------ ---- ---- ---- --------
|
|
340
|
+
写文档 是 2 100 200 元
|
|
341
|
+
评审 否 3 100 300 元
|
|
342
|
+
合计 1/2 5 500 元
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
**公式就是 JS 表达式**(不发明语法),只包成 `return ( … )`,所以 `for` / `var` 这类语句写不进来:
|
|
346
|
+
|
|
347
|
+
| 想写什么 | 怎么写 |
|
|
348
|
+
| --- | --- |
|
|
349
|
+
| 同行计算 | `hours * rate` `工时 * 单价`(**列 key 与中文列名都能当变量**) |
|
|
350
|
+
| 取原值 / 整表 | `row.hours`(空格子是 null) `rows` / `表`(整张表) `i` 行号 `n` 行数 |
|
|
351
|
+
| 取一列 | `col("单价")` `sum(col("单价"))` |
|
|
352
|
+
| 聚合 | `sum / avg / min / max / count / countTrue / countFalse / distinct / median / first / last / join` |
|
|
353
|
+
| 数值 | `round / floor / ceil / abs / pct / ratio / clamp` 外加 `Math`、`Number`、`JSON`… |
|
|
354
|
+
| 判空 | `isBlank(row.hours)` `ifEmpty(x, 0)` `toNum(x)` |
|
|
355
|
+
|
|
356
|
+
- **计算列按声明顺序算**:只能引用排在它前面的列,天然不循环。算错会给出能照着改的话
|
|
357
|
+
(「公式里用了不存在的名字『qty』,可用的名字:a、b…」)。
|
|
358
|
+
- **空格子当 0 / false / ''**(`hours * rate` 不会因为空格子变 NaN);要判「到底填没填」用 `isBlank(row.x)`。
|
|
359
|
+
- **统计两层**:列上的 `total`(`sum|avg|min|max|count|countTrue|countFalse|distinct|median|none`,
|
|
360
|
+
不写就按类型默认:数字求和、勾选计是)决定表尾那一格;整表表达式写在数据的 `totals` 里
|
|
361
|
+
(`{"label":"完成率","expr":"pct(countTrue(col(\"done\")), n)","unit":"%"}`),`summary: false` 关掉表尾。
|
|
362
|
+
统计**不落盘**,每次读现算——不会出现「存下来的合计和现在的数据对不上」。
|
|
363
|
+
- 面板上直接**加行 / 加列**、改列类型与公式(「列设置」),改完就是这条数据的一部分。
|
|
364
|
+
敏感列(`sensitive: true`)与顶层敏感字段同一条边界:密文落盘、默认原文、`--mask` 打码。
|
|
365
|
+
- **写入即体检**:每条公式在保存前拿一行空值当探针跑一遍,只拦**与数据无关**的错
|
|
366
|
+
(语法错 / 列名解析不到 / 结果不是单值),除零这类「这条数据不巧」留到渲染时逐格报。
|
|
367
|
+
跑不起来就不保存 —— 定义阶段的错误停在定义阶段。
|
|
368
|
+
- **空与默认**:`--set 表=` / `[]` / `{}` 都能清空(有初始列时 `[]` 留下「列在、行空」的骨架);
|
|
369
|
+
列可以带 `default`(新增行时的初值,`0` / `false` 都算数);数字列默认求和、勾选列默认计是。
|
|
370
|
+
- 求值作用域用 `with` + Proxy 封死:`window` / `document` / `process` / `fetch` 都取不到。
|
|
371
|
+
这不是安全沙箱(公式是数据所有者自己写的),而是**把写错的边界前移**。
|
|
372
|
+
|
|
373
|
+
形状、列的每个键、公式内建表、错误对照表:`nx-sk skill get nx-sk 15-special-fields`
|
|
374
|
+
(同一篇也讲了 `entrylist` / `md` / `file` / `source` / `secret` 这几种「值不是标量」的字段)。
|
|
375
|
+
|
|
296
376
|
### 全局导出 / 导入(多栏目)
|
|
297
377
|
|
|
298
378
|
**项目里只有一个导出导入模块,没有独立的「备份」模块。** 导出的包就是唯一回退手段:
|
package/assets/nx-sk/SKILL.md
CHANGED
|
@@ -7,20 +7,25 @@ description: 本机个人资源管理器——栏目化存储个人信息、场
|
|
|
7
7
|
一句话:**把「你的信息」按栏目存起来,凭据就放在它该在的地方,CLI 与 Web 面板是同一套业务。**
|
|
8
8
|
|
|
9
9
|
数据落在 `~/nx-sk/`(可用环境变量 `NX_SK_HOME` / `NX_SK_STORE` 覆盖),**永远在仓库之外**。
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
21
|
-
|
|
10
|
+
首次运行**只播种一个「字段样例」栏目**(`demo`,连一条示例条目一起)——
|
|
11
|
+
把「能存什么、能算到哪」直接摆出来:标量字段(文本/数字/是否/下拉/日期/标签)、
|
|
12
|
+
组合字段(**结构清单** + **表格**:列在数据里、带计算列与表尾统计)、富内容(**图文** / **附件** / **密钥**),
|
|
13
|
+
外加每个栏目自带的「原始资料」袋。看完或改完可以整栏删掉。
|
|
14
|
+
|
|
15
|
+
**不再播种**求职 / 密钥 / 项目那一堆场景栏目——它们仍是模板,用时建:
|
|
16
|
+
|
|
17
|
+
| 模板 | id | 内容 |
|
|
18
|
+
| --------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| 求职 | `job` | 求职用的个人信息档案(姓名/学历/联系方式/求职意向/简历头像成绩单附件…约 80 个字段) |
|
|
20
|
+
| 项目经历 | `projects` | 一个项目一个条目:名称 / 角色 / 时间 / 技术栈 / 职责与亮点 |
|
|
21
|
+
| 实习/工作经历 | `internships` | 一段经历一个条目:公司 / 岗位 / 时间 / 职责 |
|
|
22
|
+
| 校内职务/实践 | `campus` | 一条职务或实践一个条目 |
|
|
23
|
+
| 密钥 | `secret` | **一张 KV 表**(`kv: true`):一行一个键值对。**只放跨场景通用的 key**;播种不带它,第一次 `key set` 会自动补建 |
|
|
24
|
+
| 部署配置 | `deploy` | **一份配置文件一个条目**(Dockerfile / compose / k8s 清单):正文即文件原文 + 放哪 + 哪些值要替换 + **这个场景自己的凭据清单** + 何时用。详见 [[50-deploy]] |
|
|
25
|
+
|
|
26
|
+
**这些只是模板,不是固定清单**:栏目可以新建(`section add`,不给模板就是空栏目全自定义)、
|
|
22
27
|
可以加/删字段(`section update --add-field`,或直接 `entry update --set 任意键=值` 自动登记)、
|
|
23
|
-
也可以删掉整个栏目。内置模板共 **
|
|
28
|
+
也可以删掉整个栏目。内置模板共 **9 个**——除 `demo` 与上面 6 个外还有
|
|
24
29
|
`platform`(容器平台:控制台链接 / 账号 / 密码 / 镜像,一个平台一个条目)与
|
|
25
30
|
`thesis`(毕业论文规范字段化),`section templates` 列出它们;
|
|
26
31
|
模板在栏目实例化时被**深拷贝**,此后各自独立演化,
|
|
@@ -219,7 +224,8 @@ nx-sk file get f_bbb # 反查「被引用:求职
|
|
|
219
224
|
|
|
220
225
|
- **只认附件 id 与 http(s) 外链**:本地路径、`file://`、相对路径都渲染不出来(也会传不走)。
|
|
221
226
|
- 图片会**自动算作已引用**:`nx-sk file list` 里它们的 `usedBy` 指向引用它的栏目 / 条目 / 字段,
|
|
222
|
-
|
|
227
|
+
不会因为「只出现在正文里」被列进「未引用」。`file` 字段挂的与**资料袋里的**同理——
|
|
228
|
+
三种正式引用(file 字段 / md 正文 / source 袋)判同一套,cleanup 只删三种都没有的真孤儿。
|
|
223
229
|
- 面板里支持 Ctrl+V、拖拽、附件库插图;插入光标处即时预览。
|
|
224
230
|
- 可勾选待办:`- [ ] 步骤` 在预览里就是勾选框,点一下写回正文。
|
|
225
231
|
|
|
@@ -237,6 +243,24 @@ nx-sk entry update 张三 --data '{"账号清单":[{"链接":"https://…","密
|
|
|
237
243
|
|
|
238
244
|
面板渲染成密集迷你表(直接增删行);`entry get` 里清单一行一条、带列标签。口径见 [[10-sections-entries]]。
|
|
239
245
|
|
|
246
|
+
表格字段(`type: 'table'`)——**结构写在数据里**的表单表格:列有类型(勾选 / 下拉 / 数字 / 日期),
|
|
247
|
+
可带**计算列**(JS 表达式)与**表尾统计**。列、行、公式、统计配置全在条目值里
|
|
248
|
+
(`{v, columns, rows, totals?, summary?}`),字段定义里的 `columns` 只是「新建时的初始列」——
|
|
249
|
+
所以「这一条想多一列」不必改 schema,面板「列设置」里加就行。
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
# 建字段:只给类型(初始列可省,省了就在数据里定)
|
|
253
|
+
nx-sk section update <栏目> --add-field '{"key":"tasks","label":"任务表","type":"table"}'
|
|
254
|
+
# 写入:值 = 文档(列 + 行)。计算列不用给值(给了也不落盘,读时现算)
|
|
255
|
+
nx-sk entry update 周报 --data '{"任务表":{"columns":[{"key":"task","label":"任务"},{"key":"hours","label":"工时","type":"number"},{"key":"rate","label":"单价","type":"number"},{"key":"cost","label":"费用","formula":"hours*rate"}],"rows":[{"task":"写文档","hours":2,"rate":100}]}}'
|
|
256
|
+
# 看现值(表头 + 数据 + 合计 + 公式报错),只读
|
|
257
|
+
nx-sk entry table 周报 --field 任务表
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
写入即体检:公式的**语法 / 列名 / 是否单值**在保存前就校验,跑不起来不许存;
|
|
261
|
+
空值(`--set 表=`、`[]`、`{}`)与默认值都有明确语义。形状、公式作用域、统计口径、
|
|
262
|
+
错误对照表见 [[15-special-fields]]。
|
|
263
|
+
|
|
240
264
|
原始资料袋(`type: 'source'`)——**每个栏目都自带一个**的「乱入区」。值 = 一组资料条目
|
|
241
265
|
(`{id, kind, name, text|fileId|url, addedAt, note, mapped}`;kind = text / file / url)。
|
|
242
266
|
杂乱资料(邮件、截图、PDF 摘录、手抄的表)先**原样**丢进袋里,之后由 agent 或人
|
|
@@ -257,6 +281,29 @@ nx-sk source ensure # 给老栏目补上这个字段(模板
|
|
|
257
281
|
三条纪律:**原文不改写**、**不确定就留空**、**敏感内容不进袋**(袋是明文的;
|
|
258
282
|
密码走场景栏目的密文字段,不进袋)。
|
|
259
283
|
|
|
284
|
+
### 来源是文件:先挂原件,再写字段(溯源 SOP)
|
|
285
|
+
|
|
286
|
+
**「保存这个文件里的 xx 信息」——第一步不是抄内容,是把原件收进库、挂到条目上。**
|
|
287
|
+
信息会过时,但「这条字段值是从哪份原件来的」必须永远能反查回去——这是把 nx-sk
|
|
288
|
+
当可信源用的前提。顺序反了(先抄字段、原件随手一放),原件一被移动或删除,
|
|
289
|
+
字段就成了无源之水,错了都不知道该拿什么对。
|
|
290
|
+
|
|
291
|
+
| 情形 | 落点 | 动作 |
|
|
292
|
+
| --- | --- | --- |
|
|
293
|
+
| 该条目有贴切的 `file` 字段(简历 → `resumeFile`、部署清单 → `deployYaml`…) | `file` 字段 | `nx-sk file add --path <文件>` 拿 id → `entry update --set <字段>=<id>` |
|
|
294
|
+
| 只确定条目、字段不好区分 / 以后再整理 | `source` 袋 | `nx-sk source add <条目> --file <路径>` —— 复制进附件库、原样入袋,可信源的输入口本来就是干这个的 |
|
|
295
|
+
| 连条目都没定 | 先问,或建占位条目再入袋 | 别让原件只在对话里漂着——丢一次就真丢了 |
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
nx-sk source add 张三 --file "D:\扫描\成绩单.pdf" --name "教务处成绩单" # ① 原件进库、入袋
|
|
299
|
+
nx-sk entry update 张三 --set 成绩单=f_xxx # ② 提取信息写进字段(栏目有该字段时)
|
|
300
|
+
nx-sk source update 张三 --id s_xxx --mapped transcript # ③ 留痕:这条已整理到哪个字段
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
挂好的原件受三重保护:**cleanup 不会删**(袋里的文件算「已引用」)、**导出随包走**
|
|
304
|
+
(transfer 认袋里的引用)、`file get` 能反查「被哪个栏目/条目/字段引用」。
|
|
305
|
+
绕过这一步直接抄字段,这三重保护就都不存在。详细流程见 [[40-files]]。
|
|
306
|
+
|
|
260
307
|
**把袋子里的东西整理成字段**(agent 侧)有配套 skill:
|
|
261
308
|
|
|
262
309
|
```bash
|
|
@@ -298,6 +345,7 @@ nx-sk setting set --set 'navGroups=[]' # 清空 = 全部栏目恢复平铺
|
|
|
298
345
|
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
299
346
|
| `00-design` | 想搞懂**心智模型**时——栏目=结构、条目=数据、内置字段是什么、动态栏目 + 动态条目怎么用、四个聚合点在哪儿、密文边界,以及**东西该往哪儿放** |
|
|
300
347
|
| `10-sections-entries` | **动手填/改信息时必读**——栏目与条目的完整命令、AI 补全个人信息的推荐流程、字段字典怎么扩、读命令与写命令的参数陷阱 |
|
|
348
|
+
| `15-special-fields` | **值不是标量的字段怎么读怎么写**——`table`(结构在数据里 / 公式 / 统计 / 写入即体检 / 空与默认)、`entrylist`、`md`、`file`、`source`、`secret` 的形状、规矩与常见错对照表 |
|
|
301
349
|
| `20-secrets` | 密文机制、密钥从哪来(环境变量 vs 本机密钥文件)、KV 表的语义、什么时候会解不开 |
|
|
302
350
|
| `30-credentials` | **做凭据自动化时读**——凭据归属哪个栏目、多组账号怎么建清单、跨栏目台账、把凭据渲染成 compose / k8s / .env 的完整流程与安全边界 |
|
|
303
351
|
| `40-files` | **传/换简历头像成绩单等二进制原件时读**——附件库台账、导入(默认移动)与还原、`file` 字段怎么和条目建立链接、附件中心为什么由栏目驱动、看不到上传字段怎么办 |
|
|
@@ -309,6 +357,7 @@ nx-sk setting set --set 'navGroups=[]' # 清空 = 全部栏目恢复平铺
|
|
|
309
357
|
```bash
|
|
310
358
|
nx-sk skill get nx-sk # SKILL.md 全文
|
|
311
359
|
nx-sk skill get nx-sk 10-sections-entries # 裸名 → references/10-sections-entries.md
|
|
360
|
+
nx-sk skill get nx-sk 15-special-fields # 表格 / 清单 / 图文 / 附件:值不是标量的字段
|
|
312
361
|
nx-sk skill get nx-sk 30-credentials # 凭据自动化:归属 / 台账 / 渲染配置
|
|
313
362
|
nx-sk skill get nx-sk 40-files # 附件库:导入 / 链接 / 还原
|
|
314
363
|
nx-sk skill get nx-sk 50-deploy # 部署配置:存 / 找 / 复用
|
|
@@ -321,7 +370,8 @@ nx-sk skill get nx-sk --json # 四元 JSON:{skillName, ref,
|
|
|
321
370
|
|
|
322
371
|
- 用户只是随口问一句、不需要落盘 —— 别动数据。
|
|
323
372
|
- 用户只是**要读一份 PDF 的内容**(问"这文档讲了啥")—— 直接读就行,别建栏目、
|
|
324
|
-
|
|
373
|
+
别上传附件。先问一句要不要沉淀。但用户说「**保存**这份文件里的 xx」时是反例:
|
|
374
|
+
先挂原件再写字段(见「来源是文件」一节),不能只抄内容。
|
|
325
375
|
- 用户给的是**扫描件**(无文字层)—— 先 OCR,别对着图片猜正文(容易编造内容)。
|
|
326
376
|
- 想找「面板上的 skill 页」—— 没有:**skill 只走 CLI**(`nx-sk skill install` / `nx-sk skill get`),
|
|
327
377
|
面板里不呈现它。
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
模板再变也不会偷偷改你的栏目。模板后来新增的字段用 `nx-sk section sync <栏目>` 补进来
|
|
34
34
|
(**只增不改不删**;面板上是「栏目 → 编辑 → 同步模板字段」)。
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
首次运行只**播种 1 个「字段样例」栏目**(demo,连示例条目一起:每种字段一格、表格带公式与统计),
|
|
37
|
+
其余模板(job / projects / … / platform / thesis)需要时自己建。
|
|
38
38
|
|
|
39
39
|
## 三、动态栏目 + 动态条目:任何东西都能存
|
|
40
40
|
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
| --- | --- | --- |
|
|
63
63
|
| 标量字段 | 一个值 | 文本 / 数字 / 日期 / 是否 / 多值标签 |
|
|
64
64
|
| **结构清单** `entrylist` | 一个条目挂**多组**结构(多组账号、多条链接) | 行数组,列在字段定义里声明;密码列标 `sensitive` 即密文落盘 |
|
|
65
|
-
| **原始资料袋** `source` | 还没整理的杂乱资料(邮件 / 截图 /
|
|
65
|
+
| **原始资料袋** `source` | 还没整理的杂乱资料(邮件 / 截图 / 摘录);**字段值的溯源锚点** | 一袋资料条目,**先乱入、后整理**;袋里的文件算正式引用(cleanup 不删、导出随包走) |
|
|
66
66
|
| **附件** `file` | 二进制原件(简历 / 头像 / 证书) | 附件 id 列表,原件在 `~/nx-sk/files/` |
|
|
67
67
|
|
|
68
68
|
「先乱入、后整理」是刻意留的:真实数据几乎不是一次填对的,没有这个袋子,
|
|
@@ -47,8 +47,9 @@ store.json(~/nx-sk/store.json 或 $NX_SK_STORE)
|
|
|
47
47
|
|
|
48
48
|
内置模板 8 个:`job`(求职 / 个人信息,约 80 字段 / 10 分组——含「附件资料」组:简历附件 / 头像图片 / 成绩单 / 证书扫描件)、`projects`(项目经历)、`internships`(实习/工作经历)、`campus`(校内职务/实践)、`secret`(密钥,**单字段 KV**——细节见 `20-secrets`)、`deploy`(部署配置:Dockerfile / compose / k8s 清单,**一份文件一个条目**,自带「凭据清单」——细节见 `50-deploy`)、`platform`(容器平台:控制台链接 / 账号 / 密码 / 镜像,一个平台一个条目)、`thesis`(毕业论文规范字段化)。三类经历栏目(projects / internships / campus)**一个项目 / 一段经历 = 一个条目**,角色、时间、技术栈都是独立字段——不要往 job 栏目里塞经历。
|
|
49
49
|
|
|
50
|
-
首次运行只**播种
|
|
51
|
-
|
|
50
|
+
首次运行只**播种 1 个**:`demo`(字段样例 / 能力边界——每种字段一格、连示例条目一起,见 `15-special-fields`)。
|
|
51
|
+
其余模板(job / projects / internships / campus / secret / deploy / platform / thesis)需要时用
|
|
52
|
+
`section add <id> --template <模板id>` 建;没有 KV 栏目时第一次 `key set` 也会自动补建 `secret`。
|
|
52
53
|
|
|
53
54
|
## 三、条目命令
|
|
54
55
|
|
|
@@ -133,7 +134,7 @@ nx-sk section update job --remove-field blog
|
|
|
133
134
|
nx-sk section update job --fields @fields.json
|
|
134
135
|
```
|
|
135
136
|
|
|
136
|
-
字段定义支持:`key`(字母开头)、`label`、`type`(`text|textarea|number|date|month|bool|select|tags|entrylist|source|secret|file|md`)、
|
|
137
|
+
字段定义支持:`key`(字母开头)、`label`、`type`(`text|textarea|number|date|month|bool|select|tags|entrylist|table|source|secret|file|md`)、
|
|
137
138
|
`group`、`hint`、`options`(候选项)、`sensitive`(true 则密文落盘)、`maxItems`(tags / file 上限)、
|
|
138
139
|
`fill`(填写策略,见下)。
|
|
139
140
|
|
|
@@ -165,6 +166,20 @@ nx-sk section update job --fields @fields.json
|
|
|
165
166
|
> 没登记过的键直接写行数组会**自动登记**成 entrylist 并从行推断列。`entry get` 里清单一行一条:
|
|
166
167
|
> `名称=主控台 · 链接=https://… · 账号=ops · 密码=…`(--mask 时密码列打码)。
|
|
167
168
|
|
|
169
|
+
> `type: 'table'` 是**表格字段**:`entrylist` 的进阶版 —— 每格有类型(勾选 / 下拉 / 数字 / 日期),
|
|
170
|
+
> 还能有**计算列**(JS 表达式)与**表尾统计**。最根本的差别是**结构归数据**:列定义、行、公式、
|
|
171
|
+
> 统计配置全部存在**条目值里**(`{v, columns, rows, totals?, summary?}`),字段定义里的 `columns`
|
|
172
|
+
> 只是「新建时的初始列」。所以「这一条想多一列」不必改 schema,也不影响同栏目其它条目。
|
|
173
|
+
>
|
|
174
|
+
> ```bash
|
|
175
|
+
> nx-sk section update mysec --add-field '{"key":"tasks","label":"任务表","type":"table"}'
|
|
176
|
+
> nx-sk entry update 周报 --data '{"任务表":{"columns":[…],"rows":[…]}}'
|
|
177
|
+
> nx-sk entry table 周报 --field 任务表 # 只看这张表:数据 + 合计 + 公式报错
|
|
178
|
+
> ```
|
|
179
|
+
>
|
|
180
|
+
> 形状、公式作用域与内建、统计两个轴、**写入即体检**(语法 / 列名 / 单值不通过就不保存)、
|
|
181
|
+
> 空值与默认值、常见错对照表 —— 全在 [[15-special-fields]],这里不重复一份(两份必然漂移)。
|
|
182
|
+
|
|
168
183
|
> `type: 'source'` 是**原始资料袋**:每个栏目都自带一个的「乱入区」。值 = 一组资料条目
|
|
169
184
|
> (`{id, kind, name, text|fileId|url, addedAt, note, mapped}`,kind = text/file/url)。
|
|
170
185
|
> 杂乱资料(邮件、截图、PDF 摘录、手抄的表)先**原样**丢进袋里,之后由 agent 或人
|