@fui-org/fui-cli 1.3.1 → 2.0.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 (111) hide show
  1. package/README.md +19 -3
  2. package/dist/fui-bmg5pnmq.js +379 -0
  3. package/dist/fui.js +1 -1
  4. package/package.json +7 -6
  5. package/skills/fui/SKILL.md +9 -41
  6. package/skills/fui-skill/SKILL.md +95 -225
  7. package/skills/fui-skill/assets/projectdefaultstyle-3.0.css +555 -0
  8. package/skills/fui-skill/assets/projectdefaultstyle.css +207 -235
  9. package/skills/fui-skill/references/INDEX.md +105 -137
  10. package/skills/fui-skill/references/advanced-techniques.md +76 -68
  11. package/skills/fui-skill/references/coding-standards.md +56 -56
  12. package/skills/fui-skill/references/component-design.md +166 -173
  13. package/skills/fui-skill/references/component-quickref.md +61 -60
  14. package/skills/fui-skill/references/component-table.md +128 -117
  15. package/skills/fui-skill/references/components-dialog.md +55 -56
  16. package/skills/fui-skill/references/components-display.md +24 -30
  17. package/skills/fui-skill/references/components-echart.md +186 -261
  18. package/skills/fui-skill/references/components-input.md +72 -96
  19. package/skills/fui-skill/references/controls-patterns.md +196 -342
  20. package/skills/fui-skill/references/controls-styling-vocabulary.md +130 -97
  21. package/skills/fui-skill/references/db-table-design.md +24 -28
  22. package/skills/fui-skill/references/db-workflow.md +191 -390
  23. package/skills/fui-skill/references/default-function.md +169 -128
  24. package/skills/fui-skill/references/design-modes.md +35 -63
  25. package/skills/fui-skill/references/echart-templates.md +204 -196
  26. package/skills/fui-skill/references/fastproject.md +62 -60
  27. package/skills/fui-skill/references/fsheet.md +109 -124
  28. package/skills/fui-skill/references/fullstack-workflow.md +90 -128
  29. package/skills/fui-skill/references/module-data-patterns.md +31 -40
  30. package/skills/fui-skill/references/module-json-anatomy.md +47 -52
  31. package/skills/fui-skill/references/module-structure.md +80 -196
  32. package/skills/fui-skill/references/new-session.md +49 -51
  33. package/skills/fui-skill/references/pdfmake.md +17 -17
  34. package/skills/fui-skill/references/permission-system.md +89 -108
  35. package/skills/fui-skill/references/platform-architecture.md +128 -153
  36. package/skills/fui-skill/references/project-config.md +102 -134
  37. package/skills/fui-skill/references/project-provisioning.md +139 -244
  38. package/skills/fui-skill/references/script-map.md +208 -242
  39. package/skills/fui-skill/references/sql-clr-functions.md +98 -97
  40. package/skills/fui-skill/references/system-design.md +63 -88
  41. package/skills/fui-skill/references/tapi-file-api.md +46 -52
  42. package/skills/fui-skill/references/tapi-permission-patterns.md +51 -53
  43. package/skills/fui-skill/references/tapi-reference.md +132 -207
  44. package/skills/fui-skill/references/tools-registry.md +84 -460
  45. package/skills/fui-skill/references/ui-crosswindow-patterns.md +79 -75
  46. package/skills/fui-skill/references/ui-dialog-patterns.md +98 -72
  47. package/skills/fui-skill/references/ui-layout-patterns.md +26 -26
  48. package/skills/fui-skill/references/ui-patterns.md +71 -83
  49. package/skills/fui-skill/references/ui-screenshot-review.md +63 -62
  50. package/skills/fui-skill/references/ui-table-cell-patterns.md +61 -59
  51. package/skills/fui-skill/references/ui-templates.md +16 -23
  52. package/skills/fui-skill/references/verification.md +236 -246
  53. package/skills/fui-skill/references/watcher-patterns.md +30 -63
  54. package/skills/fui-skill/references/websocket-realtime.md +83 -66
  55. package/skills/fui-skill/scripts/component-3.0.js +298 -131
  56. package/skills/fui-skill/scripts/component.js +277 -271
  57. package/skills/fui-skill/scripts/componentTable-3.0.js +182 -53
  58. package/skills/fui-skill/scripts/componentTable.js +171 -49
  59. package/skills/fui-skill/scripts/defaultfunction-3.0.js +88 -3
  60. package/skills/fui-skill/scripts/defaultfunction.js +88 -3
  61. package/skills/fui-skill/scripts/fsheet.js +38 -0
  62. package/dist/fui-x7kph78r.js +0 -420
  63. package/skills/fui-skill/README.md +0 -112
  64. package/skills/fui-skill/metadata.json +0 -75
  65. package/skills/fui-skill-cli/SKILL.md +0 -139
  66. package/skills/fui-skill-cli/references/INDEX.md +0 -110
  67. package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
  68. package/skills/fui-skill-cli/references/coding-standards.md +0 -112
  69. package/skills/fui-skill-cli/references/component-design.md +0 -448
  70. package/skills/fui-skill-cli/references/component-quickref.md +0 -78
  71. package/skills/fui-skill-cli/references/component-table.md +0 -248
  72. package/skills/fui-skill-cli/references/components-dialog.md +0 -191
  73. package/skills/fui-skill-cli/references/components-display.md +0 -141
  74. package/skills/fui-skill-cli/references/components-echart.md +0 -316
  75. package/skills/fui-skill-cli/references/components-input.md +0 -335
  76. package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
  77. package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
  78. package/skills/fui-skill-cli/references/db-table-design.md +0 -73
  79. package/skills/fui-skill-cli/references/db-workflow.md +0 -288
  80. package/skills/fui-skill-cli/references/default-function.md +0 -425
  81. package/skills/fui-skill-cli/references/design-modes.md +0 -57
  82. package/skills/fui-skill-cli/references/echart-templates.md +0 -489
  83. package/skills/fui-skill-cli/references/fastproject.md +0 -99
  84. package/skills/fui-skill-cli/references/fsheet.md +0 -203
  85. package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
  86. package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
  87. package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
  88. package/skills/fui-skill-cli/references/module-structure.md +0 -141
  89. package/skills/fui-skill-cli/references/new-session.md +0 -85
  90. package/skills/fui-skill-cli/references/pdfmake.md +0 -60
  91. package/skills/fui-skill-cli/references/permission-system.md +0 -150
  92. package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
  93. package/skills/fui-skill-cli/references/project-config.md +0 -303
  94. package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
  95. package/skills/fui-skill-cli/references/script-map.md +0 -262
  96. package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
  97. package/skills/fui-skill-cli/references/system-design.md +0 -89
  98. package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
  99. package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
  100. package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
  101. package/skills/fui-skill-cli/references/tools-registry.md +0 -84
  102. package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
  103. package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
  104. package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
  105. package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
  106. package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
  107. package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
  108. package/skills/fui-skill-cli/references/ui-templates.md +0 -22
  109. package/skills/fui-skill-cli/references/verification.md +0 -236
  110. package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
  111. package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
@@ -1,144 +1,112 @@
1
- # FUI Skill — Reference Router (INDEX)
2
-
3
- > File này sở hữu: **bảng định tuyến tình huống / component / từ khóa → file reference cần load**. Không chứa nội dung kỹ thuật — mọi quy tắc đều nằm ở file đích. *(Tier A — luôn nạp cùng `skill_get`.)*
4
-
5
- **Bản đồ tra cứu: tình huống / component / từ khóa → file cần load.** Đây là file luôn được nạp cùng `skill_get`. Trước khi xử lý bất kỳ việc gì, tra bảng dưới để biết cần `skill_reference_get({ refs: [...] })` file nào — **đừng dựa vào trí nhớ, hãy load đúng file**.
6
-
7
- > Cách dùng: `skill_reference_get({ refs: ["references/<tên-file>.md"] })`. Có thể load nhiều file một lần.
8
-
9
- ---
10
-
11
- ## Luôn có sẵn (Tier A — đã nạp cùng skill_get)
12
-
13
- | File | Nội dung |
14
- |---|---|
15
- | `controls-patterns.md` | Action engine (**§QUY TẮC NỀN: một `{}` = một lệnh; nhiều lệnh tuần tự = mảng `[{…},{…}]`**), value resolution, key notation, layout grid — **nền tảng** |
16
- | `module-structure.md` | Cấu trúc file module/project, layout rules |
17
- | `INDEX.md` | (file này) — bản đồ router |
18
-
19
- ---
20
-
21
- ## Hiểu nền tảng / cấu tạo FUI (đọc sớm)
22
-
23
- | Tình huống | Load file |
24
- |---|---|
25
- | Cấu tạo FUI, phân cấp Project→Module (import/component/set trộn thế nào), runtime, vueData/v_Set | `platform-architecture.md` |
26
- | 4 thành phần module.json (data/watch/controls/set) — vai trò, cấu hình, tương tác | `module-json-anatomy.md` |
27
- | **`HTMLOnly: true`** — server KHÔNG nhúng sẵn thư viện nào (Vue/Vuetify/jQuery/lodash/MDI/`projectdefaultstyle.css` đều vắng); cần gì phải tự khai trong chính module, và `script-map.md` KHÔNG áp dụng | `module-structure.md` §HTMLOnly=true: KHÔNG có thư viện nào được nhúng sẵn (Tier A, đã nạp sẵn) |
28
-
29
- ## Thiết kế UI / chọn component
30
-
31
- | Tình huống | Load file |
32
- |---|---|
33
- | **Layout controls — class/prop/style ĐƯỢC DÙNG (đừng tự thêm style)** | `controls-styling-vocabulary.md` |
34
- | Bắt đầu thiết kế UI, chọn component nào | `component-quickref.md` |
35
- | Khai báo `data[]` — ba loại phần tử, thứ tự state → named action → auto-startup | `module-data-patterns.md` (value resolution + key lồng nhau: `controls-patterns.md` §0/§1, Tier A) |
36
- | Pattern UI thực tế (data/watch/toolbar/filter/permission) | `ui-patterns.md` |
37
- | **Hàng nhiều control / canh phải nhóm nút** — chuẩn `shrink` cho mọi cột trừ `v-spacer`; `w` px | `controls-patterns.md` (Tier A, đã nạp sẵn) |
38
- | **f-table** — **hiển thị dữ liệu dạng datatable** (list/CRUD qua form dialog, cả readonly lẫn có `:update-api`) + điều khiển trong ô: t-check/t-button/t-select/t-menu, ctrl-update, show-select, chip-group | `ui-table-cell-patterns.md` |
39
- | Bảng dữ liệu chuyên sâu (mọi props, header types, auto-headers khi bỏ `:headers`, **tổng cột `sum-format`** — object=hàng tổng trong bảng / string=dòng text dưới bảng, readonly table) | `component-table.md` |
40
- | **f-sheet** — **nhập liệu trực tiếp trên bảng kiểu Excel** (sửa ô tại chỗ, dán từ Excel, không qua dialog) — component có sẵn (nền tảng AG Grid), KHÔNG tự viết bảng nhập liệu bằng `uc-*.vue`; import, props, columns, wiring API | `fsheet.md` |
41
- | Dialog / form popup (hidden-container, mở dialog với row, checkbox-list) | `ui-dialog-patterns.md` |
42
- | Mở sub-window & trao đổi dữ liệu (`openWindow`, `#PARENT`/`#Win`) | `ui-crosswindow-patterns.md` |
43
- | Layout: page-container, master-detail, v-switch, date init, dynamic label | `ui-layout-patterns.md` |
44
- | Input controls (f-date, f-time, f-search, f-radiobox, text-field...) | `components-input.md` |
45
- | Display components (f-label, f-title, f-box, f-header, chip, badge...) | `components-display.md` |
46
- | Dialog components (f-dialog, v-dialog chi tiết) | `components-dialog.md` |
47
- | Custom Vue component (`uc-*.vue`) — scope, props/events, **ưu tiên class Vuetify có sẵn (cấm _injectStyle)**, dialog chuẩn hoá, tận dụng ajaxCALL/confirm/showMessage | `component-design.md` |
48
- | **Kiểm chứng `uc-*.vue` trong không gian riêng** (`component_preview`) + luật push component cấp project trước khi render module | `component-design.md` |
49
- | **Tra component project-scope đã có** trước khi tạo mới — quy ước `{projectId}/COMPONENTS.md` + vòng tích luỹ | `component-design.md` §1a |
50
- | Template/ví dụ tham chiếu nhanh | `ui-templates.md` + `examples/` |
51
- | **User gửi ảnh chụp màn hình giao diện** vào chat, hoặc đọc screenshot từ `renderUI` — đánh giá lỗi hiển thị, màu sắc, padding/margin, căn chỉnh, vị trí nút | `ui-screenshot-review.md` |
52
-
53
- ## Biểu đồ / báo cáo / dashboard
54
-
55
- | Tình huống | Load file |
56
- |---|---|
57
- | Dùng f-echart (nền tảng Apache ECharts) — import, props, config, theme, DataView, `grid` padding, `boundaryGap`, lỗi | `components-echart.md` |
58
- | Chọn/vẽ loại chart cụ thể + pattern module.json | `echart-templates.md` |
59
- | Xuất PDF (f-pdfmake) | `pdfmake.md` |
60
-
61
- ## API / Stored Procedure / tAPI
62
-
63
- | Tình huống | Load file |
64
- |---|---|
65
- | Đặt tên SP, params, URL, response format, error, wiring | `tapi-reference.md` |
66
- | **API trả 200 nhưng dữ liệu rỗng/sai**, hoặc sắp đổi/xoá tham số của một SP đã có module gọi — ghép tham số tAPI khoan dung (thiếu → `NULL`, thừa → bỏ qua, **không bao giờ báo lỗi**) | `tapi-reference.md` §2 |
67
- | **Đọc HTTP header trong SP** (`User-Agent`, `Cookie`, `X-Forwarded-For`, IP client, thiết bị/trình duyệt) — họ `@sys_header_*`, mỗi dấu `-` đổi thành `_` | `tapi-reference.md` §2 |
68
- | Kiểm tra quyền trong SP (5 pattern, `@sys_SystemRight`, `getSystemRight`) | `tapi-permission-patterns.md` |
69
- | Upload/download/xem file qua SP (`spAPIFILE_`, `fileContent`, `tblFileData`) | `tapi-file-api.md` |
70
- | Hàm SQL CLR: httpCall, sendMail, ImageResize, FileReader, RegexMatch... | `sql-clr-functions.md` |
71
-
72
- ## Phân quyền người dùng
73
-
74
- | Tình huống | Load file |
75
- |---|---|
76
- | Khái niệm `SystemRight` (cấp bậc) vs `FunctionRight` (quyền theo chức năng), `v-if`/menu `right`, và 8 tool quản lý định nghĩa quyền (`right_system_list/new/update/delete`, `right_function_list/new/update/delete`) | `permission-system.md` |
77
- | **Sắp gác một control/menu/SP bằng mã quyền** — mã đó có tồn tại thật không, tạo thế nào | `permission-system.md` (§"mã quyền phải TỒN TẠI trước khi đem gác") |
78
- | Kiểm tra quyền trong thân SP (5 pattern SQL) | `tapi-permission-patterns.md` |
1
+ # FUI Reference Router (INDEX)
79
2
 
80
- ## Database
3
+ Routing only; rules live in target files. Printed by `fui skill get` with SKILL.md. Before any task, find the row and load the file — never rely on memory.
81
4
 
82
- | Tình huống | Load file |
83
- |---|---|
84
- | **Database CHƯA tồn tại** — tạo DB SQL Server mới, hai loại tài khoản SQL, đăng ký alias tAPI vào `acc` | `project-provisioning.md` |
85
- | **Sắp chạy `CREATE DATABASE` / `CREATE LOGIN`** — kiểm quyền cấp máy chủ trước (`sysadmin`, hoặc `CREATE ANY DATABASE` + `ALTER ANY LOGIN`); thiếu quyền thì từ chối chứ đừng chạy thử | `project-provisioning.md` §Bước 0 |
86
- | Kết nối DB, dbToken, schema, workflow SP | `db-workflow.md` |
87
- | **Project gọi nhiều database** (module.json có `"API": "/{alias}/…"` với nhiều alias khác nhau) — mỗi alias một `db_connect`, tham số `db` chọn kết nối, tool trả MENU khi nhập nhằng | `db-workflow.md` (§1, §4) |
88
- | **SSO xuyên domain** — userToken cùng domain cha dùng được ngay, không cần hỏi lại hay xác minh | `db-workflow.md` §6a |
89
- | **Linked Server** — SP qua ranh giới linked server, quy ước đặt tên `spIO_IN_` / `spIO_OUT_` | `db-workflow.md` §8a |
90
- | Quy tắc thiết kế bảng (đặt tên, PK/FK, cột audit) | `db-table-design.md` |
91
-
92
- ## Quy trình / thiết kế hệ thống
93
-
94
- | Tình huống | Load file |
95
- |---|---|
96
- | **"Tạo dự án mới" / "tạo DB + project FUI mới"** — dựng hạ tầng từ số 0: CREATE DATABASE, tài khoản ứng dụng vs dev, alias `acc`, `project_new`, cấp quyền quản trị. Làm TRƯỚC `system-design.md` | `project-provisioning.md` |
97
- | **Cấp/thu hồi quyền SỬA PROJECT trong IDE FUI** cho một lập trình viên (`UserRight`, 5 tool `project_user_*`) — khác hẳn quyền người dùng cuối ở `permission-system.md` | `project-provisioning.md` (§Bước 6) |
98
- | **Thiết kế cả app nhiều module từ mô tả** (phân rã, schema-first, menu, quyền) | `system-design.md` |
99
- | Tạo một module fullstack (UI + API) — quy trình 6 bước UI-first | `fullstack-workflow.md` |
100
- | Cấu hình project.json: menu, điều hướng, phân quyền, domain | `project-config.md` |
101
-
102
- ## Scripting / kỹ thuật nâng cao
103
-
104
- | Tình huống | Load file |
105
- |---|---|
106
- | **Cần chạy nhiều lệnh có thứ tự** (reset state → reload → báo toast) trong `CALLBACK`/`:action`/`watch`/`THEN` | `controls-patterns.md` §QUY TẮC NỀN (Tier A, đã nạp sẵn) |
107
- | Watcher patterns (v_old, deep-watch, cascading) | `watcher-patterns.md` |
108
- | Kỹ thuật nâng cao (EXE, MAP, expression phức tạp) | `advanced-techniques.md` |
109
- | **Trang trắng / app rỗng dù 0 JS error, 0 Vue warn**, hoặc cần đặt logic phức tạp vào `:attr` `:option` `:config` | `advanced-techniques.md` §1 + chạy `module_validate` |
110
- | **`… is not defined` lúc render**, hoặc một `EXE`/`FUN` "chạy xong mà không làm gì" | `advanced-techniques.md` §2 (hàm phải có thật trong `script.js` — nhớ `module_publish_script`). ⚠️ `module_validate` KHÔNG bắt được ca này, phải `module_simulate({renderUI:true})` |
111
- | Hàm tiện ích FUI có sẵn (openWindow, ajaxCALL, jsonToExcel, groupBy...) | `default-function.md` |
112
- | **Thư viện đã bundled sẵn** (jQuery, lodash, moment, numeral, toast, jquery-confirm) — biết trước khi định thêm CDN. ⚠️ Chỉ đúng với `HTMLOnly=false` | `script-map.md` §0 |
113
- | Bản đồ script FUI (defaultfunction.js, component.js...) | `script-map.md` |
114
- | FUI project bootstrapper (fastproject) | `fastproject.md` |
115
- | Coding standards | `coding-standards.md` |
116
- | Real-time / SignalR (webSocketJoinGroup, webSocket_Send) | `websocket-realtime.md` |
117
-
118
- ## Vận hành / publish / deploy
119
-
120
- | Tình huống | Load file |
121
- |---|---|
122
- | **"new session" / "phiên mới" / "cửa sổ mới"** — mở thêm một phiên Claude Code CLI ở cửa sổ terminal riêng (lấy workspace root động, KHÔNG hard-code đường dẫn) | `new-session.md` |
123
- | Mức độ an toàn của từng MCP tool (R/M, Safe/Confirm/Destructive), strict mode, `db_sp_verify`, error log | `tools-registry.md` |
124
- | Checklist definition-of-done trước khi publish (kèm bước `module_validate` + `module_outline` + `module_simulate` + `db_sp_verify` tĩnh) | `verification.md` |
125
- | **UI hỏng mà chưa biết vì sao — chọn tầng kiểm chứng nào cho rẻ nhất** (ma trận triệu chứng → tầng; đọc TRƯỚC khi chạy `renderUI`, và đọc lại khi đã render ≥2 lượt mà chưa khá hơn) | `verification.md` §Chọn tầng kiểm chứng |
126
-
127
- ---
5
+ Load: `fui skill ref references/a.md references/b.md` (several at once OK).
128
6
 
129
- ## Design system
7
+ ## Tier A (load first via `fui skill ref`)
8
+
9
+ - `controls-patterns.md` — foundation: action engine (§CORE RULE: one `{}` = one command; sequential commands = array `[{…},{…}]`), value resolution, key notation, layout grid
10
+ - `module-structure.md` — module/project files, layout rules
11
+ - `INDEX.md` — this router
12
+
13
+ ## Foundations (read early)
14
+
15
+ - FUI anatomy, Project→Module hierarchy (import/component/set merge), runtime, vueData/v_Set → `platform-architecture.md`
16
+ - module.json's 4 parts (data/watch/controls/set) → `module-json-anatomy.md`
17
+ - `HTMLOnly: true`: server embeds NO library (Vue/Vuetify/jQuery/lodash/MDI/`projectdefaultstyle.css` absent); declare all in the module; `script-map.md` does NOT apply → `module-structure.md` §HTMLOnly=true: KHÔNG có thư viện nào được nhúng sẵn
18
+
19
+ ## UI / components
20
+
21
+ - Allowed control class/prop/style (never invent styles) → `controls-styling-vocabulary.md`
22
+ - Area with its own scrollbar / user wants a restyled scrollbar → built-in class `fpScrollbar`, NEVER hand-write `::-webkit-scrollbar`; put it only on the element that actually scrolls, NOT nested → `controls-styling-vocabulary.md` §Scrollbar
23
+ - Start UI, pick component → `component-quickref.md`
24
+ - `data[]`: three element kinds, order state → named action → auto-startup → `module-data-patterns.md` (value resolution, nested keys: `controls-patterns.md` §0/§1)
25
+ - Real patterns (data/watch/toolbar/filter/permission) → `ui-patterns.md`
26
+ - Multi-control row / right-aligned buttons: `shrink` on every column except `v-spacer`; `w` in px → `controls-patterns.md`
27
+ - f-table: datatable display (list/CRUD via form dialog, readonly or `:update-api`) + cell controls t-check/t-button/t-select/t-menu, ctrl-update, show-select, chip-group → `ui-table-cell-patterns.md`
28
+ - Table deep-dive: all props, header types, auto-headers without `:headers`, `sum-format` (object = total row in table / string = text line below), readonly, **Excel export button `excel`** (`true` = raw data / `"UI"` = rows and columns as displayed: filtered, sorted, header names and column count, but values stay raw and unformatted) → `component-table.md`
29
+ - f-sheet: Excel-style in-place entry (paste from Excel, no dialog), built-in (AG Grid); NEVER hand-build an entry grid in `uc-*.vue`; import, props, columns, API wiring → `fsheet.md`
30
+ - Popup form (hidden-container, open with row, checkbox-list) → `ui-dialog-patterns.md`
31
+ - Sub-window data exchange (`openWindow`, `#PARENT`/`#Win`) → `ui-crosswindow-patterns.md`
32
+ - page-container, master-detail, v-switch, date init, dynamic label → `ui-layout-patterns.md`
33
+ - Inputs (f-date, f-time, f-search, f-radiobox, text-field…) → `components-input.md`
34
+ - Display (f-label, f-title, f-box, f-header, chip, badge…) → `components-display.md`
35
+ - f-dialog, v-dialog → `components-dialog.md`
36
+ - `uc-*.vue`: scope, props/events, built-in Vuetify classes (no `_injectStyle`), standard dialog, reuse ajaxCALL/confirm/showMessage → `component-design.md`
37
+ - Isolated `uc-*.vue` check (`fui component preview`); push project-level components before rendering the module → `component-design.md`
38
+ - Check existing project-scope components before creating: `{projectId}/COMPONENTS.md` + accumulation loop → `component-design.md` §1a
39
+ - Templates → `ui-templates.md` + `examples/`
40
+ - UI screenshot (from user or `--render`): display bugs, colors, padding/margin, alignment, button placement → `ui-screenshot-review.md`
41
+
42
+ ## Charts / reports
130
43
 
131
- **Hai chế độ tách bạch — xác định TRƯỚC khi viết controls. Chủ sở hữu: `design-modes.md`.**
44
+ - f-echart (Apache ECharts): import, props, config, theme, DataView, `grid` padding, `boundaryGap`, errors → `components-echart.md`
45
+ - Specific chart type + module.json pattern → `echart-templates.md`
46
+ - PDF (f-pdfmake) → `pdfmake.md`
132
47
 
133
- | Chế độ | Khi nào | Nguồn thẩm mỹ |
134
- |---|---|---|
135
- | **App-mode** (mặc định) | Phần mềm quản lý: CRUD, form, danh sách, dashboard nội bộ | **DUY NHẤT** `design_read("fui")` + `controls-styling-vocabulary.md` — CẤM brand DESIGN.md, CẤM style tự chế |
136
- | **Web-mode** | Landing page / trang giới thiệu / công khai (thường `HTMLOnly: true`) | `design_list` → `design_read("<brand>")` theo tone/ngành; CSS tự do trong header.html |
48
+ ## API / SP / tAPI
49
+
50
+ - SP naming, params, URL, response, errors, wiring → `tapi-reference.md`
51
+ - 200 but empty/wrong data, or changing/removing params of an SP a module calls: lenient binding (missing → `NULL`, extra → ignored, never errors) → `tapi-reference.md` §2
52
+ - HTTP headers in SP (`User-Agent`, `Cookie`, `X-Forwarded-For`, client IP, device/browser): `@sys_header_*`, each `-` → `_` → `tapi-reference.md` §2
53
+ - SP permission checks (5 patterns, `@sys_SystemRight`, `getSystemRight`) → `tapi-permission-patterns.md`
54
+ - File upload/download/view (`spAPIFILE_`, `fileContent`, `tblFileData`) → `tapi-file-api.md`
55
+ - SQL CLR: httpCall, sendMail, ImageResize, FileReader, RegexMatch… → `sql-clr-functions.md`
56
+
57
+ ## User permissions
58
+
59
+ - `SystemRight` (level) vs `FunctionRight` (per function), `v-if`/menu `right`, `fui right system|function list/new/update/delete` (8 commands) → `permission-system.md`
60
+ - Guarding control/menu/SP with a right code — it must exist; how to create → `permission-system.md` (§"mã quyền phải TỒN TẠI trước khi đem gác")
61
+ - SQL permission checks in SP body → `tapi-permission-patterns.md`
62
+
63
+ ## Database
64
+
65
+ - DB doesn't exist: new SQL Server DB, two SQL account types, tAPI alias in `acc` → `project-provisioning.md`
66
+ - Before `CREATE DATABASE` / `CREATE LOGIN`: check server rights (`sysadmin`, or `CREATE ANY DATABASE` + `ALTER ANY LOGIN`); if missing, refuse, no trial run → `project-provisioning.md` §Step 0
67
+ - Connection, dbToken, schema, SP workflow → `db-workflow.md`
68
+ - Multiple DBs / an alias repeated across zones: `connectionName` names a readable folder, `apiName` is stored separately, `--db` picks the connection → `db-workflow.md` (§1, §4)
69
+ - Cross-domain SSO: userToken of same parent domain works as-is; don't re-ask/verify → `db-workflow.md` §6a
70
+ - Linked Server SPs, naming `spIO_IN_` / `spIO_OUT_` → `db-workflow.md` §8a
71
+ - Table design (naming, PK/FK, audit columns) → `db-table-design.md`
72
+
73
+ ## Process / system design
74
+
75
+ - New project / new DB + FUI project from zero: CREATE DATABASE, app vs dev accounts, `acc` alias, `fui project new`, admin grant; do BEFORE `system-design.md` → `project-provisioning.md`
76
+ - Grant/revoke IDE project-edit rights for a developer (`UserRight`, `fui user search/list/add/set/remove`); not end-user rights (`permission-system.md`) → `project-provisioning.md` (§Step 6)
77
+ - Multi-module app from a description (decomposition, schema-first, menu, rights) → `system-design.md`
78
+ - One fullstack module, 6-step UI-first → `fullstack-workflow.md`
79
+ - project.json: menu, navigation, permissions, domain → `project-config.md`
80
+
81
+ ## Scripting / advanced
82
+
83
+ - Ordered commands (reset → reload → toast) in `CALLBACK`/`:action`/`watch`/`THEN` → `controls-patterns.md` §CORE RULE
84
+ - v_old, deep-watch, cascading → `watcher-patterns.md`
85
+ - EXE, MAP, complex expressions → `advanced-techniques.md`
86
+ - Blank page with 0 JS errors and 0 Vue warns, or complex logic in `:attr` `:option` `:config` → `advanced-techniques.md` §1 + `fui module validate`
87
+ - `… is not defined` at render, or `EXE`/`FUN` doing nothing → `advanced-techniques.md` §2 (function must exist in `script.js`; `fui module publish script`). ⚠️ `fui module validate` misses this; use `fui module simulate --render`
88
+ - Built-in utilities (openWindow, ajaxCALL, jsonToExcel, groupBy…) → `default-function.md`
89
+ - Bundled libs (jQuery, lodash, moment, numeral, toast, jquery-confirm) — check before adding a CDN; ⚠️ `HTMLOnly=false` only → `script-map.md` §0
90
+ - Script map (defaultfunction.js, component.js…) → `script-map.md`
91
+ - fastproject bootstrapper → `fastproject.md`
92
+ - Coding standards → `coding-standards.md`
93
+ - SignalR (webSocketJoinGroup, webSocket_Send) → `websocket-realtime.md`
94
+
95
+ ## Operations / publish
96
+
97
+ - "new session" / "phiên mới" / "cửa sổ mới": open another Claude Code CLI in its own terminal window (workspace root resolved dynamically, NEVER hard-coded) → `new-session.md`
98
+ - Hand work / instructions to another running Claude session (coordinating several sessions, a multi-AI workflow, parallelizing work per module) — `ListAgents`/`SendMessage` → `new-session.md` §6
99
+ - Per-command safety (R/M, Safe/Confirm/Destructive), strict mode, `fui sp verify`, error log → `tools-registry.md`
100
+ - Pre-publish definition-of-done (`fui module validate` + `fui module outline` + `fui module simulate` + static `fui sp verify`) → `verification.md`
101
+ - UI broken, cause unknown — cheapest verification layer (symptom → layer; read BEFORE `--render`, reread after ≥2 renders without progress) → `verification.md` §Chọn tầng kiểm chứng
102
+
103
+ ## Design system
137
104
 
138
- | Tình huống | Load file |
139
- |---|---|
140
- | Chọn App-mode hay Web-mode, giới hạn `border-radius`, vòng tích luỹ `{projectId}/DESIGN.md` | `design-modes.md` |
141
- | Anatomy dialog/form/bảng màu chuẩn App-mode | tool `design_read("fui")` (không qua `skill_reference_get`) |
105
+ Pick the mode BEFORE writing controls. Owner: `design-modes.md`.
142
106
 
143
- - `{projectId}/DESIGN.md` (nếu có) **ghi đè** quy tắc cùng chủ đề của chế độ đang dùng — kiểm tra trước khi thiết kế.
144
- - User góp ý UI → ghi quy tắc vào `{projectId}/DESIGN.md` (vòng tích luỹ — `design-modes.md` §3).
107
+ - App-mode (default): CRUD, forms, lists, internal dashboards. Source: ONLY `fui design read fui` + `controls-styling-vocabulary.md`; NO brand DESIGN.md, NO custom styles.
108
+ - Web-mode: landing/intro/public pages (usually `HTMLOnly: true`). Source: `fui design list` → `fui design read <brand>` by tone/industry; free CSS in header.html.
109
+ - Mode choice, `border-radius` limits, `{projectId}/DESIGN.md` loop → `design-modes.md`
110
+ - App-mode dialog/form/palette anatomy → `fui design read fui` (not `fui skill ref`)
111
+ - `{projectId}/DESIGN.md`, if present, overrides same-topic rules of the active mode; check before designing.
112
+ - User UI feedback → record rule in `{projectId}/DESIGN.md` (`design-modes.md` §3).
@@ -1,57 +1,60 @@
1
1
  # Advanced FUI Techniques
2
2
 
3
- > File này sở hữu: **kỹ thuật nâng cao: `EXE`, `MAP`, expression phức tạp, luật expression thuần cho `:attr`, luật hàm gọi trong `EXE`/`FUN` phải tồn tại thật**. Action engine cơ bản xem [controls-patterns.md](controls-patterns.md).
4
-
5
- This document captures advanced patterns and techniques for FUI development, extracted from real-world implementations.
3
+ > Owns: **advanced techniques: `EXE`, `MAP`, complex expressions, pure-expression rule for `:attr`, rule that functions called in `EXE`/`FUN` must really exist**. Basic action engine: [controls-patterns.md](controls-patterns.md).
6
4
 
7
5
  ---
8
6
 
9
- ## 1. `:attr` CHỈ NHẬN EXPRESSION THUẦN — không bao giờ nhét statement
7
+ ## 1. `:attr` takes a PURE EXPRESSION — never statements
10
8
 
11
- **Luật cứng.** Mọi giá trị binding trong `module.json` — `:option`, `:config`, `:items`, `:headers`, `:style`, và mọi `v-bind:*` — đi **thẳng vào template compiler của Vue**, nơi chỉ chấp nhận **một biểu thức**. Tuyệt đối không được chứa:
9
+ **Hard rule.** Every binding value in `module.json` — `:option`, `:config`, `:items`, `:headers`, `:style`, every `v-bind:*` — goes **straight to Vue's template compiler**, which accepts **one expression**. Never include:
12
10
 
13
- - `function(){ ... }` hay IIFE `(function(){...})()`
11
+ - `function(){ ... }` or IIFE `(function(){...})()`
14
12
  - `return`
15
13
  - `var` / `let` / `const`
16
- - dấu `;` nối nhiều câu lệnh
14
+ - `;` joining statements
15
+
16
+ ### Why it is worse than it looks
17
17
 
18
- ### Vì sao nghiêm trọng hơn vẻ ngoài của nó
18
+ A statement in `:attr` breaks template compilation and Vue **swallows the error**: **blank page, 0 JS errors, 0 `[Vue warn]`**, no stack trace — found only after many `fui module simulate --render` rounds. That is why `fui module validate` reports it as an **error**, not a warning.
19
19
 
20
- Statement trong `:attr` làm **compile template hỏng**, và Vue **nuốt lỗi đó**: kết quả là **trang trắng với 0 JS error, 0 `[Vue warn]`**. Không có stack trace, không có dòng nào để lần — chỉ mò ra được sau nhiều vòng `module_simulate({renderUI:true})`. Đây là lý do nó là **error** trong `module_validate` chứ không phải warning.
20
+ > Unlike `data[]` / `IN` / `{{ }}`, which go through FUI's `getVueData()` (see [controls-patterns.md](controls-patterns.md) §0 Value Resolution) with their own rules, `:attr` does **not**.
21
21
 
22
- > Khác hẳn `data[]` / `IN` / `{{ }}`: những chỗ đó đi qua `getVueData()` của FUI (xem [controls-patterns.md](controls-patterns.md) §0 Value Resolution) và có luật riêng. `:attr` **không** đi qua đó.
22
+ ### Allowed in `:attr`
23
23
 
24
- ### Được phép trong `:attr`
24
+ | Form | Example |
25
+ | ---------------------------------- | ------------------------------------------------------- |
26
+ | Object / array literal | `":config": "{ height: 300, legend: { show: true } }"` |
27
+ | Ternary | `":color": "ok ? 'primary' : 'warning'"` |
28
+ | Arrow `.map` / `.filter` chains | `":items": "ds.filter(x => x.Active).map(x => x.Name)"` |
29
+ | Property access / vueData variable | `":option": "optThe"` |
25
30
 
26
- | Dạng | Ví dụ |
27
- |---|---|
28
- | Object / array literal | `":config": "{ height: 300, legend: { show: true } }"` |
29
- | Ternary | `":color": "ok ? 'primary' : 'warning'"` |
30
- | Chuỗi arrow `.map` / `.filter` | `":items": "ds.filter(x => x.Active).map(x => x.Name)"` |
31
- | Truy cập thuộc tính / biến vueData | `":option": "optThe"` |
31
+ ### Complex logic → `script.js` + `EXE`
32
32
 
33
- ### Logic phức tạp → chuyển sang `script.js` + `EXE`
33
+ Multi-step transforms, temp variables, loops, complex conditions → **not in `:attr`**:
34
34
 
35
- Nhiều bước biến đổi, biến trung gian, vòng lặp, điều kiện phức tạp → **đừng đặt trong `:attr`**. Bốn bước:
35
+ 1. Write a plain function in `script.js`: `function tenHam(){ ... }`
36
+ 2. It **assigns directly to `vueData.xxx`** (does not `return` a value for JSON)
37
+ 3. Call it via `EXE` — usually in the data-loading action's `CALLBACK`: `"EXE": "tenHam()"`
38
+ 4. `:attr` in `module.json` only points at the variable: `":option": "optThe"`
36
39
 
37
- 1. Viết một hàm thường trong `script.js`: `function tenHam(){ ... }`
38
- 2. Hàm **gán thẳng vào `vueData.xxx`** (không `return` giá trị cho JSON đọc)
39
- 3. Gọi hàm qua `EXE` — thường trong `CALLBACK` của action nạp dữ liệu: `"EXE": "tenHam()"`
40
- 4. `:attr` trong `module.json` chỉ trỏ tới biến đó: `":option": "optThe"`
40
+ ❌ **Wrong** — IIFE in `:attr`:
41
41
 
42
- ❌ **Sai** — IIFE trong `:attr`:
43
42
  ```json
44
43
  ":option": "(function(){ var src = vueData.ds.filter(r => r.id===1); return { series:[{data: src}] }; })();"
45
44
  ```
46
45
 
47
- ✅ **Đúng**:
46
+ ✅ **Right**:
47
+
48
48
  ```javascript
49
49
  // script.js
50
50
  function buildChart() {
51
- var src = vueData.ds.filter(function (r) { return r.id === 1; });
52
- vueData.optThe = { series: [{ data: src }] };
51
+ var src = vueData.ds.filter(function (r) {
52
+ return r.id === 1;
53
+ });
54
+ vueData.optThe = { series: [{ data: src }] };
53
55
  }
54
56
  ```
57
+
55
58
  ```json
56
59
  // module.json — action nạp dữ liệu
57
60
  "CALLBACK": { "EXE": "buildChart()" },
@@ -59,102 +62,107 @@ function buildChart() {
59
62
  ":option": "optThe"
60
63
  ```
61
64
 
62
- `:option` khai báo trong `data[]` là `{}` để lần render đầu không vỡ; `buildChart()` gán bản thật sau khi API trả về.
65
+ Declare `:option`'s variable as `{}` in `data[]` so the first render doesn't break; `buildChart()` assigns the real value after the API returns.
63
66
 
64
- ### Chẩn đoán trang trắng khi "0 JS error, 0 Vue warn"
67
+ ### Diagnosing a blank page with "0 JS error, 0 Vue warn"
65
68
 
66
- Triệu chứng đó **không phải lỗi runtime** — nghi **compile template trong `:attr`** trước tiên, đừng đi tìm trong `script.js` hay action engine.
69
+ Not a runtime error — suspect **`:attr` template compilation** first, not `script.js` or the action engine.
67
70
 
68
- Cách khoanh vùng nhanh: tạm thay biểu thức nghi ngờ bằng một giá trị tĩnh đơn giản (`":option": "{}"` hoặc bỏ hẳn attr đó) rồi render lại. **Trang hiện lại ⇒ chính biểu thức đó là thủ phạm.** Lặp lại cho từng `:attr` khả nghi cho tới khi khoanh đúng một cái.
71
+ Isolate: replace a suspect expression with a simple static value (`":option": "{}"` or remove the attr) and re-render. **Page comes back ⇒ that expression is the culprit.** Repeat per suspect `:attr` until one remains.
69
72
 
70
- Chạy `module_validate` trước khi render sẽ bắt được hầu hết các ca này ở dạng error, không cần mò.
73
+ Running `fui module validate` before rendering catches most of these as errors.
71
74
 
72
75
  ---
73
76
 
74
- ## 2. Hàm gọi trong `EXE` / `FUN` phải TỒN TẠI THẬT trong `script.js`
77
+ ## 2. Functions called in `EXE` / `FUN` must REALLY EXIST
75
78
 
76
- **Luật cứng.** `"EXE": "buildChart()"` và `"FUN": "buildChart"` chỉ chạy được nếu `buildChart` là một hàm **toàn cục có thật** lúc runtime — nghĩa là khai trong `{moduleDir}/script.js`, trong một file import `.js`, hoặc là hàm sẵn có của nền tảng ([default-function.md](default-function.md), [script-map.md](script-map.md)).
79
+ **Hard rule.** `"EXE": "buildChart()"` and `"FUN": "buildChart"` work only if `buildChart` is a **real global function** at runtime — declared in `{moduleDir}/script.js`, in an imported `.js` file, or a platform built-in ([default-function.md](default-function.md), [script-map.md](script-map.md)).
77
80
 
78
- Đây là mặt kia của §1: §1 bảo *"logic phức tạp thì đẩy sang `script.js` rồi gọi qua `EXE`"* — và bước đẩy đó **rất hay bị quên nửa sau**. Module.json được sửa, `EXE` được viết, `module_publish_json` chạy xong; `script.js` thì không ai viết và `module_publish_script` không ai gọi.
81
+ This is the flip side of §1: moving logic to `script.js` and calling via `EXE` **often loses its second half**. `module.json` is edited, `EXE` written, `fui module publish json` run — but nobody writes `script.js` or runs `fui module publish script`.
79
82
 
80
- ### Vì sao không có gì báo cho bạn biết
83
+ ### Why nothing tells you
81
84
 
82
- Hai lệnh, hai kiểu hỏng, **cả hai đều không nói tên hàm ở chỗ dễ thấy**:
85
+ Two commands, two failure modes, **neither shows the function name prominently**:
83
86
 
84
- | Lệnh | Cơ chế | Biểu hiện khi hàm thiếu |
85
- |---|---|---|
86
- | `EXE` | Chạy qua `templateCompiled(\`<% … %>\`)` — tức lodash `_.template`. Do lỗi toán tử phẩy ở `fastproject-3.0.js:490`, **object dữ liệu không bao giờ được truyền vào**, nên định danh trần trong chuỗi EXE phân giải thẳng vào **global** | `ReferenceError: buildChart is not defined` — chỉ lộ ra ở `module_simulate({renderUI:true})`, và ở đó nó chỉ là **"1 JS error"** trong một report dài |
87
- | `FUN` | `runFunction()` tra `window[obj.FUN]`, không thấy thì `console.log("Func:", …, "not found")` rồi **đi tiếp** | **Hỏng hoàn toàn im lặng.** Không error, không `[Vue warn]`, action vẫn "chạy xong" — chỉ là không làm gì cả |
87
+ | Command | Mechanism | Symptom when missing |
88
+ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
89
+ | `EXE` | Runs through `templateCompiled(\`<% … %>\`)`— lodash`_.template`. A comma-operator bug at `fastproject-3.0.js:490` means **the data object is never passed**, so bare identifiers resolve to **global** | `ReferenceError: buildChart is not defined` — shows only in `fui module simulate --render`, as just **"1 JS error"** in a long report |
90
+ | `FUN` | `runFunction()` looks up `window[obj.FUN]`; if absent, `console.log("Func:", …, "not found")` and **continues** | **Completely silent.** No error, no `[Vue warn]`, the action "finishes" and does nothing |
88
91
 
89
- Giá thật đã đo trong log: một module tốn **36 lượt `renderUI` liên tiếp trong 5 ngày** vì đúng lớp lỗi này (`buildKPI8Columns is not defined`).
92
+ Measured cost: one module burned **36 consecutive `--render` runs over 5 days** on this bug class (`buildKPI8Columns is not defined`).
90
93
 
91
- ### Tầng bắt được: **`module_simulate({ renderUI: true })`** — và chỉ tầng đó
94
+ ### The only layer that catches it: **`fui module simulate --render`**
92
95
 
93
- `module_validate` **KHÔNG** kiểm việc này: nó không đọc `script.js`. (Đã từng có một luật tĩnh làm việc đó, đã gỡ — để không báo oan, luật phải biết trước **mọi** hàm toàn cục của nền tảng, và danh sách đó không bao giờ nuôi đủ; mỗi tên bỏ sót là một lần chặn publish một module chạy được.) `module_simulate` ở chế độ vm cũng không phải tầng bắt được — nó không nạp `script.js` vào sandbox nên báo ReferenceError cho **mọi** module dùng hàm `script.js`, kể cả module đúng.
96
+ `fui module validate` does **NOT** check this: it does not read `script.js`. (A static rule once did, and was removed — to avoid false positives it had to know **every** platform global, a list never complete; each missing name blocked publishing a working module.) `fui module simulate` in vm mode doesn't catch it either — it doesn't load `script.js` into the sandbox, so it reports ReferenceError for **every** module using `script.js` functions, even correct ones.
94
97
 
95
- Nên đường kiểm chứng là **renderUI**: trình duyệt thật ném `ReferenceError: buildChart is not defined`, và từ nay **mọi JS error đều làm tool trả `isError`** (không riêng lỗi lúc init — lỗi phát sinh khi bấm nút cũng tính). Câu lỗi nằm trong khối `═══ CHẨN ĐOÁN ═══` ở **đầu** report, dòng `[MODULE]`.
98
+ So verify with **`--render`**: the real browser throws `ReferenceError: buildChart is not defined`, and **every JS error now makes the result an error (`isError`)** — not only init errors; errors from button clicks count too. The message is in the `═══ CHẨN ĐOÁN ═══` block at the **top** of the report, line `[MODULE]`.
96
99
 
97
- ⚠️ **Vế `FUN` thì renderUI cũng không bắt được** — `runFunction` không thấy hàm thì `console.log` rồi đi tiếp, không ném gì cả. Với `FUN` phải **tự soát tên hàm** đối chiếu `script.js`; triệu chứng duy nhất là "action chạy xong mà không có gì xảy ra".
100
+ ⚠️ **`--render` does not catch the `FUN` case** — `runFunction` just `console.log`s and continues, throwing nothing. For `FUN`, **check function names against `script.js` yourself**; the only symptom is "action finishes, nothing happens".
98
101
 
99
- ### Cách sửa
102
+ ### Fix
100
103
 
101
- 1. Viết hàm trong `script.js`: `function buildChart(){ … vueData.optThe = …; }`
102
- 2. **`module_publish_script`** — bước hay bị quên nhất. `module_publish_json` **không** đẩy `script.js`.
103
- 3. Gõ nhầm tên thì sửa tên, đừng thêm hàm rỗng cho hết lỗi.
104
+ 1. Write the function in `script.js`: `function buildChart(){ … vueData.optThe = …; }`
105
+ 2. **`fui module publish script`** — the most-forgotten step. `fui module publish json` does **not** push `script.js`.
106
+ 3. Typo → fix the name; never add an empty function to silence the error.
104
107
 
105
108
  ---
106
109
 
107
110
  ## 3. Advanced Logic & Scripting
108
111
 
109
- FUI's JSON-based logic has limitations. Use `script.js` for complex operations.
112
+ JSON logic is limited; use `script.js` for complex operations.
113
+
114
+ ### Computed properties workaround
110
115
 
111
- ### Computed Properties Workaround
112
- FUI `module.json` does not natively support computed properties.
113
- **Solution:** Define calculation functions in `script.js` and call them directly in `module.json`.
116
+ `module.json` has no native computed properties. Define calculation functions in `script.js` and call them from `module.json`.
114
117
 
115
118
  **script.js**:
119
+
116
120
  ```javascript
117
121
  function getTongTien() {
118
- return vueData.items.reduce((sum, item) => sum + (item.amount || 0), 0);
122
+ return vueData.items.reduce((sum, item) => sum + (item.amount || 0), 0);
119
123
  }
120
124
  ```
121
125
 
122
126
  **module.json**:
127
+
123
128
  ```json
124
129
  {
125
130
  "innerHTML": "Total: {{getTongTien().toLocaleString()}} VNĐ"
126
131
  }
127
132
  ```
128
133
 
129
- ### Complex Validation
130
- Avoid writing long logic strings in JSON. Move validation logic to `script.js`.
134
+ ### Complex validation
135
+
136
+ Don't write long logic strings in JSON; move validation to `script.js`.
131
137
 
132
138
  **script.js**:
139
+
133
140
  ```javascript
134
141
  function validateStep1() {
135
- const d = vueData;
136
- if (!d.name || !d.email) {
137
- alert("Missing required fields!");
138
- return false;
139
- }
140
- return true;
142
+ const d = vueData;
143
+ if (!d.name || !d.email) {
144
+ alert("Missing required fields!");
145
+ return false;
146
+ }
147
+ return true;
141
148
  }
142
149
 
143
150
  function nextStep() {
144
- if (vueData.step === 1 && !validateStep1()) return;
145
- vueData.step++;
151
+ if (vueData.step === 1 && !validateStep1()) return;
152
+ vueData.step++;
146
153
  }
147
154
  ```
148
155
 
149
156
  **module.json**:
157
+
150
158
  ```json
151
159
  "v-on:click": "nextStep()"
152
160
  ```
153
161
 
154
- ### Action Binding
155
- You can bind direct JS functions to events instead of using the `CALL` action protocol if needed for simple UI logic.
162
+ ### Action binding
163
+
164
+ For simple UI logic you may bind JS functions to events directly instead of the `CALL` action protocol.
156
165
 
157
166
  ```json
158
167
  "v-on:click": "prevBuoc()"
159
168
  ```
160
-