skill-bill 0.1.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 (101) hide show
  1. package/dist/cli/cmd_read.d.ts +3 -0
  2. package/dist/cli/cmd_read.d.ts.map +1 -0
  3. package/dist/cli/cmd_read.js +530 -0
  4. package/dist/cli/cmd_read.js.map +1 -0
  5. package/dist/fetch/db.d.ts +55 -0
  6. package/dist/fetch/db.d.ts.map +1 -0
  7. package/dist/fetch/db.js +255 -0
  8. package/dist/fetch/db.js.map +1 -0
  9. package/dist/fetch/errors.d.ts +13 -0
  10. package/dist/fetch/errors.d.ts.map +1 -0
  11. package/dist/fetch/errors.js +18 -0
  12. package/dist/fetch/errors.js.map +1 -0
  13. package/dist/fetch/index.d.ts +5 -0
  14. package/dist/fetch/index.d.ts.map +1 -0
  15. package/dist/fetch/index.js +4 -0
  16. package/dist/fetch/index.js.map +1 -0
  17. package/dist/fetch/paths.d.ts +8 -0
  18. package/dist/fetch/paths.d.ts.map +1 -0
  19. package/dist/fetch/paths.js +36 -0
  20. package/dist/fetch/paths.js.map +1 -0
  21. package/dist/help/index.d.ts +2 -0
  22. package/dist/help/index.d.ts.map +1 -0
  23. package/dist/help/index.js +2 -0
  24. package/dist/help/index.js.map +1 -0
  25. package/dist/help/lookup.d.ts +11 -0
  26. package/dist/help/lookup.d.ts.map +1 -0
  27. package/dist/help/lookup.js +53 -0
  28. package/dist/help/lookup.js.map +1 -0
  29. package/dist/index.d.ts +5 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +5 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/policy/accounts.d.ts +13 -0
  34. package/dist/policy/accounts.d.ts.map +1 -0
  35. package/dist/policy/accounts.js +31 -0
  36. package/dist/policy/accounts.js.map +1 -0
  37. package/dist/policy/analysis.d.ts +12 -0
  38. package/dist/policy/analysis.d.ts.map +1 -0
  39. package/dist/policy/analysis.js +39 -0
  40. package/dist/policy/analysis.js.map +1 -0
  41. package/dist/policy/category.d.ts +31 -0
  42. package/dist/policy/category.d.ts.map +1 -0
  43. package/dist/policy/category.js +115 -0
  44. package/dist/policy/category.js.map +1 -0
  45. package/dist/policy/goals.d.ts +15 -0
  46. package/dist/policy/goals.d.ts.map +1 -0
  47. package/dist/policy/goals.js +33 -0
  48. package/dist/policy/goals.js.map +1 -0
  49. package/dist/policy/index.d.ts +13 -0
  50. package/dist/policy/index.d.ts.map +1 -0
  51. package/dist/policy/index.js +7 -0
  52. package/dist/policy/index.js.map +1 -0
  53. package/dist/policy/record.d.ts +15 -0
  54. package/dist/policy/record.d.ts.map +1 -0
  55. package/dist/policy/record.js +62 -0
  56. package/dist/policy/record.js.map +1 -0
  57. package/dist/policy/wakewords.d.ts +14 -0
  58. package/dist/policy/wakewords.d.ts.map +1 -0
  59. package/dist/policy/wakewords.js +121 -0
  60. package/dist/policy/wakewords.js.map +1 -0
  61. package/dist/render/envelope.d.ts +6 -0
  62. package/dist/render/envelope.d.ts.map +1 -0
  63. package/dist/render/envelope.js +56 -0
  64. package/dist/render/envelope.js.map +1 -0
  65. package/dist/render/errors.d.ts +5 -0
  66. package/dist/render/errors.d.ts.map +1 -0
  67. package/dist/render/errors.js +9 -0
  68. package/dist/render/errors.js.map +1 -0
  69. package/dist/render/html.d.ts +13 -0
  70. package/dist/render/html.d.ts.map +1 -0
  71. package/dist/render/html.js +60 -0
  72. package/dist/render/html.js.map +1 -0
  73. package/dist/render/index.d.ts +8 -0
  74. package/dist/render/index.d.ts.map +1 -0
  75. package/dist/render/index.js +6 -0
  76. package/dist/render/index.js.map +1 -0
  77. package/dist/render/templates.d.ts +5 -0
  78. package/dist/render/templates.d.ts.map +1 -0
  79. package/dist/render/templates.js +58 -0
  80. package/dist/render/templates.js.map +1 -0
  81. package/dist/render/views.d.ts +86 -0
  82. package/dist/render/views.d.ts.map +1 -0
  83. package/dist/render/views.js +127 -0
  84. package/dist/render/views.js.map +1 -0
  85. package/package.json +32 -0
  86. package/templates/account_query.html +16 -0
  87. package/templates/account_write.html +16 -0
  88. package/templates/analysis_compare.html +16 -0
  89. package/templates/analysis_overview.html +16 -0
  90. package/templates/analysis_trend.html +16 -0
  91. package/templates/goal_query.html +16 -0
  92. package/templates/goal_write.html +16 -0
  93. package/templates/help.html +16 -0
  94. package/templates/link_submit.html +16 -0
  95. package/templates/record_add.html +16 -0
  96. package/templates/record_detail.html +16 -0
  97. package/templates/record_range.html +16 -0
  98. package/templates/record_search.html +16 -0
  99. package/templates/record_today.html +16 -0
  100. package/templates/record_update.html +16 -0
  101. package/templates/setup_run.html +16 -0
@@ -0,0 +1,56 @@
1
+ // 渲染层·envelope:16 联动 key×shape 映射(拆分表);key 字符串后续票落表时冻结,此处只做形状分配与全字段校验。
2
+ import { createEnvelope, parseEnvelope, parseRegistryKey } from 'base-link-core';
3
+ import { BillRenderError } from './errors.js';
4
+ export const BILL_KEY_SHAPES = {
5
+ 'bill.record.add': 'receipt',
6
+ 'bill.record.update': 'receipt',
7
+ 'bill.record.today': 'list',
8
+ 'bill.record.range': 'list',
9
+ 'bill.record.search': 'list',
10
+ 'bill.record.detail': 'detail',
11
+ 'bill.analysis.overview': 'stat',
12
+ 'bill.analysis.compare': 'analysis',
13
+ 'bill.analysis.trend': 'analysis',
14
+ 'bill.goal.write': 'receipt',
15
+ 'bill.goal.query': 'list',
16
+ 'bill.account.write': 'receipt',
17
+ 'bill.account.query': 'list',
18
+ 'bill.link.submit': 'receipt',
19
+ 'bill.setup.run': 'receipt',
20
+ 'bill.help.lookup': 'list',
21
+ };
22
+ export function billShapeFor(key) {
23
+ const s = BILL_KEY_SHAPES[key];
24
+ if (!s)
25
+ throw new BillRenderError('BILL_UNKNOWN_KEY', '未知联动 key:' + key);
26
+ return s;
27
+ }
28
+ // 建 envelope:key 先过命名空间,再按分配形状做全字段校验;错形状载荷即 throw。
29
+ export function buildBillEnvelope(key, data) {
30
+ let parsedKey = '';
31
+ try {
32
+ parsedKey = parseRegistryKey(key).key;
33
+ }
34
+ catch (e) {
35
+ throw new BillRenderError('BILL_UNKNOWN_KEY', '非法 key:' + e.message);
36
+ }
37
+ const shape = billShapeFor(parsedKey);
38
+ if (typeof data !== 'object' || data === null || Array.isArray(data)) {
39
+ throw new BillRenderError('BILL_BAD_PAYLOAD', '载荷须为对象:' + parsedKey);
40
+ }
41
+ try {
42
+ return createEnvelope({ skill: 'bill', shape, key: parsedKey, data: data });
43
+ }
44
+ catch (e) {
45
+ throw new BillRenderError('BILL_SHAPE_MISMATCH', shape + ' 全字段未过:' + e.message);
46
+ }
47
+ }
48
+ export function parseBillEnvelope(input) {
49
+ try {
50
+ return parseEnvelope(input);
51
+ }
52
+ catch (e) {
53
+ throw new BillRenderError('BILL_BAD_PAYLOAD', 'envelope 非法:' + e.message);
54
+ }
55
+ }
56
+ //# sourceMappingURL=envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.js","sourceRoot":"","sources":["../../src/render/envelope.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAqC,MAAM,gBAAgB,CAAC;AACpH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,CAAC,MAAM,eAAe,GAAkC;IAC5D,iBAAiB,EAAE,SAAS;IAC5B,oBAAoB,EAAE,SAAS;IAC/B,mBAAmB,EAAE,MAAM;IAC3B,mBAAmB,EAAE,MAAM;IAC3B,oBAAoB,EAAE,MAAM;IAC5B,oBAAoB,EAAE,QAAQ;IAC9B,wBAAwB,EAAE,MAAM;IAChC,uBAAuB,EAAE,UAAU;IACnC,qBAAqB,EAAE,UAAU;IACjC,iBAAiB,EAAE,SAAS;IAC5B,iBAAiB,EAAE,MAAM;IACzB,oBAAoB,EAAE,SAAS;IAC/B,oBAAoB,EAAE,MAAM;IAC5B,kBAAkB,EAAE,SAAS;IAC7B,gBAAgB,EAAE,SAAS;IAC3B,kBAAkB,EAAE,MAAM;CAC3B,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,WAAW,GAAG,GAAG,CAAC,CAAC;IACzE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,IAAa;IAC1D,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI,CAAC;QAAC,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;IAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,CAAC;QAAC,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,SAAS,GAAI,CAAW,CAAC,OAAO,CAAC,CAAC;IAAC,CAAC;IAC9F,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,SAAS,GAAG,SAAS,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,CAAC;QACH,OAAO,cAAc,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,IAAa,EAAE,CAAC,CAAC;IACvF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,eAAe,CAAC,qBAAqB,EAAE,KAAK,GAAG,SAAS,GAAI,CAAW,CAAC,OAAO,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,CAAC;QAAC,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;IAAC,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC;QAAC,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,cAAc,GAAI,CAAW,CAAC,OAAO,CAAC,CAAC;IAAC,CAAC;AACrG,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare class BillRenderError extends Error {
2
+ readonly code: 'BILL_UNKNOWN_KEY' | 'BILL_BAD_PAYLOAD' | 'BILL_SHAPE_MISMATCH' | 'BILL_TEMPLATE_MISSING' | 'BILL_MARKER_INVALID' | 'BILL_HTML_TOO_LARGE';
3
+ constructor(code: BillRenderError['code'], message: string);
4
+ }
5
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/render/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EACT,kBAAkB,GAAG,kBAAkB,GAAG,qBAAqB,GAC/D,uBAAuB,GAAG,qBAAqB,GAAG,qBAAqB,CAAC;gBAChE,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM;CAK3D"}
@@ -0,0 +1,9 @@
1
+ export class BillRenderError extends Error {
2
+ code;
3
+ constructor(code, message) {
4
+ super(message);
5
+ this.name = 'BillRenderError';
6
+ this.code = code;
7
+ }
8
+ }
9
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/render/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAE+D;IAC5E,YAAY,IAA6B,EAAE,OAAe;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import type { Envelope } from 'base-link-core';
2
+ export declare const BILL_HTML_MAX_BYTES: number;
3
+ export declare function escapeHtml(s: string): string;
4
+ export declare function renderEnvelopeHtml(env: Envelope): string;
5
+ export declare function estimateBytes(html: string): number;
6
+ export declare function assertHtmlSize(html: string, max?: number): void;
7
+ export declare const SHARED_CSS_MARKER = "<!--SHARED-CSS-->";
8
+ export declare const SHARED_HELPERS_MARKER = "<!--SHARED-HELPERS-->";
9
+ export declare const CONTENT_MARKER = "<!--CONTENT-->";
10
+ export declare const SHARED_CSS = ".page{font-family:system-ui,sans-serif;max-width:720px;margin:0 auto;padding:12px}.item{border:1px solid #ddd;border-radius:8px;padding:8px;margin:8px 0}.item-head{display:flex;gap:8px;align-items:center}.badge{background:#eee;border-radius:4px;padding:0 6px}.amt{font-weight:700}.receipt{background:#f0fff0;border:1px solid #090;border-radius:8px;padding:12px}.stat{display:flex;gap:8px}.analysis{white-space:pre-wrap}.hm-empty{color:#888}";
11
+ export declare const SHARED_HELPERS = "<script>function copyItem(id){var e=document.getElementById(id);if(e&&navigator.clipboard){navigator.clipboard.writeText(e.innerText);}}</script>";
12
+ export declare function fillTemplate(template: string, contentHtml: string): string;
13
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/render/html.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG/C,eAAO,MAAM,mBAAmB,QAAa,CAAC;AAE9C,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAiBD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAexD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAA4C;AAG/F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAsB,GAAG,IAAI,CAI5E;AAGD,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AACrD,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAC7D,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAE/C,eAAO,MAAM,UAAU,6bAA6b,CAAC;AACrd,eAAO,MAAM,cAAc,sJAAsJ,CAAC;AAElL,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAU1E"}
@@ -0,0 +1,60 @@
1
+ import { BillRenderError } from './errors.js';
2
+ export const BILL_HTML_MAX_BYTES = 256 * 1024;
3
+ export function escapeHtml(s) {
4
+ return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
5
+ }
6
+ function billItemHtml(n) {
7
+ const time = escapeHtml(String(n.time ?? ''));
8
+ const cat = escapeHtml(String(n.category ?? ''));
9
+ const amt = escapeHtml(String(n.amount ?? ''));
10
+ const note = escapeHtml(String(n.note ?? ''));
11
+ const id = escapeHtml(String(n.id ?? ''));
12
+ return '<div class="item"><div class="item-head"><span class="id">' + id + '</span><span class="time">' + time + '</span><span class="badge">' + cat + '</span><span class="amt">' + amt + '</span></div><div class="content">' + note + '</div></div>';
13
+ }
14
+ function listHtml(items) {
15
+ if (!items.length)
16
+ return '<div class="hm-empty">暂无记录</div>';
17
+ return items.map((x) => billItemHtml(x)).join('');
18
+ }
19
+ // 按形状渲染 envelope 为 section 页;未知形状 throw 不返空页。
20
+ export function renderEnvelopeHtml(env) {
21
+ const head = '<section data-skill="bill" data-shape="' + env.shape + '" data-key="' + escapeHtml(env.key) + '">';
22
+ const d = env.data;
23
+ switch (env.shape) {
24
+ case 'list': return head + listHtml(d.items) + '</section>';
25
+ case 'detail': return head + billItemHtml(d.item) + '</section>';
26
+ case 'receipt': return head + '<div class="receipt">' + escapeHtml(String(d.message)) + '</div></section>';
27
+ case 'stat': {
28
+ const rows = Object.entries((d.metrics || {}));
29
+ return head + rows.map(([k, v]) => '<div class="stat"><b>' + v + '</b><span>' + escapeHtml(k) + '</span></div>').join('') + '</section>';
30
+ }
31
+ case 'analysis': return head + '<div class="analysis">' + escapeHtml(String(d.summary)).replace(/\n/g, '<br>') + '</div></section>';
32
+ case 'fallback': return head + '<div data-degraded="1">' + escapeHtml(String(d.reason)) + '</div></section>';
33
+ default: throw new BillRenderError('BILL_SHAPE_MISMATCH', '无法渲染形状:' + String(env.shape));
34
+ }
35
+ }
36
+ export function estimateBytes(html) { return Buffer.byteLength(html, 'utf8'); }
37
+ // 体积门:超限 throw(调用方走 fallback 形状显式降级,不静默截断)。
38
+ export function assertHtmlSize(html, max = BILL_HTML_MAX_BYTES) {
39
+ if (estimateBytes(html) > max) {
40
+ throw new BillRenderError('BILL_HTML_TOO_LARGE', 'HTML 超体积:' + estimateBytes(html) + ' > ' + max);
41
+ }
42
+ }
43
+ // 共享标记填充(老家离线注入壳对应):CSS/HELPERS/CONTENT 三标记各恰出现 1 次,否则 throw。
44
+ export const SHARED_CSS_MARKER = '<!--SHARED-CSS-->';
45
+ export const SHARED_HELPERS_MARKER = '<!--SHARED-HELPERS-->';
46
+ export const CONTENT_MARKER = '<!--CONTENT-->';
47
+ export const SHARED_CSS = '.page{font-family:system-ui,sans-serif;max-width:720px;margin:0 auto;padding:12px}.item{border:1px solid #ddd;border-radius:8px;padding:8px;margin:8px 0}.item-head{display:flex;gap:8px;align-items:center}.badge{background:#eee;border-radius:4px;padding:0 6px}.amt{font-weight:700}.receipt{background:#f0fff0;border:1px solid #090;border-radius:8px;padding:12px}.stat{display:flex;gap:8px}.analysis{white-space:pre-wrap}.hm-empty{color:#888}';
48
+ export const SHARED_HELPERS = '<script>function copyItem(id){var e=document.getElementById(id);if(e&&navigator.clipboard){navigator.clipboard.writeText(e.innerText);}}</script>';
49
+ export function fillTemplate(template, contentHtml) {
50
+ for (const m of [SHARED_CSS_MARKER, SHARED_HELPERS_MARKER, CONTENT_MARKER]) {
51
+ if (template.split(m).length - 1 !== 1) {
52
+ throw new BillRenderError('BILL_MARKER_INVALID', '标记须恰出现 1 次:' + m);
53
+ }
54
+ }
55
+ return template
56
+ .split(SHARED_CSS_MARKER).join('<style>' + SHARED_CSS + '</style>')
57
+ .split(SHARED_HELPERS_MARKER).join(SHARED_HELPERS)
58
+ .split(CONTENT_MARKER).join(contentHtml);
59
+ }
60
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/render/html.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export { BillRenderError } from './errors.js';
2
+ export { BILL_KEY_SHAPES, billShapeFor, buildBillEnvelope, parseBillEnvelope } from './envelope.js';
3
+ export { BILL_HTML_MAX_BYTES, escapeHtml, renderEnvelopeHtml, estimateBytes, assertHtmlSize, SHARED_CSS_MARKER, SHARED_HELPERS_MARKER, CONTENT_MARKER, SHARED_CSS, SHARED_HELPERS, fillTemplate } from './html.js';
4
+ export { BILL_TEMPLATES, templateFor, loadTemplate } from './templates.js';
5
+ export type { BillTemplate } from './templates.js';
6
+ export { toBillItem, calcKpi, calcCategories, buildRecordToday, buildRecordRange, buildRecordSearch, buildRecordDetail, buildRecordReceipt, buildOverview, buildCompare, buildTrend, buildGoalQuery, buildAccountQuery, buildHelpItems } from './views.js';
7
+ export type { BillItem, HelpItem } from './views.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACnN,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC3E,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC3P,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { BillRenderError } from './errors.js';
2
+ export { BILL_KEY_SHAPES, billShapeFor, buildBillEnvelope, parseBillEnvelope } from './envelope.js';
3
+ export { BILL_HTML_MAX_BYTES, escapeHtml, renderEnvelopeHtml, estimateBytes, assertHtmlSize, SHARED_CSS_MARKER, SHARED_HELPERS_MARKER, CONTENT_MARKER, SHARED_CSS, SHARED_HELPERS, fillTemplate } from './html.js';
4
+ export { BILL_TEMPLATES, templateFor, loadTemplate } from './templates.js';
5
+ export { toBillItem, calcKpi, calcCategories, buildRecordToday, buildRecordRange, buildRecordSearch, buildRecordDetail, buildRecordReceipt, buildOverview, buildCompare, buildTrend, buildGoalQuery, buildAccountQuery, buildHelpItems } from './views.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACnN,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE3E,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const BILL_TEMPLATES: readonly ["record_add", "record_update", "record_today", "record_range", "record_search", "record_detail", "analysis_overview", "analysis_compare", "analysis_trend", "goal_write", "goal_query", "account_write", "account_query", "link_submit", "setup_run", "help"];
2
+ export type BillTemplate = (typeof BILL_TEMPLATES)[number];
3
+ export declare function templateFor(key: string): BillTemplate;
4
+ export declare function loadTemplate(name: string): string;
5
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/render/templates.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc,yQAiBjB,CAAC;AACX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAG3D,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAoBrD;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjD"}
@@ -0,0 +1,58 @@
1
+ // 渲染层·模板装载:16 模板随包发布;未知/缺失大声失败。
2
+ import { readFileSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { BillRenderError } from './errors.js';
6
+ export const BILL_TEMPLATES = [
7
+ 'record_add',
8
+ 'record_update',
9
+ 'record_today',
10
+ 'record_range',
11
+ 'record_search',
12
+ 'record_detail',
13
+ 'analysis_overview',
14
+ 'analysis_compare',
15
+ 'analysis_trend',
16
+ 'goal_write',
17
+ 'goal_query',
18
+ 'account_write',
19
+ 'account_query',
20
+ 'link_submit',
21
+ 'setup_run',
22
+ 'help',
23
+ ];
24
+ // key → 模板(1 键 1 模板)。
25
+ export function templateFor(key) {
26
+ switch (key) {
27
+ case 'bill.record.add': return 'record_add';
28
+ case 'bill.record.update': return 'record_update';
29
+ case 'bill.record.today': return 'record_today';
30
+ case 'bill.record.range': return 'record_range';
31
+ case 'bill.record.search': return 'record_search';
32
+ case 'bill.record.detail': return 'record_detail';
33
+ case 'bill.analysis.overview': return 'analysis_overview';
34
+ case 'bill.analysis.compare': return 'analysis_compare';
35
+ case 'bill.analysis.trend': return 'analysis_trend';
36
+ case 'bill.goal.write': return 'goal_write';
37
+ case 'bill.goal.query': return 'goal_query';
38
+ case 'bill.account.write': return 'account_write';
39
+ case 'bill.account.query': return 'account_query';
40
+ case 'bill.link.submit': return 'link_submit';
41
+ case 'bill.setup.run': return 'setup_run';
42
+ case 'bill.help.lookup': return 'help';
43
+ default: throw new BillRenderError('BILL_UNKNOWN_KEY', '无模板映射:' + key);
44
+ }
45
+ }
46
+ const templatesDir = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'templates');
47
+ export function loadTemplate(name) {
48
+ if (!BILL_TEMPLATES.includes(name)) {
49
+ throw new BillRenderError('BILL_TEMPLATE_MISSING', '未知模板:' + name);
50
+ }
51
+ try {
52
+ return readFileSync(join(templatesDir, name + '.html'), 'utf8');
53
+ }
54
+ catch (e) {
55
+ throw new BillRenderError('BILL_TEMPLATE_MISSING', '模板缺失:' + name);
56
+ }
57
+ }
58
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/render/templates.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,YAAY;IACZ,eAAe;IACf,cAAc;IACd,cAAc;IACd,eAAe;IACf,eAAe;IACf,mBAAmB;IACnB,kBAAkB;IAClB,gBAAgB;IAChB,YAAY;IACZ,YAAY;IACZ,eAAe;IACf,eAAe;IACf,aAAa;IACb,WAAW;IACX,MAAM;CACE,CAAC;AAGX,sBAAsB;AACtB,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,iBAAiB,CAAC,CAAC,OAAO,YAAY,CAAC;QAC5C,KAAK,oBAAoB,CAAC,CAAC,OAAO,eAAe,CAAC;QAClD,KAAK,mBAAmB,CAAC,CAAC,OAAO,cAAc,CAAC;QAChD,KAAK,mBAAmB,CAAC,CAAC,OAAO,cAAc,CAAC;QAChD,KAAK,oBAAoB,CAAC,CAAC,OAAO,eAAe,CAAC;QAClD,KAAK,oBAAoB,CAAC,CAAC,OAAO,eAAe,CAAC;QAClD,KAAK,wBAAwB,CAAC,CAAC,OAAO,mBAAmB,CAAC;QAC1D,KAAK,uBAAuB,CAAC,CAAC,OAAO,kBAAkB,CAAC;QACxD,KAAK,qBAAqB,CAAC,CAAC,OAAO,gBAAgB,CAAC;QACpD,KAAK,iBAAiB,CAAC,CAAC,OAAO,YAAY,CAAC;QAC5C,KAAK,iBAAiB,CAAC,CAAC,OAAO,YAAY,CAAC;QAC5C,KAAK,oBAAoB,CAAC,CAAC,OAAO,eAAe,CAAC;QAClD,KAAK,oBAAoB,CAAC,CAAC,OAAO,eAAe,CAAC;QAClD,KAAK,kBAAkB,CAAC,CAAC,OAAO,aAAa,CAAC;QAC9C,KAAK,gBAAgB,CAAC,CAAC,OAAO,WAAW,CAAC;QAC1C,KAAK,kBAAkB,CAAC,CAAC,OAAO,MAAM,CAAC;QACvC,OAAO,CAAC,CAAC,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,QAAQ,GAAG,GAAG,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;AAE5F,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAoB,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,eAAe,CAAC,uBAAuB,EAAE,OAAO,GAAG,IAAI,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,CAAC;QAAC,OAAO,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;IAAC,CAAC;IACxE,OAAO,CAAC,EAAE,CAAC;QAAC,MAAM,IAAI,eAAe,CAAC,uBAAuB,EAAE,OAAO,GAAG,IAAI,CAAC,CAAC;IAAC,CAAC;AACnF,CAAC"}
@@ -0,0 +1,86 @@
1
+ import type { BillRow } from '../fetch/db.js';
2
+ export interface BillItem {
3
+ id: number;
4
+ category: string;
5
+ time: string;
6
+ amount: number;
7
+ account: string;
8
+ ledger: string;
9
+ currency: string;
10
+ note: string;
11
+ }
12
+ export declare function toBillItem(r: BillRow): BillItem;
13
+ export declare function calcKpi(records: BillRow[]): {
14
+ count: number;
15
+ expense: number;
16
+ income: number;
17
+ net: number;
18
+ };
19
+ export declare function calcCategories(records: BillRow[]): {
20
+ category: string;
21
+ total: number;
22
+ count: number;
23
+ }[];
24
+ export declare function buildRecordToday(date: string, records: BillRow[]): {
25
+ items: BillItem[];
26
+ total: number;
27
+ date: string;
28
+ kpi: ReturnType<typeof calcKpi>;
29
+ };
30
+ export declare function buildRecordRange(start: string, end: string, records: BillRow[]): {
31
+ items: BillItem[];
32
+ total: number;
33
+ start: string;
34
+ end: string;
35
+ kpi: ReturnType<typeof calcKpi>;
36
+ };
37
+ export declare function buildRecordSearch(kind: string, records: BillRow[]): {
38
+ items: BillItem[];
39
+ total: number;
40
+ kind: string;
41
+ kpi: ReturnType<typeof calcKpi>;
42
+ };
43
+ export declare function buildRecordDetail(record: BillRow): {
44
+ item: Record<string, unknown>;
45
+ };
46
+ export declare function buildRecordReceipt(message: string): {
47
+ ok: boolean;
48
+ message: string;
49
+ };
50
+ export declare function buildOverview(label: string, records: BillRow[]): {
51
+ metrics: Record<string, number>;
52
+ };
53
+ export declare function buildCompare(args: {
54
+ labelA: string;
55
+ labelB: string;
56
+ a: BillRow[];
57
+ b: BillRow[];
58
+ }): {
59
+ summary: string;
60
+ };
61
+ export declare function buildTrend(kind: string, records: BillRow[], opts?: {
62
+ limit?: number;
63
+ }): {
64
+ summary: string;
65
+ };
66
+ export declare function buildGoalQuery(op: string, items: Record<string, unknown>[]): {
67
+ items: Record<string, unknown>[];
68
+ total: number;
69
+ op: string;
70
+ };
71
+ export declare function buildAccountQuery(items: Record<string, unknown>[]): {
72
+ items: Record<string, unknown>[];
73
+ total: number;
74
+ };
75
+ export interface HelpItem {
76
+ phrase: string;
77
+ key: string;
78
+ shape: string;
79
+ cli: string;
80
+ desc: string;
81
+ }
82
+ export declare function buildHelpItems(all: HelpItem[], q?: string): {
83
+ items: HelpItem[];
84
+ total: number;
85
+ };
86
+ //# sourceMappingURL=views.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"views.d.ts","sourceRoot":"","sources":["../../src/render/views.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,127 @@
1
+ import { l1Of } from '../policy/category.js';
2
+ export function toBillItem(r) {
3
+ return {
4
+ id: r.id, category: r.category, time: r.time, amount: r.amount,
5
+ account: r.account, ledger: r.ledger, currency: r.currency, note: r.note,
6
+ };
7
+ }
8
+ function isTransfer(r) {
9
+ return r.ledger === '转账' || r.category.startsWith('转账/');
10
+ }
11
+ // KPI(转账除外):count/expense/income/net 全 number。
12
+ export function calcKpi(records) {
13
+ const real = records.filter((r) => !isTransfer(r));
14
+ let expense = 0;
15
+ let income = 0;
16
+ for (const r of real) {
17
+ if (r.amount < 0)
18
+ expense += Math.abs(r.amount);
19
+ else
20
+ income += r.amount;
21
+ }
22
+ expense = Math.round(expense * 100) / 100;
23
+ income = Math.round(income * 100) / 100;
24
+ return { count: real.length, expense, income, net: Math.round((income - expense) * 100) / 100 };
25
+ }
26
+ // 分类聚合(支出侧绝对值降序,转账除外)。
27
+ export function calcCategories(records) {
28
+ const agg = new Map();
29
+ for (const r of records) {
30
+ if (r.amount >= 0 || isTransfer(r))
31
+ continue;
32
+ const cat = r.category || '其他';
33
+ const it = agg.get(cat) ?? { category: cat, total: 0, count: 0 };
34
+ it.total += Math.abs(r.amount);
35
+ it.count += 1;
36
+ agg.set(cat, it);
37
+ }
38
+ const out = [...agg.values()].sort((a, b) => b.total - a.total);
39
+ for (const it of out)
40
+ it.total = Math.round(it.total * 100) / 100;
41
+ return out;
42
+ }
43
+ // 单日/区间/搜索:items + total + kpi(供模板主卡)。
44
+ export function buildRecordToday(date, records) {
45
+ const items = records.map(toBillItem);
46
+ return { items, total: items.length, date, kpi: calcKpi(records) };
47
+ }
48
+ export function buildRecordRange(start, end, records) {
49
+ const items = records.map(toBillItem);
50
+ return { items, total: items.length, start, end, kpi: calcKpi(records) };
51
+ }
52
+ export function buildRecordSearch(kind, records) {
53
+ const items = records.map(toBillItem);
54
+ return { items, total: items.length, kind, kpi: calcKpi(records) };
55
+ }
56
+ export function buildRecordDetail(record) {
57
+ return { item: { ...toBillItem(record) } };
58
+ }
59
+ export function buildRecordReceipt(message) {
60
+ return { ok: true, message };
61
+ }
62
+ // 总览:stat metrics(count/expense/income/net + l1.* + days 全 number)。
63
+ export function buildOverview(label, records) {
64
+ const kpi = calcKpi(records);
65
+ const metrics = { count: kpi.count, expense: kpi.expense, income: kpi.income, net: kpi.net };
66
+ const days = new Set();
67
+ for (const r of records) {
68
+ days.add(r.time.slice(0, 10));
69
+ if (r.amount < 0 && !isTransfer(r)) {
70
+ const k = 'l1.' + l1Of(r.category);
71
+ metrics[k] = Math.round(((metrics[k] || 0) + Math.abs(r.amount)) * 100) / 100;
72
+ }
73
+ }
74
+ metrics.days = days.size;
75
+ void label;
76
+ return { metrics };
77
+ }
78
+ // 对比:analysis summary(两聚合 + 差异句;数字全来自实算)。
79
+ export function buildCompare(args) {
80
+ const ka = calcKpi(args.a);
81
+ const kb = calcKpi(args.b);
82
+ const fmt = (n) => String(n);
83
+ const lines = [
84
+ `${args.labelA} vs ${args.labelB}:笔数 ${ka.count}→${kb.count},支出 ${fmt(ka.expense)}→${fmt(kb.expense)},收入 ${fmt(ka.income)}→${fmt(kb.income)},净额 ${fmt(ka.net)}→${fmt(kb.net)}。`,
85
+ ];
86
+ const d = Math.round((kb.expense - ka.expense) * 100) / 100;
87
+ lines.push('支出变化:' + (d >= 0 ? '+' : '') + d + '。');
88
+ return { summary: lines.join('\n') };
89
+ }
90
+ // 趋势/排行/洞察:analysis summary(按月聚合 + Top/高频/分布/异常句;数字全来自实算)。
91
+ export function buildTrend(kind, records, opts = {}) {
92
+ const limit = opts.limit ?? 5;
93
+ const byMonth = new Map();
94
+ for (const r of records) {
95
+ if (isTransfer(r))
96
+ continue;
97
+ const m = r.time.slice(0, 7);
98
+ byMonth.set(m, Math.round(((byMonth.get(m) || 0) + Math.abs(r.amount)) * 100) / 100);
99
+ }
100
+ const months = [...byMonth.entries()].sort((a, b) => a[0].localeCompare(b[0]));
101
+ const lines = [`${kind}:共 ${records.length} 笔,` + months.map(([m, v]) => `${m} ${v}`).join('、') + '。'];
102
+ if (kind === 'top' || kind === 'trend') {
103
+ const top = [...records].filter((r) => r.amount < 0 && !isTransfer(r)).sort((a, b) => a.amount - b.amount).slice(0, limit);
104
+ for (const r of top)
105
+ lines.push(`${r.time.slice(0, 10)} ${r.category} ${r.amount} ${r.note}`.trim());
106
+ }
107
+ if (kind === 'insight' || kind === 'anomaly') {
108
+ const cats = calcCategories(records).slice(0, 3);
109
+ if (cats.length)
110
+ lines.push('主要支出:' + cats.map((c) => `${c.category} ${c.total}`).join('、') + '。');
111
+ else
112
+ lines.push('样本不足,无显著异常。');
113
+ }
114
+ return { summary: lines.join('\n') };
115
+ }
116
+ // 目标/账户查询:list(items + total;预算执行/余额由调用方实算装配)。
117
+ export function buildGoalQuery(op, items) {
118
+ return { items, total: items.length, op };
119
+ }
120
+ export function buildAccountQuery(items) {
121
+ return { items, total: items.length };
122
+ }
123
+ export function buildHelpItems(all, q) {
124
+ const items = !q || !q.trim() ? all : all.filter((h) => q.includes(h.phrase) || h.phrase.includes(q.trim()));
125
+ return { items, total: items.length };
126
+ }
127
+ //# sourceMappingURL=views.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"views.js","sourceRoot":"","sources":["../../src/render/views.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "skill-bill",
3
+ "version": "0.1.0",
4
+ "description": "饼干记账SKILL一期:取数+口径+渲染+出口(16 联动 key+cmd_read+SKILL+HELP+parity),依 link-core",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": "./dist/index.js",
10
+ "./fetch": "./dist/fetch/index.js",
11
+ "./policy": "./dist/policy/index.js",
12
+ "./render": "./dist/render/index.js",
13
+ "./cli": "./dist/cli/cmd_read.js"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "templates/*.html"
18
+ ],
19
+ "bin": {
20
+ "bill-cmd-read": "./dist/cli/cmd_read.js"
21
+ },
22
+ "dependencies": {
23
+ "base-link-core": "workspace:^0.1.0"
24
+ },
25
+ "engines": {
26
+ "node": ">=22.13"
27
+ },
28
+ "scripts": {
29
+ "build": "tsc -b && node scripts/build-help.mjs",
30
+ "test": "node --test test/*.test.mjs"
31
+ }
32
+ }
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>看账户汇总</title>
6
+ <!--SHARED-CSS-->
7
+ </head>
8
+ <body>
9
+ <div class="page">
10
+ <h1>看账户汇总</h1>
11
+ <p class="cmd">bill-cmd-read bill.account.query</p>
12
+ <!--CONTENT-->
13
+ </div>
14
+ <!--SHARED-HELPERS-->
15
+ </body>
16
+ </html>
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>新增改转账</title>
6
+ <!--SHARED-CSS-->
7
+ </head>
8
+ <body>
9
+ <div class="page">
10
+ <h1>新增改转账</h1>
11
+ <p class="cmd">bill-cmd-read bill.account.write</p>
12
+ <!--CONTENT-->
13
+ </div>
14
+ <!--SHARED-HELPERS-->
15
+ </body>
16
+ </html>
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>看对比</title>
6
+ <!--SHARED-CSS-->
7
+ </head>
8
+ <body>
9
+ <div class="page">
10
+ <h1>看对比</h1>
11
+ <p class="cmd">bill-cmd-read bill.analysis.compare</p>
12
+ <!--CONTENT-->
13
+ </div>
14
+ <!--SHARED-HELPERS-->
15
+ </body>
16
+ </html>
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>看月度总览</title>
6
+ <!--SHARED-CSS-->
7
+ </head>
8
+ <body>
9
+ <div class="page">
10
+ <h1>看月度总览</h1>
11
+ <p class="cmd">bill-cmd-read bill.analysis.overview</p>
12
+ <!--CONTENT-->
13
+ </div>
14
+ <!--SHARED-HELPERS-->
15
+ </body>
16
+ </html>