skill-bill 0.1.0 → 0.2.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.
Files changed (298) hide show
  1. package/SKILL.md +127 -0
  2. package/dist/.gen-inputs.json +14 -0
  3. package/dist/cli/cmd_read.js +133 -142
  4. package/dist/cli/cmd_read.js.map +1 -1
  5. package/dist/cli/registry.d.ts +15 -0
  6. package/dist/cli/registry.d.ts.map +1 -0
  7. package/dist/cli/registry.js +22 -0
  8. package/dist/cli/registry.js.map +1 -0
  9. package/dist/fetch/db.d.ts +4 -0
  10. package/dist/fetch/db.d.ts.map +1 -1
  11. package/dist/fetch/db.js +12 -0
  12. package/dist/fetch/db.js.map +1 -1
  13. package/dist/fetch/index.d.ts +1 -1
  14. package/dist/fetch/index.d.ts.map +1 -1
  15. package/dist/fetch/index.js +1 -1
  16. package/dist/fetch/index.js.map +1 -1
  17. package/dist/help/index.d.ts +1 -0
  18. package/dist/help/index.d.ts.map +1 -1
  19. package/dist/help/index.js +1 -0
  20. package/dist/help/index.js.map +1 -1
  21. package/dist/help/lookup.d.ts.map +1 -1
  22. package/dist/help/lookup.js +3 -2
  23. package/dist/help/lookup.js.map +1 -1
  24. package/dist/help/writeWire.d.ts +16 -0
  25. package/dist/help/writeWire.d.ts.map +1 -0
  26. package/dist/help/writeWire.js +109 -0
  27. package/dist/help/writeWire.js.map +1 -0
  28. package/dist/output.d.ts +21 -0
  29. package/dist/output.d.ts.map +1 -0
  30. package/dist/output.js +48 -0
  31. package/dist/output.js.map +1 -0
  32. package/dist/policy/category.d.ts +5 -0
  33. package/dist/policy/category.d.ts.map +1 -1
  34. package/dist/policy/category.js +9 -2
  35. package/dist/policy/category.js.map +1 -1
  36. package/dist/policy/index.d.ts +1 -1
  37. package/dist/policy/index.d.ts.map +1 -1
  38. package/dist/policy/index.js +1 -1
  39. package/dist/policy/index.js.map +1 -1
  40. package/dist/policy/record.d.ts +12 -0
  41. package/dist/policy/record.d.ts.map +1 -1
  42. package/dist/policy/record.js +27 -0
  43. package/dist/policy/record.js.map +1 -1
  44. package/dist/policy/wakewords.d.ts +4 -0
  45. package/dist/policy/wakewords.d.ts.map +1 -1
  46. package/dist/policy/wakewords.js +12 -7
  47. package/dist/policy/wakewords.js.map +1 -1
  48. package/dist/query/commands.d.ts +19 -0
  49. package/dist/query/commands.d.ts.map +1 -0
  50. package/dist/query/commands.js +40 -0
  51. package/dist/query/commands.js.map +1 -0
  52. package/dist/query/detail.d.ts +26 -0
  53. package/dist/query/detail.d.ts.map +1 -0
  54. package/dist/query/detail.js +115 -0
  55. package/dist/query/detail.js.map +1 -0
  56. package/dist/query/index.d.ts +13 -0
  57. package/dist/query/index.d.ts.map +1 -0
  58. package/dist/query/index.js +12 -0
  59. package/dist/query/index.js.map +1 -0
  60. package/dist/query/list.d.ts +78 -0
  61. package/dist/query/list.d.ts.map +1 -0
  62. package/dist/query/list.js +110 -0
  63. package/dist/query/list.js.map +1 -0
  64. package/dist/query/read.d.ts +21 -0
  65. package/dist/query/read.d.ts.map +1 -0
  66. package/dist/query/read.js +301 -0
  67. package/dist/query/read.js.map +1 -0
  68. package/dist/record/collect.d.ts +18 -0
  69. package/dist/record/collect.d.ts.map +1 -0
  70. package/dist/record/collect.js +15 -0
  71. package/dist/record/collect.js.map +1 -0
  72. package/dist/record/collectBody.d.ts +29 -0
  73. package/dist/record/collectBody.d.ts.map +1 -0
  74. package/dist/record/collectBody.js +196 -0
  75. package/dist/record/collectBody.js.map +1 -0
  76. package/dist/record/commands.d.ts +11 -0
  77. package/dist/record/commands.d.ts.map +1 -0
  78. package/dist/record/commands.js +22 -0
  79. package/dist/record/commands.js.map +1 -0
  80. package/dist/record/index.d.ts +14 -0
  81. package/dist/record/index.d.ts.map +1 -0
  82. package/dist/record/index.js +12 -0
  83. package/dist/record/index.js.map +1 -0
  84. package/dist/record/receipt.d.ts +16 -0
  85. package/dist/record/receipt.d.ts.map +1 -0
  86. package/dist/record/receipt.js +11 -0
  87. package/dist/record/receipt.js.map +1 -0
  88. package/dist/record/receiptBody.d.ts +5 -0
  89. package/dist/record/receiptBody.d.ts.map +1 -0
  90. package/dist/record/receiptBody.js +112 -0
  91. package/dist/record/receiptBody.js.map +1 -0
  92. package/dist/record/scene-batch.d.ts +3 -0
  93. package/dist/record/scene-batch.d.ts.map +1 -0
  94. package/dist/record/scene-batch.js +211 -0
  95. package/dist/record/scene-batch.js.map +1 -0
  96. package/dist/record/scene-borrow.d.ts +3 -0
  97. package/dist/record/scene-borrow.d.ts.map +1 -0
  98. package/dist/record/scene-borrow.js +285 -0
  99. package/dist/record/scene-borrow.js.map +1 -0
  100. package/dist/record/scene-collect.d.ts +3 -0
  101. package/dist/record/scene-collect.d.ts.map +1 -0
  102. package/dist/record/scene-collect.js +294 -0
  103. package/dist/record/scene-collect.js.map +1 -0
  104. package/dist/record/scene-expense.d.ts +3 -0
  105. package/dist/record/scene-expense.d.ts.map +1 -0
  106. package/dist/record/scene-expense.js +21 -0
  107. package/dist/record/scene-expense.js.map +1 -0
  108. package/dist/record/scene-income.d.ts +3 -0
  109. package/dist/record/scene-income.d.ts.map +1 -0
  110. package/dist/record/scene-income.js +219 -0
  111. package/dist/record/scene-income.js.map +1 -0
  112. package/dist/record/scene-installment.d.ts +3 -0
  113. package/dist/record/scene-installment.d.ts.map +1 -0
  114. package/dist/record/scene-installment.js +248 -0
  115. package/dist/record/scene-installment.js.map +1 -0
  116. package/dist/record/scene-lend.d.ts +3 -0
  117. package/dist/record/scene-lend.d.ts.map +1 -0
  118. package/dist/record/scene-lend.js +273 -0
  119. package/dist/record/scene-lend.js.map +1 -0
  120. package/dist/record/scene-photo.d.ts +3 -0
  121. package/dist/record/scene-photo.d.ts.map +1 -0
  122. package/dist/record/scene-photo.js +262 -0
  123. package/dist/record/scene-photo.js.map +1 -0
  124. package/dist/record/scene-plain.d.ts +3 -0
  125. package/dist/record/scene-plain.d.ts.map +1 -0
  126. package/dist/record/scene-plain.js +221 -0
  127. package/dist/record/scene-plain.js.map +1 -0
  128. package/dist/record/scene-refund.d.ts +3 -0
  129. package/dist/record/scene-refund.d.ts.map +1 -0
  130. package/dist/record/scene-refund.js +281 -0
  131. package/dist/record/scene-refund.js.map +1 -0
  132. package/dist/record/scene-reimburse-done.d.ts +3 -0
  133. package/dist/record/scene-reimburse-done.d.ts.map +1 -0
  134. package/dist/record/scene-reimburse-done.js +288 -0
  135. package/dist/record/scene-reimburse-done.js.map +1 -0
  136. package/dist/record/scene-reimburse.d.ts +3 -0
  137. package/dist/record/scene-reimburse.d.ts.map +1 -0
  138. package/dist/record/scene-reimburse.js +224 -0
  139. package/dist/record/scene-reimburse.js.map +1 -0
  140. package/dist/record/scene-repay.d.ts +3 -0
  141. package/dist/record/scene-repay.d.ts.map +1 -0
  142. package/dist/record/scene-repay.js +294 -0
  143. package/dist/record/scene-repay.js.map +1 -0
  144. package/dist/record/scene-restore.d.ts +3 -0
  145. package/dist/record/scene-restore.d.ts.map +1 -0
  146. package/dist/record/scene-restore.js +250 -0
  147. package/dist/record/scene-restore.js.map +1 -0
  148. package/dist/record/scene-undo.d.ts +3 -0
  149. package/dist/record/scene-undo.d.ts.map +1 -0
  150. package/dist/record/scene-undo.js +262 -0
  151. package/dist/record/scene-undo.js.map +1 -0
  152. package/dist/record/scene-update.d.ts +3 -0
  153. package/dist/record/scene-update.d.ts.map +1 -0
  154. package/dist/record/scene-update.js +249 -0
  155. package/dist/record/scene-update.js.map +1 -0
  156. package/dist/record/scene.d.ts +79 -0
  157. package/dist/record/scene.d.ts.map +1 -0
  158. package/dist/record/scene.js +39 -0
  159. package/dist/record/scene.js.map +1 -0
  160. package/dist/record/slots.d.ts +16 -0
  161. package/dist/record/slots.d.ts.map +1 -0
  162. package/dist/record/slots.js +72 -0
  163. package/dist/record/slots.js.map +1 -0
  164. package/dist/record/write.d.ts +9 -0
  165. package/dist/record/write.d.ts.map +1 -0
  166. package/dist/record/write.js +186 -0
  167. package/dist/record/write.js.map +1 -0
  168. package/dist/render/envelope.d.ts.map +1 -1
  169. package/dist/render/envelope.js +21 -8
  170. package/dist/render/envelope.js.map +1 -1
  171. package/dist/render/errors.d.ts +1 -1
  172. package/dist/render/errors.d.ts.map +1 -1
  173. package/dist/render/errors.js.map +1 -1
  174. package/dist/render/helpFile.d.ts +85 -0
  175. package/dist/render/helpFile.d.ts.map +1 -0
  176. package/dist/render/helpFile.js +110 -0
  177. package/dist/render/helpFile.js.map +1 -0
  178. package/dist/render/helpPaths.d.ts +19 -0
  179. package/dist/render/helpPaths.d.ts.map +1 -0
  180. package/dist/render/helpPaths.js +19 -0
  181. package/dist/render/helpPaths.js.map +1 -0
  182. package/dist/render/html.js +1 -1
  183. package/dist/render/html.js.map +1 -1
  184. package/dist/render/index.d.ts +5 -1
  185. package/dist/render/index.d.ts.map +1 -1
  186. package/dist/render/index.js +4 -1
  187. package/dist/render/index.js.map +1 -1
  188. package/dist/render/templates.js +1 -1
  189. package/dist/render/templates.js.map +1 -1
  190. package/dist/render/views.d.ts +0 -22
  191. package/dist/render/views.d.ts.map +1 -1
  192. package/dist/render/views.js +1 -16
  193. package/dist/render/views.js.map +1 -1
  194. package/dist/shared/blockedSlots.d.ts +39 -0
  195. package/dist/shared/blockedSlots.d.ts.map +1 -0
  196. package/dist/shared/blockedSlots.js +105 -0
  197. package/dist/shared/blockedSlots.js.map +1 -0
  198. package/dist/shared/candidatePick.d.ts +50 -0
  199. package/dist/shared/candidatePick.d.ts.map +1 -0
  200. package/dist/shared/candidatePick.js +115 -0
  201. package/dist/shared/candidatePick.js.map +1 -0
  202. package/dist/shared/collectFrame.d.ts +15 -0
  203. package/dist/shared/collectFrame.d.ts.map +1 -0
  204. package/dist/shared/collectFrame.js +34 -0
  205. package/dist/shared/collectFrame.js.map +1 -0
  206. package/dist/shared/commandSpec.d.ts +72 -0
  207. package/dist/shared/commandSpec.d.ts.map +1 -0
  208. package/dist/shared/commandSpec.js +2 -0
  209. package/dist/shared/commandSpec.js.map +1 -0
  210. package/dist/shared/copyArea.d.ts +51 -0
  211. package/dist/shared/copyArea.d.ts.map +1 -0
  212. package/dist/shared/copyArea.js +122 -0
  213. package/dist/shared/copyArea.js.map +1 -0
  214. package/dist/shared/diffTable.d.ts +26 -0
  215. package/dist/shared/diffTable.d.ts.map +1 -0
  216. package/dist/shared/diffTable.js +77 -0
  217. package/dist/shared/diffTable.js.map +1 -0
  218. package/dist/shared/docPage.d.ts +17 -0
  219. package/dist/shared/docPage.d.ts.map +1 -0
  220. package/dist/shared/docPage.js +111 -0
  221. package/dist/shared/docPage.js.map +1 -0
  222. package/dist/shared/duplicateNote.d.ts +40 -0
  223. package/dist/shared/duplicateNote.d.ts.map +1 -0
  224. package/dist/shared/duplicateNote.js +96 -0
  225. package/dist/shared/duplicateNote.js.map +1 -0
  226. package/dist/shared/emptyNote.d.ts +15 -0
  227. package/dist/shared/emptyNote.d.ts.map +1 -0
  228. package/dist/shared/emptyNote.js +27 -0
  229. package/dist/shared/emptyNote.js.map +1 -0
  230. package/dist/shared/errorReceipt.d.ts +21 -0
  231. package/dist/shared/errorReceipt.d.ts.map +1 -0
  232. package/dist/shared/errorReceipt.js +37 -0
  233. package/dist/shared/errorReceipt.js.map +1 -0
  234. package/dist/shared/flowSteps.d.ts +25 -0
  235. package/dist/shared/flowSteps.d.ts.map +1 -0
  236. package/dist/shared/flowSteps.js +49 -0
  237. package/dist/shared/flowSteps.js.map +1 -0
  238. package/dist/shared/installmentPreview.d.ts +23 -0
  239. package/dist/shared/installmentPreview.d.ts.map +1 -0
  240. package/dist/shared/installmentPreview.js +144 -0
  241. package/dist/shared/installmentPreview.js.map +1 -0
  242. package/dist/shared/outsideScan.d.ts +34 -0
  243. package/dist/shared/outsideScan.d.ts.map +1 -0
  244. package/dist/shared/outsideScan.js +116 -0
  245. package/dist/shared/outsideScan.js.map +1 -0
  246. package/dist/shared/pageIdentity.d.ts +30 -0
  247. package/dist/shared/pageIdentity.d.ts.map +1 -0
  248. package/dist/shared/pageIdentity.js +33 -0
  249. package/dist/shared/pageIdentity.js.map +1 -0
  250. package/dist/shared/pageShell.d.ts +24 -0
  251. package/dist/shared/pageShell.d.ts.map +1 -0
  252. package/dist/shared/pageShell.js +42 -0
  253. package/dist/shared/pageShell.js.map +1 -0
  254. package/dist/shared/photoEscape.d.ts +53 -0
  255. package/dist/shared/photoEscape.d.ts.map +1 -0
  256. package/dist/shared/photoEscape.js +139 -0
  257. package/dist/shared/photoEscape.js.map +1 -0
  258. package/dist/shared/prefillNote.d.ts +21 -0
  259. package/dist/shared/prefillNote.d.ts.map +1 -0
  260. package/dist/shared/prefillNote.js +78 -0
  261. package/dist/shared/prefillNote.js.map +1 -0
  262. package/dist/shared/receiptParts.d.ts +12 -0
  263. package/dist/shared/receiptParts.d.ts.map +1 -0
  264. package/dist/shared/receiptParts.js +38 -0
  265. package/dist/shared/receiptParts.js.map +1 -0
  266. package/dist/shared/recentPicks.d.ts +26 -0
  267. package/dist/shared/recentPicks.d.ts.map +1 -0
  268. package/dist/shared/recentPicks.js +41 -0
  269. package/dist/shared/recentPicks.js.map +1 -0
  270. package/dist/shared/recordPicker.d.ts +32 -0
  271. package/dist/shared/recordPicker.d.ts.map +1 -0
  272. package/dist/shared/recordPicker.js +201 -0
  273. package/dist/shared/recordPicker.js.map +1 -0
  274. package/dist/shared/rowEditorTable.d.ts +31 -0
  275. package/dist/shared/rowEditorTable.d.ts.map +1 -0
  276. package/dist/shared/rowEditorTable.js +103 -0
  277. package/dist/shared/rowEditorTable.js.map +1 -0
  278. package/dist/shared/summaryRow.d.ts +44 -0
  279. package/dist/shared/summaryRow.d.ts.map +1 -0
  280. package/dist/shared/summaryRow.js +82 -0
  281. package/dist/shared/summaryRow.js.map +1 -0
  282. package/dist/shared/typeBadge.d.ts +21 -0
  283. package/dist/shared/typeBadge.d.ts.map +1 -0
  284. package/dist/shared/typeBadge.js +68 -0
  285. package/dist/shared/typeBadge.js.map +1 -0
  286. package/dist/shared/userWording.d.ts +54 -0
  287. package/dist/shared/userWording.d.ts.map +1 -0
  288. package/dist/shared/userWording.js +131 -0
  289. package/dist/shared/userWording.js.map +1 -0
  290. package/dist/shared/writeParts.d.ts +62 -0
  291. package/dist/shared/writeParts.d.ts.map +1 -0
  292. package/dist/shared/writeParts.js +39 -0
  293. package/dist/shared/writeParts.js.map +1 -0
  294. package/dist/triggers/wake-assets.d.ts +37 -0
  295. package/dist/triggers/wake-assets.d.ts.map +1 -0
  296. package/dist/triggers/wake-assets.js +951 -0
  297. package/dist/triggers/wake-assets.js.map +1 -0
  298. package/package.json +10 -4
@@ -0,0 +1,27 @@
1
+ /** 空态(写入域每张页的空手那一格,**唯一定义地**):候选为空、无记录可改、三要素没给时给一句**下一步**。
2
+ *
3
+ * 谁在用(按实际写,别写名义调用点):
4
+ * ① `src/record/collect.ts`——过程型采集页:账户候选一个都没有时出一格(`collect.ts:211`,本件真调用点);
5
+ * ② **本票没有第二个调用点**:回执页的明细段恒有行,`src/record/receipt.ts` 不引本件(件头原来写它
6
+ * 「那一处还没有空手面」,那是名义调用点,按实际改掉)。
7
+ * 第二个消费者:`src/query/`(随兄弟图 #403 的查询域一起到位;撤销/恢复的候选为空也走同一件)。
8
+ * 本票实测:本包 `src/` 下真引用本件的只有 `collect.ts` 一处。
9
+ *
10
+ * 本件只做一件事:把 base 的 `renderEmptyBlock` 包一层,锁住**「必须给下一步」**这条口径——
11
+ * 只有 `text`(现在是什么都没有)没有 `next`(接下来怎么办)的空态,是让人干瞪眼的那种,本仓不出。
12
+ * 这一条是硬约定:`next` 为空即抛错,不静默降级成一句安慰话。
13
+ */
14
+ import { renderEmptyBlock } from 'base-paint/blocks';
15
+ /** 空态区块:一句「什么都没有」+ 一句「接下来怎么办」。 */
16
+ export function emptyNote(input) {
17
+ if (typeof input.next !== 'string' || input.next.trim() === '') {
18
+ throw new Error('emptyNote: next 不能为空(空态必须给一句下一步)');
19
+ }
20
+ return renderEmptyBlock({
21
+ ...(input.title === undefined ? {} : { title: input.title }),
22
+ text: input.text,
23
+ hint: input.next,
24
+ ...(input.actionHtml === undefined ? {} : { actionHtml: input.actionHtml }),
25
+ });
26
+ }
27
+ //# sourceMappingURL=emptyNote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emptyNote.js","sourceRoot":"","sources":["../../src/shared/emptyNote.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAcrD,kCAAkC;AAClC,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,gBAAgB,CAAC;QACtB,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;QAC5D,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;KAC5E,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ToastInput } from 'base-paint/blocks';
2
+ /** 错误回执的入参。 */
3
+ interface ErrorReceipt {
4
+ /** 区块小标题(缺省不写这一行)。 */
5
+ readonly title?: string;
6
+ /** 事由那一句(必填,非空)。 */
7
+ readonly message: string;
8
+ /** 出错后怎么重来(缺省「补齐后照这句跟助手说一遍」)。 */
9
+ readonly retryPrompt?: string;
10
+ /** 可复制的数据文本(给了才出「复制数据」按钮)。 */
11
+ readonly dataText?: string;
12
+ /** 可复制的日志文本(给了才出「复制日志」按钮)。 */
13
+ readonly logText?: string;
14
+ /** 同时给一条提示条(与错误回执同容器;两样至少给一样)。 */
15
+ readonly toast?: ToastInput;
16
+ }
17
+ /** 错误回执:一段错误回执(可选加一条提示条),整块交回调用方拼进页面。
18
+ * **只在共用位内部用**:对共用位以外的件(`src/record/` 那两张页)它不出现在公开面。 */
19
+ export declare function errorReceipt(input: ErrorReceipt): string;
20
+ export {};
21
+ //# sourceMappingURL=errorReceipt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorReceipt.d.ts","sourceRoot":"","sources":["../../src/shared/errorReceipt.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAqB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEvE,eAAe;AACf,UAAU,YAAY;IACpB,sBAAsB;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iCAAiC;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,8BAA8B;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,8BAA8B;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,kCAAkC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;CAC7B;AAED;yDACyD;AACzD,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAexD"}
@@ -0,0 +1,37 @@
1
+ /** 错误回执(**本共用件的内部件**):异常/缺项时替换正文的那一段。
2
+ *
3
+ * 谁在用(指名,按实际写):
4
+ * ① `src/shared/blockedSlots.ts`——缺项阻断条顶上那句「写库已阻断」由本件出(同一次渲染只用一段回执);
5
+ * ② **后票的落点**(本票还没有这个调用点):JSON/状态异常、缺 id、参数不合法时「整页替换正文」那一支。
6
+ * 本件没有第三个消费者,也**不出本目录**:名字只在本共用位内部用(`errorReceipt` 不 export,
7
+ * 铁律五:接口小、里面厚)。以后要真有第二处消费,再按那时的调用点收进公开面。
8
+ *
9
+ * 本件只管口径,不重造控件:本体是 `base-paint/blocks` 的 `renderFeedbackBlock`(含 `renderErrorReceipt`/`renderToast`)。
10
+ * 锁住的那条口径:**消息句必填**(不许出一段没有事由的红块),`retryPrompt` 缺省写「补齐后照这句跟助手说一遍」——
11
+ * 本仓页面不写内联脚本,那段话是提示不是按钮动作。
12
+ *
13
+ * 整页替换这条**债务**(写在件头,不装作做过):`docs/skills/skill-bill/t407-页面块清单-16词.md` 第一节末列
14
+ * 把「JSON/状态异常、缺 id、参数不合法」也划给这个块。今天这些情形仍走 stderr + 非 0 退出码
15
+ * (`test/record-write.test.mjs`「id 有值但不是记录编号 → 仍走口径失败」那条钉着这条行为),
16
+ * 整页替换归后票;本票只把这一件冻好、并给它一个真落点(缺项阻断条)。
17
+ */
18
+ import { renderFeedbackBlock } from 'base-paint/blocks';
19
+ /** 错误回执:一段错误回执(可选加一条提示条),整块交回调用方拼进页面。
20
+ * **只在共用位内部用**:对共用位以外的件(`src/record/` 那两张页)它不出现在公开面。 */
21
+ export function errorReceipt(input) {
22
+ if (typeof input.message !== 'string' || input.message.trim() === '') {
23
+ throw new Error('errorReceipt: message 不能为空(不许出一段没有事由的红块)');
24
+ }
25
+ const error = {
26
+ message: input.message,
27
+ retryPrompt: input.retryPrompt === undefined || input.retryPrompt === '' ? '补齐后照这句跟助手说一遍' : input.retryPrompt,
28
+ ...(input.dataText === undefined ? {} : { dataText: input.dataText }),
29
+ ...(input.logText === undefined ? {} : { logText: input.logText }),
30
+ };
31
+ return renderFeedbackBlock({
32
+ ...(input.title === undefined ? {} : { title: input.title }),
33
+ error,
34
+ ...(input.toast === undefined ? {} : { toast: input.toast }),
35
+ });
36
+ }
37
+ //# sourceMappingURL=errorReceipt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorReceipt.js","sourceRoot":"","sources":["../../src/shared/errorReceipt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAmBxD;yDACyD;AACzD,MAAM,UAAU,YAAY,CAAC,KAAmB;IAC9C,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,KAAK,GAAsB;QAC/B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,WAAW,EAAE,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW;QAC7G,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;QACrE,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;KACnE,CAAC;IACF,OAAO,mBAAmB,CAAC;QACzB,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;QAC5D,KAAK;QACL,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;KAC7D,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { ParamFieldInput } from 'base-paint/blocks';
2
+ /** 一段里的一个字段(就是 base 的表单字段:`name`/`label`/`hint`/`required`/`value`/`options` 照给)。 */
3
+ export type FlowField = ParamFieldInput;
4
+ /** 一段:标题 + 一句说明 + 字段(或别处出的成品)。 */
5
+ export interface FlowStepInput {
6
+ /** 这一段叫什么(如「原记账」「退款(这一步)」「结果」)。 */
7
+ readonly title: string;
8
+ /** 这一段的一句说明(出在徽标下面那行小字里;不给就不出这一行)。 */
9
+ readonly note?: string;
10
+ /** 这一段的字段(本件出表单);不给/空数组=这一段没有要填的格。 */
11
+ readonly fields?: readonly FlowField[];
12
+ /** 这一段已由别的块出的成品 HTML(受信透传,不转义)。 */
13
+ readonly html?: string;
14
+ /** 这一段定没定(缺省按「没定」算,徽标走 `warn`)。 */
15
+ readonly done?: boolean;
16
+ /** 徽标上那句状态(缺省按 `done` 取「已定」/「未定」)。 */
17
+ readonly state?: string;
18
+ }
19
+ /** 三段(或几段)一整块的入参:**顺序即页面上从上到下的顺序**。 */
20
+ export interface FlowStepsInput {
21
+ readonly steps: readonly FlowStepInput[];
22
+ }
23
+ /** 流程三段式整块:逐段出「徽标 + 说明行 + 字段表单 + 成品」。空数组=空串。 */
24
+ export declare function flowSteps(input: FlowStepsInput): string;
25
+ //# sourceMappingURL=flowSteps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowSteps.d.ts","sourceRoot":"","sources":["../../src/shared/flowSteps.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,qFAAqF;AACrF,MAAM,MAAM,SAAS,GAAG,eAAe,CAAC;AAExC,kCAAkC;AAClC,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,sCAAsC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,mCAAmC;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,mCAAmC;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,sCAAsC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,uCAAuC;AACvC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;CAC1C;AAUD,gDAAgD;AAChD,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAavD"}
@@ -0,0 +1,49 @@
1
+ /** 流程三段式(缺口块之一,**唯一定义地**):一条过程型写入按「选原记录 → 填金额与对象 → 确认复制」
2
+ * 三段摆开,每段一枚状态徽标说这一段定没定(定了 `ok`、没定 `warn`)。
3
+ *
4
+ * 谁在用(两个用法,指名):
5
+ * ① **特殊收支族 6 条词的采集页**——`src/record/scene-refund.ts`、`scene-reimburse-done.ts`、
6
+ * `scene-lend.ts`、`scene-borrow.ts`、`scene-collect.ts`、`scene-repay.ts` 六件各叫一次;
7
+ * 三段的标题、字段与说明由各件自己给(这一段是本件与那六件的分界:件只管摆,节奏由调用方定)。
8
+ * ② 第二个用法:批量与修正族的「改记录」(缺 id 出候选 → 填新值 → 确认复制)与「撤销/恢复」
9
+ * (列候选 → 打标说明 → 确认复制)三形态同形,换的是三段标题与字段,本件一行不动。
10
+ *
11
+ * 入参是**普通数据**:三段标题 + 每段字段(`FlowField` 与 base 的 `ParamFieldInput` 同形)。
12
+ * 一段的正文两种给法:给 `fields`=本件出表单;给 `html`=那一段已由别的块出的成品(受信透传,
13
+ * 例如第一段直接用候选单选出的记录列表)。两种都给就两样都出,按「表单在前、成品在后」摆。
14
+ *
15
+ * 一件不自造:状态徽标走 base 的 `renderStatusBadge`、字段表单走 `renderParamForm`、
16
+ * 一句口径走 `renderCaliberLine`;件内不写 CSS、不写脚本、不设颜色。
17
+ *
18
+ * 空集口径:`steps` 空数组=不出这一块(与 base「没内容就不留空块」同口径,返回空串);
19
+ * 一段既没字段也没成品又没说明=那一段只剩一枚徽标,出得来、不抛错(三段骨架本身就是要看的东西)。
20
+ */
21
+ import { renderStatusBadge } from 'base-paint';
22
+ import { renderCaliberLine, renderParamForm } from 'base-paint/blocks';
23
+ /** 一段的徽标文字:段号 + 标题 + 这一段的现状。
24
+ * 本轮整改:段号与标题之间那个 `·` 换全角空格——徽标是版式位,行内不再拿 `·` 当版式
25
+ * (`docs/skills/skill-bill/t407-机审读数.md` 第三节:`.ilife-status-badge` 上不许再出现 `·`)。 */
26
+ function stepText(no, step) {
27
+ const state = step.state ?? (step.done === true ? '已定' : '未定');
28
+ return '第 ' + no + ' 段 ' + step.title + ':' + state;
29
+ }
30
+ /** 流程三段式整块:逐段出「徽标 + 说明行 + 字段表单 + 成品」。空数组=空串。 */
31
+ export function flowSteps(input) {
32
+ if (!Array.isArray(input.steps) || input.steps.length === 0)
33
+ return '';
34
+ return input.steps.map((step, i) => {
35
+ const fields = step.fields ?? [];
36
+ const parts = [renderStatusBadge({
37
+ status: step.done === true ? 'ok' : 'warn',
38
+ text: stepText(i + 1, step),
39
+ })];
40
+ if (step.note !== undefined && step.note !== '')
41
+ parts.push(renderCaliberLine(step.note));
42
+ if (fields.length > 0)
43
+ parts.push(renderParamForm({ fields }));
44
+ if (step.html !== undefined && step.html !== '')
45
+ parts.push(step.html);
46
+ return parts.join('');
47
+ }).join('');
48
+ }
49
+ //# sourceMappingURL=flowSteps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowSteps.js","sourceRoot":"","sources":["../../src/shared/flowSteps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA2BvE;;oFAEoF;AACpF,SAAS,QAAQ,CAAC,EAAU,EAAE,IAAmB;IAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC/D,OAAO,IAAI,GAAG,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,GAAG,GAAG,KAAK,CAAC;AACtD,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACvE,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;QACjC,MAAM,KAAK,GAAa,CAAC,iBAAiB,CAAC;gBACzC,MAAM,EAAE,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;gBAC1C,IAAI,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;aAC5B,CAAC,CAAC,CAAC;QACJ,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1F,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QAC/D,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvE,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
@@ -0,0 +1,23 @@
1
+ /** 一期:第几期 + 这一期多少钱 + 哪一天。 */
2
+ export interface InstallmentShare {
3
+ /** 第几期(从 1 数起)。 */
4
+ readonly no: number;
5
+ /** 这一期的金额(元,两位小数以内)。 */
6
+ readonly amount: number;
7
+ /** 这一期的日期(`YYYY-MM-DD`)。 */
8
+ readonly date: string;
9
+ }
10
+ /** 分摊的入参:总价 + 期数 + 首期日(三个都必给,格式从宽、解析从严)。 */
11
+ export interface InstallmentInput {
12
+ /** 总价(元):数字或数字串。 */
13
+ readonly total: string | number;
14
+ /** 期数:正整数(数字或数字串)。 */
15
+ readonly periods: string | number;
16
+ /** 首期日(`YYYY-MM-DD`)。 */
17
+ readonly startDate: string;
18
+ }
19
+ /** 分摊:逐期金额 + 日期(纯函数)。**合计逐分等于总价**——算完当场核一遍,不等距就抛错。 */
20
+ export declare function installmentShares(input: InstallmentInput): readonly InstallmentShare[];
21
+ /** 分摊预览整块:说明行 + 表(>24 期只显前 12 期)+ 其余期数的折叠区。 */
22
+ export declare function installmentPreview(input: InstallmentInput): string;
23
+ //# sourceMappingURL=installmentPreview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installmentPreview.d.ts","sourceRoot":"","sources":["../../src/shared/installmentPreview.ts"],"names":[],"mappings":"AAqBA,6BAA6B;AAC7B,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,4CAA4C;AAC5C,MAAM,WAAW,gBAAgB;IAC/B,oBAAoB;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,sBAAsB;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,yBAAyB;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AA6DD,sDAAsD;AACtD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,SAAS,gBAAgB,EAAE,CAgBtF;AA8BD,+CAA+C;AAC/C,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAqBlE"}
@@ -0,0 +1,144 @@
1
+ /** 分摊预览表(缺口块之一,**唯一定义地**):一笔总价摊成 N 期,逐期列「每期金额 + 日期」,合计逐分等于总价。
2
+ *
3
+ * 谁在用(两个用法,指名):
4
+ * ① **记分期**(`src/record/scene-installment.ts`)的采集页与回执页两处——同一组入参算两遍,算出来的表一致;
5
+ * ② 第二个用法:批量与修正族的「改记录」改总价那一支(改完重算同一张表),本件一行不动。
6
+ *
7
+ * 两半分明:**算**的是纯函数 `installmentShares`(无页面、无颜色、可单独核数);
8
+ * **摆**的是 `installmentPreview`(只走 base 现成组件:`renderDataTable`/`renderDisclosure`/`renderCaliberLine`)。
9
+ *
10
+ * 口径(本件唯一,改一处就是改全部):
11
+ * ① 每期=总价 ÷ 期数,四舍五入到分;
12
+ * ② **尾差对齐到最后一期**(末期=总价 − 每期 × (期数 − 1)),故合计**逐分等于总价**;
13
+ * ③ 日期=首期日之后每月同日,该月没有这一天就回退到该月最后一天(如 1 月 31 日的下一个月=2 月末)。
14
+ * 第②条与老侧不同:老侧把差额补在**首期**(`scripts/render_write.py` 的 `compute_installments`),本仓按施工图
15
+ * `docs/skills/skill-bill/t407-页面块清单-16词.md` 第二节「记分期」那一行改到末期。
16
+ *
17
+ * **先校验再算**:总价解析不出、期数不是正整数、首期日不是有效日期,一律当场抛错——不静默当空、
18
+ * 不拿 `NaN` 往下走(老侧那段裸转数字先崩,本件不照抄那一处)。
19
+ */
20
+ import { renderCaliberLine, renderDataTable, renderDisclosure } from 'base-paint/blocks';
21
+ /** 数字串的那个样子(只有整段都是数字才算,`'12abc'`/`''` 一律不算)。 */
22
+ const NUMERIC = /^-?\d+(\.\d+)?$/;
23
+ /** 日期串的那个样子(`YYYY-MM-DD`,真不真有这一天另算)。 */
24
+ const DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
25
+ /** 期数上限:再多也不许一次摊(摊到 600 期之外没有对账的意义)。 */
26
+ const PERIODS_MAX = 600;
27
+ /** 总价 → 分。解析不出、不是正数一律抛错(**先校验再算**的第一处)。 */
28
+ function centsOf(raw) {
29
+ const s = typeof raw === 'number' ? String(raw) : (typeof raw === 'string' ? raw.trim() : '');
30
+ if (s === '')
31
+ throw new Error('installmentPreview:总额没给(这一格要一个数)');
32
+ if (!NUMERIC.test(s))
33
+ throw new Error('installmentPreview:总额解析失败——「' + s + '」不是数字');
34
+ const cents = Math.round(Number(s) * 100);
35
+ if (!Number.isFinite(cents) || cents <= 0) {
36
+ throw new Error('installmentPreview:总额要大于 0(摊的是总价,负数不摊)');
37
+ }
38
+ return cents;
39
+ }
40
+ /** 期数 → 正整数。非正整数/超上限一律抛错(**先校验再算**的第二处)。 */
41
+ function periodsOf(raw) {
42
+ const s = typeof raw === 'number' ? String(raw) : (typeof raw === 'string' ? raw.trim() : '');
43
+ if (s === '')
44
+ throw new Error('installmentPreview:期数没给(这一格要一个正整数)');
45
+ if (!/^\d+$/.test(s))
46
+ throw new Error('installmentPreview:期数解析失败——「' + s + '」不是正整数');
47
+ const n = Number(s);
48
+ if (n < 1)
49
+ throw new Error('installmentPreview:期数要大于 0');
50
+ if (n > PERIODS_MAX)
51
+ throw new Error('installmentPreview:期数最多 ' + PERIODS_MAX + ' 期,给的是 ' + n);
52
+ return n;
53
+ }
54
+ /** 首期日 → 年月日。格式不对或日历上没有这一天一律抛错(**先校验再算**的第三处)。 */
55
+ function ymdOf(raw) {
56
+ const s = typeof raw === 'string' ? raw.trim() : '';
57
+ const m = DATE.exec(s);
58
+ if (m === null)
59
+ throw new Error('installmentPreview:首期日解析失败——「' + s + '」不是 YYYY-MM-DD');
60
+ const y = Number(m[1]);
61
+ const mo = Number(m[2]);
62
+ const d = Number(m[3]);
63
+ const daysInMonth = new Date(Date.UTC(y, mo, 0)).getUTCDate();
64
+ if (mo < 1 || mo > 12 || d < 1 || d > daysInMonth) {
65
+ throw new Error('installmentPreview:首期日「' + s + '」这一天不存在');
66
+ }
67
+ return { y, m: mo, d };
68
+ }
69
+ /** 两位补零。 */
70
+ function pad(n) {
71
+ return n < 10 ? '0' + n : String(n);
72
+ }
73
+ /** 首期日往后第 `k` 个月的同一天;该月没有这一天就回退到月末。 */
74
+ function shiftMonths(ymd, k) {
75
+ const months = ymd.y * 12 + (ymd.m - 1) + k;
76
+ const y = Math.floor(months / 12);
77
+ const m = (months % 12) + 1;
78
+ const daysInMonth = new Date(Date.UTC(y, m, 0)).getUTCDate();
79
+ return y + '-' + pad(m) + '-' + pad(Math.min(ymd.d, daysInMonth));
80
+ }
81
+ /** 分摊:逐期金额 + 日期(纯函数)。**合计逐分等于总价**——算完当场核一遍,不等距就抛错。 */
82
+ export function installmentShares(input) {
83
+ const cents = centsOf(input.total);
84
+ const periods = periodsOf(input.periods);
85
+ const ymd = ymdOf(input.startDate);
86
+ const each = Math.floor(cents / periods);
87
+ const shares = [];
88
+ for (let i = 1; i <= periods; i += 1) {
89
+ // 尾差对齐到最后一期:前几期各拿整数分,剩下的一分不差全压在末期。
90
+ const amount = i === periods ? cents - each * (periods - 1) : each;
91
+ shares.push({ no: i, amount: amount / 100, date: shiftMonths(ymd, i - 1) });
92
+ }
93
+ const sum = shares.reduce((acc, s) => acc + Math.round(s.amount * 100), 0);
94
+ if (sum !== cents) {
95
+ throw new Error('installmentPreview:分摊合计 ' + (sum / 100).toFixed(2) + ' 与总价 ' + (cents / 100).toFixed(2) + ' 对不上');
96
+ }
97
+ return shares;
98
+ }
99
+ /** 一行的钱:两位小数,不补正号(分摊表里全是正数)。 */
100
+ function yuan(amount) {
101
+ return amount.toFixed(2);
102
+ }
103
+ /** 表体格的一行。 */
104
+ function rowOf(s) {
105
+ return { no: '第 ' + s.no + ' 期', amount: yuan(s.amount), date: s.date };
106
+ }
107
+ /** 分摊表(一页表体,列与行都由本件定)。 */
108
+ function shareTable(shares, caption) {
109
+ return renderDataTable({
110
+ columns: [
111
+ { key: 'no', label: '期数' },
112
+ { key: 'amount', label: '每期金额', align: 'right' },
113
+ { key: 'date', label: '日期' },
114
+ ],
115
+ rows: shares.map(rowOf),
116
+ caption,
117
+ });
118
+ }
119
+ /** 超过这个期数就折起来:只显前 `HEAD_PERIODS` 期,其余进折叠区(老侧 `installment_confirm.html` 同一处)。 */
120
+ const FOLD_OVER = 24;
121
+ /** 折起来之后前面留几期。 */
122
+ const HEAD_PERIODS = 12;
123
+ /** 分摊预览整块:说明行 + 表(>24 期只显前 12 期)+ 其余期数的折叠区。 */
124
+ export function installmentPreview(input) {
125
+ const shares = installmentShares(input);
126
+ const total = shares.reduce((acc, s) => acc + Math.round(s.amount * 100), 0) / 100;
127
+ const periods = shares.length;
128
+ const folded = periods > FOLD_OVER;
129
+ const head = folded ? shares.slice(0, HEAD_PERIODS) : shares;
130
+ const rest = folded ? shares.slice(HEAD_PERIODS) : [];
131
+ const parts = [renderCaliberLine('每期=总价 ÷ 期数,四舍五入到分。尾差对齐到最后一期(末期=总价 − 每期 × (期数 − 1)),'
132
+ + '故合计逐分等于总价:' + yuan(total) + '(' + periods + ' 期)。')];
133
+ parts.push(shareTable(head, folded
134
+ ? '分摊预览:共 ' + periods + ' 期,这里先显前 ' + HEAD_PERIODS + ' 期;合计 ' + yuan(total) + '(=总价)'
135
+ : '分摊预览:共 ' + periods + ' 期;合计 ' + yuan(total) + '(=总价)'));
136
+ if (rest.length > 0) {
137
+ parts.push(renderDisclosure({
138
+ title: '还有 ' + rest.length + ' 期(折叠在这里)',
139
+ contentHtml: shareTable(rest, '第 ' + (HEAD_PERIODS + 1) + ' 期到第 ' + periods + ' 期'),
140
+ }));
141
+ }
142
+ return parts.join('');
143
+ }
144
+ //# sourceMappingURL=installmentPreview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installmentPreview.js","sourceRoot":"","sources":["../../src/shared/installmentPreview.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /** 拍账单的图片数入参:本仓只说明「收到了几张」,不做上传控件(老侧也没有图片入口)。 */
2
+ export interface PhotoScale {
3
+ /** 已收到的图片张数(本次用户交上来的)。 */
4
+ readonly count: number;
5
+ /** 这些图现在在哪(如「助手那边/外部识别工具」):本仓不落图片,兜底的归档位由助手那边给。 */
6
+ readonly where: string;
7
+ }
8
+ /** 拍账单三要素(**唯一定义地**):金额/分类/时间;明示表与提示话术都引这张表。 */
9
+ export declare const ESCAPE_FIELDS: readonly {
10
+ readonly name: string;
11
+ readonly label: string;
12
+ readonly hint: string;
13
+ }[];
14
+ /** 已收到的图片数说明(拍账单必备块):**各占独立一块**,不与打标提示、来源提示共容器。 */
15
+ export declare function imageNote(scale: PhotoScale): string;
16
+ /** 外部识别通道那张明示卡:三要素逐条 + 每一步在谁那里办 + 缺了会怎样。
17
+ * 第 3 轮返工(上级追加的定点小修):原先四列里有一列「参数名」,把库列名(`amount`/`category`/`time`)
18
+ * 印到了可见正文上——全批 32 页里就这一处区外印了库列名。整列删掉:要素那一列写的就是中文名,
19
+ * 下一张表照旧交代每一步在谁那里办。命令原文仍只活在复制载荷区(`pre` 与 `data-t`),本件不碰。 */
20
+ export declare function escapeCard(input: {
21
+ readonly params: Record<string, unknown>;
22
+ }): string;
23
+ /** 外部识别通道那段可复制的话:说清「识别在本仓之外办完」,并给出补齐后照抄重跑的那条命令。
24
+ * 那条命令原文由 `photoEscape.ts` 的 `blockedPromptOf` 出(缺的值留尖括号占位符),本件不另写一份。 */
25
+ export declare function escapePrompt(input: {
26
+ readonly params: Record<string, unknown>;
27
+ readonly blocked: readonly {
28
+ readonly name: string;
29
+ readonly label: string;
30
+ readonly why: string;
31
+ }[];
32
+ readonly scale: PhotoScale;
33
+ }): string;
34
+ //# sourceMappingURL=outsideScan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outsideScan.d.ts","sourceRoot":"","sources":["../../src/shared/outsideScan.ts"],"names":[],"mappings":"AA8BA,gDAAgD;AAChD,MAAM,WAAW,UAAU;IACzB,0BAA0B;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,gDAAgD;AAChD,eAAO,MAAM,aAAa,EAAE,SAAS;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,EAIA,CAAC;AAEF,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAgBnD;AAED;;;6DAG6D;AAC7D,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C,GAAG,MAAM,CAmCT;AAED;0EAC0E;AAC1E,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrG,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC5B,GAAG,MAAM,CAoBT"}
@@ -0,0 +1,116 @@
1
+ /** 拍账单的「图片识别外置」通道(**唯一定义地**):这一条通道只做一件事——把「已收到几张图/
2
+ * 哪几个要素还缺/补齐后照抄哪条命令」讲清,并给成可复制的一段。
3
+
4
+ * 谁在用(唯一调用点,指名):
5
+ * `src/record/scene-photo.ts`——拍账单那件场景件的采集页取本件这五个名字;
6
+ * `ESCAPE_FIELDS` 另被它用来拼三要素填空那三格的槽位(`ESCAPE_SLOTS`)。
7
+ * **为什么另立成件、不搬进那件场景件**:搬进去只是把「一个件对外给的东西多于五个」从共用位挪到场景位,
8
+ * 形状超线没解决(派单点名的拆法就是这一句);本件自成一件事,搬出来之后两边各自数得清。
9
+
10
+ * 本件只吃普通数据、零跨目录引用(与同目录的 `photoEscape.ts` 同一形状):入参是「本次参数」「缺项表」
11
+ * 这类普通数据,**不引** `src/record/` 下的件,也不认 `CollectInput`/`ReceiptInput`。
12
+ * 可引的只有:`base-paint/blocks`(现成组件)、同目录共用件。
13
+
14
+ * 件名取自它的活:**图片识别在本仓之外办**(本仓不装识别引擎,也不做上传控件;老侧同样没有,
15
+ * 只有一行「已收到 N 张账单图片」)。
16
+
17
+ * 口径(三件事一处定义,别处不许再写第二份):
18
+ * - **拍账单的三个要素**:金额/分类/时间,名字出自施工图 `t407-页面块清单-16词.md` 第二节点名的
19
+ * 「文字三要素填空(金额/分类/时间)」那一行,只在本件的 `ESCAPE_FIELDS` 一处定义(明示表、提示话术两处都引它);
20
+ * - **图片识别在本仓之外办**:页上只说明「收图在哪、读图在哪」,不做上传控件;
21
+ * - **缺项即不出复制指令**:与代表页同口径,阻断判定与写库指令原文仍由 `src/shared/blockedSlots.ts`
22
+ * 与 `src/shared/photoEscape.ts` 的 `blockedPromptOf` 管,本件只把那段原文串进那段话里。
23
+
24
+ * 本件不自造任何页面骨架与样式:明示表走 `renderDataTable`,提示条走 `renderFeedbackBlock`。
25
+ */
26
+ import { renderDataTable, renderFeedbackBlock } from 'base-paint/blocks';
27
+ import { blockedPromptOf } from './photoEscape.js';
28
+ import { textOf } from './recentPicks.js';
29
+ /** 拍账单三要素(**唯一定义地**):金额/分类/时间;明示表与提示话术都引这张表。 */
30
+ export const ESCAPE_FIELDS = [
31
+ { name: 'amount', label: '金额', hint: '识别出来的金额照原样写:支出为负、收入为正,如 -12.5' },
32
+ { name: 'category', label: '分类', hint: '三级分类:L1/L2/L3,如 餐饮/外卖/午餐(L3 即名目)' },
33
+ { name: 'time', label: '时间', hint: '账单上的日期,如 2026-09-14 或 2026-09-14 12:00:00' },
34
+ ];
35
+ /** 已收到的图片数说明(拍账单必备块):**各占独立一块**,不与打标提示、来源提示共容器。 */
36
+ export function imageNote(scale) {
37
+ const n = Number.isFinite(scale.count) && scale.count > 0 ? Math.floor(scale.count) : 0;
38
+ const toast = {
39
+ msg: '已收到 ' + n + ' 张账单图片',
40
+ detail: n === 0
41
+ ? '本次一张图都没交上来:那就走三要素文字填空这条路,照样能记。'
42
+ : '图放在 ' + scale.where + ',本仓不存图也不读图;识别在外部办完,把三样要素填回来。',
43
+ icon: 'info',
44
+ badge: { text: '已收图片数', type: 'warn' },
45
+ lines: [
46
+ '收图这一步在哪:' + scale.where,
47
+ '读图这一步在哪:本仓之外(本仓不装识别引擎,也不做上传控件)',
48
+ ESCAPE_FIELDS.map((f) => f.label).join('/') + '三样要素:由外部识别结果或你手填,填回下面那张卡',
49
+ ],
50
+ };
51
+ return renderFeedbackBlock({ title: '已收图片数与识别分工(各占独立一块)', toast });
52
+ }
53
+ /** 外部识别通道那张明示卡:三要素逐条 + 每一步在谁那里办 + 缺了会怎样。
54
+ * 第 3 轮返工(上级追加的定点小修):原先四列里有一列「参数名」,把库列名(`amount`/`category`/`time`)
55
+ * 印到了可见正文上——全批 32 页里就这一处区外印了库列名。整列删掉:要素那一列写的就是中文名,
56
+ * 下一张表照旧交代每一步在谁那里办。命令原文仍只活在复制载荷区(`pre` 与 `data-t`),本件不碰。 */
57
+ export function escapeCard(input) {
58
+ const rows = ESCAPE_FIELDS.map((f) => ({
59
+ field: f.label,
60
+ 现在: textOf(input.params[f.name]) === '' ? '还没填' : textOf(input.params[f.name]),
61
+ 找谁: '外部识别结果(或用你眼睛看一眼账单)',
62
+ }));
63
+ const missing = ESCAPE_FIELDS.filter((f) => textOf(input.params[f.name]) === '');
64
+ return renderDataTable({
65
+ columns: [
66
+ { key: 'field', label: '要素' },
67
+ { key: '现在', label: '现在' },
68
+ { key: '找谁', label: '这一步谁办' },
69
+ ],
70
+ rows,
71
+ caption: '图片识别外置:三要素现在到了哪一步'
72
+ + (missing.length === 0
73
+ ? '(三样齐了,可以直接写库)'
74
+ : '(还缺 ' + missing.map((f) => f.label).join('、') + ',缺一样就不写库)'),
75
+ }) + renderDataTable({
76
+ columns: [
77
+ { key: 'step', label: '这一步' },
78
+ { key: 'who', label: '在哪办' },
79
+ { key: 'detail', label: '办成什么样' },
80
+ ],
81
+ rows: [
82
+ { step: '收图', who: '你交图的那一头', detail: '图上内容原样,本仓不裁剪不读取' },
83
+ {
84
+ step: '读图取三要素',
85
+ who: '本仓之外(外部识别工具/你手填)',
86
+ detail: ESCAPE_FIELDS.map((f) => f.label).join('/') + '三样文字',
87
+ },
88
+ { step: '落库', who: '这台手机上的记账技能', detail: '三样齐了才写;缺一样只出这一页,不写库' },
89
+ ],
90
+ caption: '每一步在谁那里办(识别不落在本仓)',
91
+ });
92
+ }
93
+ /** 外部识别通道那段可复制的话:说清「识别在本仓之外办完」,并给出补齐后照抄重跑的那条命令。
94
+ * 那条命令原文由 `photoEscape.ts` 的 `blockedPromptOf` 出(缺的值留尖括号占位符),本件不另写一份。 */
95
+ export function escapePrompt(input) {
96
+ const missing = ESCAPE_FIELDS.filter((f) => textOf(input.params[f.name]) === '');
97
+ const head = '拍账单:本仓不装识别引擎、也不做上传控件,图片识别在外部办(本仓之外)。'
98
+ + '已收到 ' + (input.scale.count > 0 ? input.scale.count : 0) + ' 张图;'
99
+ + (missing.length === 0
100
+ ? '三要素齐了,可以落库。'
101
+ : '还缺 ' + missing.map((f) => f.label).join('、') + ',缺一样不许写库、也不替你猜。');
102
+ const ask = '请在外部识别(或眼看)之后,把 ' + ESCAPE_FIELDS.map((f) => f.label).join('/')
103
+ + '三样写成参数,然后照抄下面这条命令重跑:\n'
104
+ + blockedPromptOf({
105
+ key: 'bill.record.add',
106
+ params: input.params,
107
+ blocked: input.blocked,
108
+ replaces: {
109
+ amount: '<外部识别出的金额:支出为负、收入为正>',
110
+ category: '<外部识别出的分类:L1/L2/L3>',
111
+ time: '<账单上的时间>',
112
+ },
113
+ }).command;
114
+ return head + '\n' + ask;
115
+ }
116
+ //# sourceMappingURL=outsideScan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outsideScan.js","sourceRoot":"","sources":["../../src/shared/outsideScan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /** 页面三个公共标识 + 场景名(**唯一定义地**):文档版本/技能名/页面标题/`sceneKeyOf`。
2
+ * 整页装配的调用方与复制日志都读它,别处只引用、不另写这几个字面量(同一件事实两处就会走散)。
3
+ *
4
+ * 谁在用(两个能力,指名):
5
+ * ① `src/record/`——写入域:结果型回执整页与过程型采集页的 envelope 三字段(其中 `key` 过 `sceneKeyOf`)、
6
+ * 复制日志版本、页标题前缀;`src/shared/writeParts.ts` 的 `writeSection` 取技能名做 `data-skill`;
7
+ * ② `src/query/`——查询域:通用查询列表页的同一批取值(envelope 三字段、复制日志版本、页标题前缀)。
8
+ * 两域的页面内置 envelope 都拿本件的 `sceneKeyOf` 把对外命令名收成场景名(`bill.record.today` → `record.today`),
9
+ * 公共层的日志场景标识再与技能名拼回整名。
10
+ *
11
+ * 为什么另立一件:这三个取值是「页面是谁」那件活,与回执事实、`<section>` 段不是同一件事——
12
+ * 混在 `./writeParts.ts` 里会把那份的对外名字顶过五个(铁律五)。
13
+ */
14
+ /** 文档版本(envelope 的 `version`,也是复制日志第 5 段后半)。 */
15
+ export declare const DOC_VERSION = "0.1.0";
16
+ /** 技能名(envelope 的 `skill`,也是 `<section>` 上 `data-skill` 的取值)。 */
17
+ export declare const DOC_SKILL = "bill";
18
+ /** 页面标题前缀(两种页各接一个后缀,如「·写库回执」)。 */
19
+ export declare const DOC_TITLE = "\u997C\u5E72\u8BB0\u8D26";
20
+ /** 页面内置 envelope 的 `key`(=**场景名**,技能内的本地名)。
21
+ *
22
+ * 为什么不是对外命令名:公共层的日志第 1 段(`scene`)由 envelope 派生,形如 `{skill}.{key}`
23
+ * (`packages/base-render/src/text.ts:296-298` 的 `sceneText`)——`skill` 已是 `bill`,
24
+ * 这里再写一条带 `bill.` 前缀的整名,日志就会印成 `bill.bill.record.add`(两处都重复一遍)。
25
+ * 本件按公共层的分工收口:**页面内置 envelope 的 key=本地场景名**(`bill.record.add` → `record.add`),
26
+ * `skill` + `key` 拼起来正好是对外命令名;`<section data-key>` **同写场景名**(R4 收口:`bill.` 只许出现在
27
+ * 复制载荷区,页面标记一律不带技能前缀),两处一个值,不再各写各的。
28
+ */
29
+ export declare function sceneKeyOf(key: string): string;
30
+ //# sourceMappingURL=pageIdentity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageIdentity.d.ts","sourceRoot":"","sources":["../../src/shared/pageIdentity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,gDAAgD;AAChD,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,iEAAiE;AACjE,eAAO,MAAM,SAAS,SAAS,CAAC;AAEhC,kCAAkC;AAClC,eAAO,MAAM,SAAS,6BAAS,CAAC;AAEhC;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG9C"}
@@ -0,0 +1,33 @@
1
+ /** 页面三个公共标识 + 场景名(**唯一定义地**):文档版本/技能名/页面标题/`sceneKeyOf`。
2
+ * 整页装配的调用方与复制日志都读它,别处只引用、不另写这几个字面量(同一件事实两处就会走散)。
3
+ *
4
+ * 谁在用(两个能力,指名):
5
+ * ① `src/record/`——写入域:结果型回执整页与过程型采集页的 envelope 三字段(其中 `key` 过 `sceneKeyOf`)、
6
+ * 复制日志版本、页标题前缀;`src/shared/writeParts.ts` 的 `writeSection` 取技能名做 `data-skill`;
7
+ * ② `src/query/`——查询域:通用查询列表页的同一批取值(envelope 三字段、复制日志版本、页标题前缀)。
8
+ * 两域的页面内置 envelope 都拿本件的 `sceneKeyOf` 把对外命令名收成场景名(`bill.record.today` → `record.today`),
9
+ * 公共层的日志场景标识再与技能名拼回整名。
10
+ *
11
+ * 为什么另立一件:这三个取值是「页面是谁」那件活,与回执事实、`<section>` 段不是同一件事——
12
+ * 混在 `./writeParts.ts` 里会把那份的对外名字顶过五个(铁律五)。
13
+ */
14
+ /** 文档版本(envelope 的 `version`,也是复制日志第 5 段后半)。 */
15
+ export const DOC_VERSION = '0.1.0';
16
+ /** 技能名(envelope 的 `skill`,也是 `<section>` 上 `data-skill` 的取值)。 */
17
+ export const DOC_SKILL = 'bill';
18
+ /** 页面标题前缀(两种页各接一个后缀,如「·写库回执」)。 */
19
+ export const DOC_TITLE = '饼干记账';
20
+ /** 页面内置 envelope 的 `key`(=**场景名**,技能内的本地名)。
21
+ *
22
+ * 为什么不是对外命令名:公共层的日志第 1 段(`scene`)由 envelope 派生,形如 `{skill}.{key}`
23
+ * (`packages/base-render/src/text.ts:296-298` 的 `sceneText`)——`skill` 已是 `bill`,
24
+ * 这里再写一条带 `bill.` 前缀的整名,日志就会印成 `bill.bill.record.add`(两处都重复一遍)。
25
+ * 本件按公共层的分工收口:**页面内置 envelope 的 key=本地场景名**(`bill.record.add` → `record.add`),
26
+ * `skill` + `key` 拼起来正好是对外命令名;`<section data-key>` **同写场景名**(R4 收口:`bill.` 只许出现在
27
+ * 复制载荷区,页面标记一律不带技能前缀),两处一个值,不再各写各的。
28
+ */
29
+ export function sceneKeyOf(key) {
30
+ const prefix = DOC_SKILL + '.';
31
+ return key.startsWith(prefix) ? key.slice(prefix.length) : key;
32
+ }
33
+ //# sourceMappingURL=pageIdentity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageIdentity.js","sourceRoot":"","sources":["../../src/shared/pageIdentity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,gDAAgD;AAChD,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AAEnC,iEAAiE;AACjE,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC;AAEhC,kCAAkC;AAClC,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC;AAEhC;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,MAAM,GAAG,SAAS,GAAG,GAAG,CAAC;IAC/B,OAAO,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACjE,CAAC"}