@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,296 +1,262 @@
1
- # FUI Script Map (Quick Lookup)
1
+ # FUI Script Map
2
2
 
3
- > File này sở hữu: **thư viện bundled sẵn (§0) và bản đồ source script FUI — hàm nào nằm ở file/dòng nào**. Cách dùng từng hàm xem [default-function.md](default-function.md).
3
+ > Owns: **bundled libraries (§0) and the FUI script source map — which function lives in which file/line**. Function usage: [default-function.md](default-function.md). Read framework sources with `fui library <name>`.
4
4
 
5
- Mục tiêu: tra cứu nhanh "hàm nào dùng để làm gì" theo từng file runtime trong `scripts/`.
6
-
7
- > **Bản đồ file theo framework** — tra `_moduleInfo.json.Framework` (`"V2"` hoặc `"V3"`) rồi mở đúng cột:
5
+ > **File by framework** — check `_moduleInfo.json.Framework` (`"V2"` or `"V3"`):
8
6
  >
9
- > | Nội dung | File V2 | File V3 |
10
- > |---|---|---|
11
- > | Core engine (action, API, layout) | `scripts/fastproject.js` | `scripts/fastproject-3.0.js` |
12
- > | Utility layer (router, export, auth, WS) | `scripts/defaultfunction.js` | `scripts/defaultfunction-3.0.js` |
13
- > | Component registry (`f-*`, dialog, editor...) | `scripts/component.js` | `scripts/component-3.0.js` |
14
- > | Table system (`f-table`, `t-*`) | `scripts/componentTable.js` | `scripts/componentTable-3.0.js` |
15
- > | Biểu đồ (`f-echart`) | `scripts/fechart.js` | `scripts/fechart.js` |
16
- > | Bảng tính nhập liệu (`f-sheet`) | `scripts/fsheet.js` (dùng chung, xem §5) | `scripts/fsheet.js` (dùng chung, xem §5) |
17
-
18
- Lưu ý dùng đúng chuẩn FUI:
19
- - Metadata chính là `module.json` (không dùng `controls.json`).
20
- - Logic action gọi qua `CALL(vueData.actionName)` hoặc Action Protocol.
21
- - Layout trong `controls` luôn theo grid wrapper `container > rows > cols`.
22
- - Event trong JSON dùng `v-on:...` (không dùng `@...`).
7
+ > | Content | V2 file | V3 file |
8
+ > | --------------------------------------------- | -------------------------------- | -------------------------------- |
9
+ > | Core engine (action, API, layout) | `scripts/fastproject.js` | `scripts/fastproject-3.0.js` |
10
+ > | Utilities (router, export, auth, WS) | `scripts/defaultfunction.js` | `scripts/defaultfunction-3.0.js` |
11
+ > | Component registry (`f-*`, dialog, editor...) | `scripts/component.js` | `scripts/component-3.0.js` |
12
+ > | Table system (`f-table`, `t-*`) | `scripts/componentTable.js` | `scripts/componentTable-3.0.js` |
13
+ > | Chart (`f-echart`) | `scripts/fechart.js` | `scripts/fechart.js` |
14
+ > | Input sheet (`f-sheet`) | `scripts/fsheet.js` (shared, §5) | `scripts/fsheet.js` (shared, §5) |
15
+
16
+ FUI conventions:
17
+
18
+ - Metadata is `module.json` (not `controls.json`).
19
+ - Call action logic via `CALL(vueData.actionName)` or the Action Protocol.
20
+ - `controls` layout is always `container > rows > cols`.
21
+ - JSON events use `v-on:...` (not `@...`).
23
22
  - Literal forcing (`` ` `` or `'...'`) is for Action `IN` mapping, not normal static component props.
24
23
 
25
- ## Table of Contents
26
- - [0) Thư viện nhúng sẵn (FUI V2)](#0-thu-vien-nhung-san-fui-v2)
27
- - [1) scripts/fastproject.js](#1-scriptsfastprojectjs)
28
- - [2) scripts/defaultfunction.js](#2-scriptsdefaultfunctionjs)
29
- - [3) scripts/component.js](#3-scriptscomponentjs)
30
- - [4) scripts/componentTable.js](#4-scriptscomponenttablejs)
31
- - [4b) scripts/componentTable-3.0.js](#4b-scriptscomponenttable-30js)
32
- - [5) scripts/fsheet.js](#5-scriptsfsheetjs)
33
- - [6) Tra cứu theo tác vụ](#6-tra-cuu-theo-tac-vu)
34
-
35
- ## 0) Thư viện nhúng sẵn (FUI V2)
36
-
37
- FUI tự động nhúng các thư viện sau vào **mọi** module — **không cần import thêm**. Luôn tận dụng
38
- chúng thay vì thêm thư viện tương đương. **Không thêm CDN** cho bất kỳ thư viện nào trong danh sách
39
- — thêm lại gây xung đột.
40
-
41
- > ⛔ **Cả mục này CHỈ đúng với `HTMLOnly=false`.** Module `HTMLOnly: true` không được nhúng sẵn một
42
- > byte nào — không Vue, không Vuetify, không jQuery, không lodash, không MDI, không
43
- > `projectdefaultstyle.css`. Ở đó thêm CDN **không phải là trùng lặp** mà là điều kiện để trang chạy:
44
- > xem [module-structure.md §HTMLOnly=true: KHÔNG có thư viện nào được nhúng sẵn](module-structure.md#htmlonlytrue-không-có-thư-viện-nào-được-nhúng-sẵn).
24
+ ## 0) Bundled libraries (FUI V2)
45
25
 
46
- ### CSS (tự động load)
26
+ Auto-loaded into **every** module — no import needed; use them instead of equivalents. **Never add a CDN** for any of them — re-adding causes conflicts.
47
27
 
48
- Roboto font · Material Design Icons (`mdi-*`) · Vuetify CSS · vue-toast-notification CSS · jquery-confirm CSS · FUI projectdefaultstyle.css
28
+ > ⛔ **Applies ONLY to `HTMLOnly=false`.** `HTMLOnly: true` modules get nothing preloaded (no Vue, Vuetify, jQuery, lodash, MDI, `projectdefaultstyle.css`); there CDNs are **required**: see [module-structure.md §HTMLOnly=true: KHÔNG có thư viện nào được nhúng sẵn](module-structure.md).
49
29
 
50
- ### JavaScript globals
30
+ CSS: Roboto · Material Design Icons (`mdi-*`) · Vuetify · vue-toast-notification · jquery-confirm · FUI projectdefaultstyle.css
51
31
 
52
- | Global | Thư viện | Công dụng |
53
- |---|---|---|
54
- | `$`, `jQuery` | jQuery 3.6.0 | DOM, AJAX |
55
- | `$.confirm()` / `$.dialog()` | jquery-confirm | Dialog xác nhận / thông báo có style (thay cho `window.confirm`) |
56
- | `_` | Lodash 4.17 | Utility: sort, filter, group, clone array/object |
57
- | `moment` | Moment.js (vi) | Parse và format ngày giờ, locale tiếng Việt sẵn |
58
- | `numeral` | Numeral.js | Format số và tiền tệ |
59
- | `Vue.$toast` | vue-toast-notification | Toast thông báo góc màn hình |
32
+ | Global | Library | Use |
33
+ | ---------------------------- | ---------------------- | -------------------------------------------- |
34
+ | `$`, `jQuery` | jQuery 3.6.0 | DOM, AJAX |
35
+ | `$.confirm()` / `$.dialog()` | jquery-confirm | Styled dialogs (instead of `window.confirm`) |
36
+ | `_` | Lodash 4.17 | Array/object utils |
37
+ | `moment` | Moment.js (vi) | Dates, Vietnamese locale preset |
38
+ | `numeral` | Numeral.js | Number/currency format |
39
+ | `Vue.$toast` | vue-toast-notification | Toasts |
60
40
 
61
- ### FUI built-in JS (luôn load sau các thư viện trên)
62
-
63
- `defaultfunction.js` — hàm tiện ích FUI (`jsonToExcel`, `pushRouter`, `openWindow`, `CALL`, `confirm`, `showMessage`, ...)
64
- `component.js` — đăng ký toàn bộ FUI components (`f-table`, `f-form`, `f-echart`, ...)
65
- `componentTable.js` — FUI table helpers · `fastproject.js` — FUI project bootstrapper
66
-
67
- ### Ví dụ dùng phổ biến trong FUI
41
+ FUI JS (loaded after the above): `defaultfunction.js` (`jsonToExcel`, `pushRouter`, `openWindow`, `CALL`, `confirm`, `showMessage`, ...) · `component.js` (all `f-*`: `f-table`, `f-form`, `f-echart`, ...) · `componentTable.js` (table helpers) · `fastproject.js` (bootstrapper).
68
42
 
69
43
  ```js
70
44
  // Toast thông báo
71
- Vue.$toast.success('Lưu thành công', { position: 'top' });
72
- Vue.$toast.error('Có lỗi xảy ra', { position: 'top' });
45
+ Vue.$toast.success("Lưu thành công", { position: "top" });
46
+ Vue.$toast.error("Có lỗi xảy ra", { position: "top" });
73
47
 
74
48
  // Dialog xác nhận (FUI wrapper — dùng hàm confirm() từ defaultfunction.js)
75
49
  confirm({
76
- title: 'Xác nhận xóa',
77
- message: 'Bạn có chắc muốn xóa không?',
78
- action: function() { /* xử lý khi OK */ }
50
+ title: "Xác nhận xóa",
51
+ message: "Bạn có chắc muốn xóa không?",
52
+ action: function () {
53
+ /* xử lý khi OK */
54
+ },
79
55
  });
80
56
 
81
57
  // Dialog thông báo (FUI wrapper)
82
- showMessage({ title: 'Thông báo', message: 'Đã lưu thành công' });
58
+ showMessage({ title: "Thông báo", message: "Đã lưu thành công" });
83
59
 
84
60
  // Lodash — dùng trong script.js / vueData
85
- _.find(vueData.list, { id: 5 })
86
- _.groupBy(vueData.data, 'loai')
87
- _.sumBy(items, 'soLuong')
88
- _.cloneDeep(vueData.formData)
89
- _.debounce(fn, 300)
61
+ _.find(vueData.list, { id: 5 });
62
+ _.groupBy(vueData.data, "loai");
63
+ _.sumBy(items, "soLuong");
64
+ _.cloneDeep(vueData.formData);
65
+ _.debounce(fn, 300);
90
66
 
91
67
  // Moment — format ngày
92
- moment(val).format('DD/MM/YYYY')
93
- moment(val).format('DD/MM/YYYY HH:mm')
94
- moment().subtract(7, 'days').format('YYYY-MM-DD')
68
+ moment(val).format("DD/MM/YYYY");
69
+ moment(val).format("DD/MM/YYYY HH:mm");
70
+ moment().subtract(7, "days").format("YYYY-MM-DD");
95
71
 
96
72
  // Numeral — format số
97
- numeral(value).format('0,0') // 1,234,567
98
- numeral(value).format('0,0.0') // 1,234,567.8
99
- numeral(_.sumBy(items, key)).format('0,0') // tổng cột trong bảng
73
+ numeral(value).format("0,0"); // 1,234,567
74
+ numeral(value).format("0,0.0"); // 1,234,567.8
75
+ numeral(_.sumBy(items, key)).format("0,0"); // tổng cột trong bảng
100
76
  ```
101
77
 
102
- > Component `f-*` nào cần import thêm JS/CSS ngoài danh sách trên: xem
103
- > [component-quickref.md](component-quickref.md) §Components cần import JS/CSS.
78
+ > `f-*` needing extra JS/CSS: [component-quickref.md](component-quickref.md) §Components needing JS/CSS imports.
104
79
 
105
80
  ## 1) scripts/fastproject.js — V3: fastproject-3.0.js
106
81
 
107
- Vai trò: core engine để khởi tạo module, dựng DOM từ `module.json.controls`, chạy action, map data và gọi API.
108
-
109
- Luồng khởi tạo chính:
110
- 1. `$(document).ready` -> `loadModuleInfo()`
111
- 2. `loadModuleInfo()` -> merge config + đọc URL/user info
112
- 3. `createModuleDom()` -> `runAction($moduleUI.data)` + render controls
113
- 4. `createWatch()` -> gắn watcher từ `$moduleUI.watch`
114
- 5. Vue instance mount và module chạy
115
-
116
- | Line | Hàm | Dùng để làm gì |
117
- |---:|---|---|
118
- | 65 | `buildParamURL()` | Đọc query string và đẩy params vào `vueData`. |
119
- | 77 | `loadModuleInfo()` | Nạp config project/module, user info, chuẩn bị tạo app. |
120
- | 122 | `createModuleDom()` | Tạo layout Vue chính, render controls, init watch. |
121
- | 210 | `buildModuleUI(controlsList, target)` | Recursively build UI từ JSON controls. |
122
- | 233 | `buildControl(controlsList, flex, target)` | Render từng control, bind attr/event/import. |
123
- | 299 | `addImport(importArr)` | Nạp script/css phụ thuộc theo control. |
124
- | 310 | `createWatch_Data(obj)` | Khởi tạo dữ liệu cho watch config. |
125
- | 320 | `createWatch(obj)` | Gắn watcher Vue theo config `watch`. |
126
- | 345 | `buildVisualValForObj(controlAttr, target)` | Bind giá trị động vào attr control. |
127
- | 373 | `runAction(obj, includeData)` | Action engine tổng: chạy object/array action. |
128
- | 407 | `vueAction(objAction, includeData, callBack)` | Chạy 1 action cụ thể (IF/API/CALL/EXE/...). |
129
- | 485 | `mapData(map, target, src, includeData)` | Map dữ liệu giữa object theo rule FUI. |
130
- | 527 | `defProp(obj)` | Chuẩn hoá property object theo context. |
131
- | 537 | `bindData(obj)` | Resolve biến động (string/object) từ context hiện tại. |
132
- | 542 | `getVueData(key, src)` | Lấy value theo path (`vueData.x.y`, `item.x`, template...). Literal forcing is for `IN` mapping; static component props without `:` are already plain strings. |
133
- | 578 | `setValue(target, key, value, srcData, index)` | Gán dữ liệu theo path vào target object/window. |
134
- | 612 | `bindDataToString(str, data)` | Resolve template string với dữ liệu runtime. |
135
- | 619 | `templateCompiled(str, data)` | Compile template lodash-style cho chuỗi động. |
136
- | 624 | `getWindowData(value)` | Lấy dữ liệu từ window/iframe context. |
137
- | 638 | `setWindowData(key, value)` | Set dữ liệu cho window/iframe context. |
138
- | 657 | `runFunction(obj, callback)` | Gọi function JS đã khai báo theo action config. |
139
- | 665 | `tableActionEvent(ctrl)` | Xử lý action event liên quan table/control. |
140
- | 687 | `callAPI(objApi, callBack, includeData)` | Gọi API theo cấu hình action (`IN/OUT/CALLBACK`). |
141
- | 743 | `loginFUN()` | Luồng đăng nhập/chuyển hướng login. |
142
- | 761 | `errorMess(code, message)` | Hiển thị lỗi chuẩn theo status/message. |
82
+ Core engine: init module, build DOM from `module.json.controls`, run actions, map data, call APIs.
83
+
84
+ Init: `$(document).ready` → `loadModuleInfo()` (merge config, read URL/user info) → `createModuleDom()` (`runAction($moduleUI.data)` + render controls) → `createWatch()` (watchers from `$moduleUI.watch`) → Vue mounts.
85
+
86
+ | Line | Function | Purpose |
87
+ | ---: | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
88
+ | 65 | `buildParamURL()` | Query string → `vueData` |
89
+ | 77 | `loadModuleInfo()` | Load project/module config, user info |
90
+ | 122 | `createModuleDom()` | Main layout, render controls, init watch |
91
+ | 210 | `buildModuleUI(controlsList, target)` | Recursive UI from JSON controls |
92
+ | 233 | `buildControl(controlsList, flex, target)` | One control: attr/event/import |
93
+ | 299 | `addImport(importArr)` | Load control script/css deps |
94
+ | 310 | `createWatch_Data(obj)` | Init watch data |
95
+ | 320 | `createWatch(obj)` | Attach watchers from `watch` |
96
+ | 345 | `buildVisualValForObj(controlAttr, target)` | Bind dynamic values into attrs |
97
+ | 373 | `runAction(obj, includeData)` | Action engine (object/array) |
98
+ | 407 | `vueAction(objAction, includeData, callBack)` | One action (IF/API/CALL/EXE/...) |
99
+ | 485 | `mapData(map, target, src, includeData)` | Map data between objects |
100
+ | 527 | `defProp(obj)` | Normalize object props for context |
101
+ | 537 | `bindData(obj)` | Resolve dynamic string/object |
102
+ | 542 | `getVueData(key, src)` | Value by path (`vueData.x.y`, `item.x`, template...). Literal forcing is for `IN` mapping; static props without `:` are already plain strings. |
103
+ | 578 | `setValue(target, key, value, srcData, index)` | Set by path on object/window |
104
+ | 612 | `bindDataToString(str, data)` | Resolve template string |
105
+ | 619 | `templateCompiled(str, data)` | Compile lodash-style template |
106
+ | 624 | `getWindowData(value)` | Read window/iframe context |
107
+ | 638 | `setWindowData(key, value)` | Write window/iframe context |
108
+ | 657 | `runFunction(obj, callback)` | Call declared JS function |
109
+ | 665 | `tableActionEvent(ctrl)` | Table/control action events |
110
+ | 687 | `callAPI(objApi, callBack, includeData)` | API call (`IN/OUT/CALLBACK`) |
111
+ | 743 | `loginFUN()` | Login/redirect |
112
+ | 761 | `errorMess(code, message)` | Standard error display |
143
113
 
144
114
  ## 2) scripts/defaultfunction.js — V3: defaultfunction-3.0.js
145
115
 
146
- Vai trò: utility layer dùng chung cho runtime (router, messaging, data transform, AJAX, export, auth, websocket...).
147
-
148
- | Line | Hàm | Dùng để làm gì |
149
- |---:|---|---|
150
- | 35 | `extractHostname(url)` | Lấy hostname từ URL. |
151
- | 53 | `getDomainWithoutSubdomain(url)` | Lấy domain gốc không subdomain. |
152
- | 62 | `loadScripts(scriptsArray, callbackFunc)` | Nạp nhiều script động rồi callback. |
153
- | 75 | `pushRouter(router)` | Push route vào browser history. |
154
- | 82 | `CALL(obj, includeData)` | Alias gọi `runAction(...)`. |
155
- | 86 | `windowSendMessage(window, cmd, data)` | `postMessage` sang parent/window/iframe. |
156
- | 100 | `appCommand(cmdData)` | Gửi lệnh về native wrapper (RN/WebKit). |
157
- | 106 | `buildHeader(obj, mapCol)` | Tạo header table từ dataset/map cột. |
158
- | 130 | `fillData(obj)` | Fill/map dữ liệu từ source sang destination. |
159
- | 162 | `groupBy(arrayObj, groupField, sumArr)` | Group mảng theo field + cộng tổng cột. |
160
- | 188 | `chartDataBuild(obj)` | Chuẩn hoá data cho chart tổng quát. |
161
- | 219 | `chartQABuild(obj)` | Build data chart chuyên QA/report. |
162
- | 239 | `confirm(obj)` | Hiển thị dialog confirm. |
163
- | 259 | `showMessage(obj)` | Hiển thị dialog/toast message. |
164
- | 283 | `rightTest(rightObject)` | Kiểm tra quyền theo user rights. |
165
- | 301 | `openWindow(obj)` | Mở popup/dialog window FUI. |
166
- | 326 | `redirect(obj, query)` | Điều hướng trang theo URL/config. |
167
- | 339 | `reload()` | Reload trang hiện tại. |
168
- | 343 | `findInArray(obj)` | Tìm phần tử theo điều kiện giá trị. |
169
- | 348 | `fixURL(url)` | Chuẩn hoá URL (ghép domain API nếu cần). |
170
- | 354 | `stringAttrToJson(str, removeVueEvent)` | Parse chuỗi attr HTML thành JSON object. |
171
- | 371 | `json_data_parse(obj, level)` | Parse đệ quy field có prefix `json_data:`. |
172
- | 407 | `ajaxCALL(URL, DATA, callBack, errorCallBack, header)` | Gọi AJAX POST helper. |
173
- | 449 | `capacityText(numb)` | Format dung lượng bytes -> KB/MB text. |
174
- | 454 | `generateID()` | Sinh ID ngẫu nhiên. |
175
- | 467 | `printPDF(obj)` | Render/in/download PDF bằng `pdfMake`. |
176
- | 499 | `colorLib(color)` | Bộ công cụ convert/manipulate màu. |
177
- | 645 | `transparentize(value, opacity)` | Tạo màu trong suốt (alpha). |
178
- | 650 | `jsonToExcel(Obj)` | Xuất dữ liệu JSON ra Excel. |
179
- | 746 | `copyToClipboard(textToCopy)` | Copy text vào clipboard. |
180
- | 770 | `fileNameClear(fname)` | Làm sạch tên file không hợp lệ. |
181
- | 775 | `hashCode(s)` | Sinh hash code từ string. |
182
- | 785 | `getCookie(cname)` | Đọc cookie theo tên. |
183
- | 800 | `setCookie(name, value, days, domain)` | Set cookie có expiry/domain. |
184
- | 814 | `logout(cookiesName, domain, url)` | Xoá cookie và logout/redirect. |
185
- | 827 | `webSocketJoinGroup(groupObj, timeout, callBackFunc)` | Join WS group theo payload. |
186
- | 851 | `webSocketConnection(wsURL, WS, wsState)` | Khởi tạo/duy trì WS connection. |
187
- | 892 | `webSocket_Send(obj)` | Gửi payload qua websocket hiện tại. |
188
-
189
- > **Real-time messaging (SignalR)**: hướng dẫn dùng đầy đủ 3 hàm trên — import bắt buộc, khai báo group trong `data[]`, nhận/gửi tin nhắn, ví dụ `module.json` hoàn chỉnh — xem [websocket-realtime.md](websocket-realtime.md).
116
+ Shared utilities (router, messaging, transform, AJAX, export, auth, websocket).
117
+
118
+ | Line | Function | Purpose |
119
+ | ---: | ------------------------------------------------------ | ------------------------------------- |
120
+ | 35 | `extractHostname(url)` | Hostname |
121
+ | 53 | `getDomainWithoutSubdomain(url)` | Root domain |
122
+ | 62 | `loadScripts(scriptsArray, callbackFunc)` | Load scripts, then callback |
123
+ | 75 | `pushRouter(router)` | Push browser history |
124
+ | 82 | `CALL(obj, includeData)` | Alias of `runAction(...)` |
125
+ | 86 | `windowSendMessage(window, cmd, data)` | `postMessage` to parent/window/iframe |
126
+ | 100 | `appCommand(cmdData)` | Command to native wrapper (RN/WebKit) |
127
+ | 106 | `buildHeader(obj, mapCol)` | Table headers from data/column map |
128
+ | 130 | `fillData(obj)` | Map source → destination |
129
+ | 162 | `groupBy(arrayObj, groupField, sumArr)` | Group + sum columns |
130
+ | 188 | `chartDataBuild(obj)` | Generic chart data |
131
+ | 219 | `chartQABuild(obj)` | QA/report chart data |
132
+ | 239 | `confirm(obj)` | Confirm dialog |
133
+ | 259 | `showMessage(obj)` | Message dialog/toast |
134
+ | 283 | `rightTest(rightObject)` | Check user rights |
135
+ | 301 | `openWindow(obj)` | FUI popup/dialog window |
136
+ | 326 | `redirect(obj, query)` | Navigate by URL/config |
137
+ | 339 | `reload()` | Reload page |
138
+ | 343 | `findInArray(obj)` | Find by value condition |
139
+ | 348 | `fixURL(url)` | Normalize URL (prepend API domain) |
140
+ | 354 | `stringAttrToJson(str, removeVueEvent)` | HTML attr string → JSON |
141
+ | 371 | `json_data_parse(obj, level)` | Parse `json_data:` fields recursively |
142
+ | 407 | `ajaxCALL(URL, DATA, callBack, errorCallBack, header)` | AJAX POST |
143
+ | 449 | `capacityText(numb)` | Bytes → KB/MB |
144
+ | 454 | `generateID()` | Random ID |
145
+ | 467 | `printPDF(obj)` | PDF via `pdfMake` |
146
+ | 499 | `colorLib(color)` | Color utils |
147
+ | 645 | `transparentize(value, opacity)` | Alpha color |
148
+ | 650 | `jsonToExcel(Obj)` | JSON → Excel |
149
+ | 746 | `copyToClipboard(textToCopy)` | Clipboard |
150
+ | 770 | `fileNameClear(fname)` | Sanitize file name |
151
+ | 775 | `hashCode(s)` | String hash |
152
+ | 785 | `getCookie(cname)` | Read cookie |
153
+ | 800 | `setCookie(name, value, days, domain)` | Set cookie |
154
+ | 814 | `logout(cookiesName, domain, url)` | Clear cookies, logout/redirect |
155
+ | 827 | `webSocketJoinGroup(groupObj, timeout, callBackFunc)` | Join WS group |
156
+ | 851 | `webSocketConnection(wsURL, WS, wsState)` | Create/keep WS connection |
157
+ | 892 | `webSocket_Send(obj)` | Send over WS |
158
+
159
+ > **Real-time (SignalR)** — required imports, `data[]` group declaration, send/receive, full `module.json`: [websocket-realtime.md](websocket-realtime.md).
190
160
 
191
161
  ## 3) scripts/component.js — V3: component-3.0.js
192
162
 
193
- Vai trò: đăng ký FUI base components và các component nghiệp vụ (dialog, editor, PDF, excel, chart, media...).
194
-
195
- Ghi chú:
196
- - File này cũng chứa `defaultControlAttr` để set attr mặc định theo từng `el`.
197
- - Nhiều component yêu cầu import ngoài (CKEditor, pdfMake, cropper, chart, ...).
198
-
199
- | Line | Component | Dùng để làm gì |
200
- |---:|---|---|
201
- | 304 | `f-label` | Hiển thị label/text theo format FUI. |
202
- | 319 | `f-box` | Khối hiển thị dữ liệu dạng box/card đơn giản. |
203
- | 377 | `f-header` | Header block nhẹ cho section/module. |
204
- | 386 | `f-title` | Title component chuẩn UI. |
205
- | 395 | `f-radiobox` | Radio group wrapper. |
206
- | 425 | `f-menu` | Menu list/navigation control. |
207
- | 472 | `f-search` | Input tìm kiếm dùng lại. |
208
- | 536 | `f-button` | Button wrapper chuẩn attr FUI. |
209
- | 607 | `f-slider` | Slider input/display. |
210
- | 618 | `f-file-upload` | Upload file cơ bản. |
211
- | 768 | `f-qrcode` | Render QR code. |
212
- | 843 | `f-qrcode-reader` | Quét/đọc QR code. |
213
- | 914 | `f-image-update` | Dialog crop/rotate/upload ảnh. |
214
- | 1161 | `f-date` | Date picker wrapper. |
215
- | 1434 | `f-time` | Time picker wrapper. |
216
- | 1639 | `f-time-counter` | Counter/countdown/clock hiển thị thời gian. |
217
- | 1775 | `fp-profile` | User profile menu trên header. |
218
- | 2020 | `header-bar` | Thanh header/menu chính của app/module. |
219
- | 2277 | `f-chart` | Biểu đồ bản cũ dựng trên canvas Chart.js (props `data`/`type`/`options`). Bản đang dùng là `f-echart` — xem [components-echart.md](components-echart.md). |
220
- | 2389 | `f-window` | Dynamic window/dialog host. |
221
- | 2453 | `f-editor` | WYSIWYG editor wrapper (CKEditor). |
222
- | 2591 | `f-editor-dialog` | Dialog chứa editor toàn màn hình. |
223
- | 2687 | `f-dialog` | Dialog dynamic dựng form từ `controls`. |
224
- | 2899 | `f-pdfmake` | Viewer/render PDF bằng `printPDF`. |
225
- | 2934 | `f-excel-reader` | Upload/đọc Excel/CSV → mảng object: chọn sheet, bỏ N dòng đầu, đặt tên key, giới hạn dung lượng; XLSX lazy-load. Xem [components-input.md](components-input.md). |
226
-
227
- ## 4) scripts/componentTable.js — V3: componentTable-3.0.js (xem §4b)
228
-
229
- Vai trò: table system cho FUI, gồm component table chính và cell renderer `t-*`.
230
-
231
- | Line | Component | Dùng để làm gì |
232
- |---:|---|---|
233
- | 1 | `f-table` | Data table duy nhất (CRUD lẫn readonly): search, select, CRUD (`update-api`, `update-form`), export, auto-build headers khi không truyền `headers`, sum row/sum line qua `sumFormat` (object/string), `:height` (xem bên dưới). |
234
- | 416 | `t-html` | Render ô dạng HTML. |
235
- | 420 | `t-label` | Render text label thường. |
236
- | 424 | `t-num` | Render/format số. |
237
- | 442 | `t-time` | Render/format thời gian. |
238
- | 452 | `t-boolean` | Render bool bằng icon/màu. |
239
- | 473 | `t-check` | Cell checkbox có thể tương tác. |
240
- | 501 | `t-text` | Cell text input inline. |
241
- | 523 | `t-select` | Cell select inline. |
242
- | 544 | `t-combobox` | Cell combobox/autocomplete inline. |
243
- | 616 | `t-menu` | Cell menu action. |
244
- | 654 | `t-link` | Cell link điều hướng/open dialog. |
245
- | 678 | `t-button` | Cell button action custom. |
246
-
247
- **`:height` (`f-table`)** — computed `heightNum`/`tableHeight` + method `updateFillHeight()`: bỏ trống = tự giãn theo số dòng; `<=0` = đo `getBoundingClientRect()` thật rồi fill tới đáy màn hình chừa `abs(n)` px (có `window.resize` listener); `>0` = px cố định.
163
+ Base `f-*` and business components. Also holds `defaultControlAttr` (default attrs per `el`). Many need external imports (CKEditor, pdfMake, cropper, chart, ...).
164
+
165
+ | Line | Component | Purpose |
166
+ | ---: | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
167
+ | 304 | `f-label` | Formatted label/text |
168
+ | 319 | `f-box` | Simple box/card |
169
+ | 377 | `f-header` | Light section header |
170
+ | 386 | `f-title` | Title |
171
+ | 395 | `f-radiobox` | Radio group |
172
+ | 425 | `f-menu` | Menu/navigation |
173
+ | 472 | `f-search` | Search input |
174
+ | 536 | `f-button` | Button |
175
+ | 607 | `f-slider` | Slider |
176
+ | 618 | `f-file-upload` | File upload |
177
+ | 768 | `f-qrcode` | QR render |
178
+ | 843 | `f-qrcode-reader` | QR scan |
179
+ | 914 | `f-image-update` | Crop/rotate/upload image dialog |
180
+ | 1161 | `f-date` | Date picker |
181
+ | 1434 | `f-time` | Time picker |
182
+ | 1639 | `f-time-counter` | Counter/countdown/clock |
183
+ | 1775 | `fp-profile` | Header profile menu |
184
+ | 2020 | `header-bar` | Main header bar |
185
+ | 2277 | `f-chart` | Legacy Chart.js (props `data`/`type`/`options`). Use `f-echart` — [components-echart.md](components-echart.md) |
186
+ | 2389 | `f-window` | Dynamic window/dialog host |
187
+ | 2453 | `f-editor` | WYSIWYG (CKEditor) |
188
+ | 2591 | `f-editor-dialog` | Fullscreen editor dialog |
189
+ | 2687 | `f-dialog` | Dialog built from `controls` |
190
+ | 2899 | `f-pdfmake` | PDF viewer via `printPDF` |
191
+ | 2934 | `f-excel-reader` | Excel/CSV → object array: sheet pick, skip N rows, key names, size limit; XLSX lazy-loaded. [components-input.md](components-input.md) |
192
+
193
+ ## 4) scripts/componentTable.js — V3: componentTable-3.0.js (§4b)
194
+
195
+ | Line | Component | Purpose |
196
+ | ---: | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
197
+ | 1 | `f-table` | The only data table (CRUD and readonly): search, select, CRUD (`update-api`, `update-form`), export, auto headers when `headers` omitted, sum row/line via `sumFormat` (object/string), `:height` |
198
+ | 416 | `t-html` | HTML cell |
199
+ | 420 | `t-label` | Text cell |
200
+ | 424 | `t-num` | Number cell |
201
+ | 442 | `t-time` | Time cell |
202
+ | 452 | `t-boolean` | Bool icon/color |
203
+ | 473 | `t-check` | Checkbox cell |
204
+ | 501 | `t-text` | Inline text input |
205
+ | 523 | `t-select` | Inline select |
206
+ | 544 | `t-combobox` | Inline combobox |
207
+ | 616 | `t-menu` | Action menu cell |
208
+ | 654 | `t-link` | Link / open-dialog cell |
209
+ | 678 | `t-button` | Action button cell |
210
+
211
+ **`f-table` `:height`** — computed `heightNum`/`tableHeight` + `updateFillHeight()`: empty = grows with rows; `<=0` = measures real `getBoundingClientRect()`, fills to screen bottom leaving `abs(n)` px (`window.resize` listener); `>0` = fixed px.
248
212
 
249
213
  ## 4b) scripts/componentTable-3.0.js
250
214
 
251
- Bản **V3** (Vue 3 + Vuetify 3) của cùng bộ component trên — tên đăng ký PascalCase (`FTable`, `THtml`, `TNum`, ...). Framework version của module quyết định file nào được nạp (`_moduleInfo.json`).
215
+ **V3** (Vue 3 + Vuetify 3) of the same components, PascalCase names (`FTable`, `THtml`, `TNum`, ...). Module framework (`_moduleInfo.json`) picks the file.
216
+
217
+ When editing **both** files:
218
+
219
+ - Lifecycle: V3 `beforeUnmount` (components declare both to run on V2 and V3).
220
+ - Classes: V3 `text-primary` / `text-subtitle-1` / `text-caption` vs V2 `primary--text` / `subtitle-1` / `caption`; `v-btn outlined` (V2) → `variant="outlined"` (V3).
221
+ - `v-data-table` scroll wrapper: V2 `.v-data-table__wrapper`, V3 `.v-table__wrapper`.
222
+ - Names bound directly in a V3 template **must not start with `_`** (proxy `has` trap) — use a suffix, e.g. `hideDefaultFooter_cacl`.
223
+ - `f-table` `headers`: V2 `{ text, value }`, V3 `{ title, key }`; slot `body.append` gets `{ headers }` (V2) / `{ columns }` (V3).
252
224
 
253
- Khác biệt phải nhớ khi sửa **cả hai** file:
254
- - Lifecycle: V3 dùng `beforeUnmount` (các component khai cả hai để chạy được ở cả V2 lẫn V3).
255
- - Class Vuetify: V3 là `text-primary` / `text-subtitle-1` / `text-caption`, V2 là `primary--text` / `subtitle-1` / `caption`; `v-btn outlined` (V2) → `variant="outlined"` (V3).
256
- - Wrapper cuộn của `v-data-table`: V2 `.v-data-table__wrapper`, V3 `.v-table__wrapper`.
257
- - Tên biến/computed **không được bắt đầu bằng `_`** nếu bind thẳng trong template V3 (proxy `has` trap chặn) — V3 dùng hậu tố kiểu `hideDefaultFooter_cacl`.
258
- - `headers` của `f-table`: V2 dùng `{ text, value }`, V3 dùng `{ title, key }` (chuẩn Vuetify 3); slot `body.append` V2 nhận `{ headers }`, V3 nhận `{ columns }`.
225
+ Verify V3: `node test/v3-table-harness.mjs [sum|fill|auto]` — real V3 framework from `https://fui.vn` in headless chromium with **local `componentTable-3.0.js` swapped in**; APIs blocked + mocked. Prints JS errors/`[Vue warn]`, real height, sum row, AG Grid cells; screenshots `test/v3-{mode}.png`.
259
226
 
260
- Kiểm chứng bản V3 sau khi sửa: `node test/v3-table-harness.mjs [sum|fill|auto]` — nạp framework V3 thật từ `https://fui.vn` trong chromium headless nhưng **thay `componentTable-3.0.js` bằng file local**, mọi API bị chặn + trả mock. In ra lỗi JS/`[Vue warn]`, chiều cao thật, nội dung dòng tổng, ô AG Grid, và chụp `test/v3-{mode}.png`.
227
+ ## 5) scripts/fsheet.js — shared V2 + V3
261
228
 
262
- ## 5) scripts/fsheet.js — dùng chung V2 + V3
229
+ Whole `f-sheet` in **one file** for V2 and V3 (declares both `beforeDestroy` and `beforeUnmount`); not split by framework.
263
230
 
264
- Vai trò: toàn bộ component `f-sheet`, một file **duy nhất** dùng chung cho cả V2 và V3 (khai cả `beforeDestroy` lẫn `beforeUnmount` để chạy được ở cả hai runtime) — không tách theo framework version như các file khác trong bảng ở đầu tài liệu.
231
+ Required imports (from `component.js` `defaultControlAttr["f-sheet"].import`), **in this order**:
265
232
 
266
- Import bắt buộc (2 file, trích từ `component.js` `defaultControlAttr["f-sheet"].import`), **đúng thứ tự**:
267
233
  ```
268
234
  /include/ag-grid/ag-grid-community.min.js
269
235
  /include/ag-grid/fsheet.js
270
236
  ```
271
237
 
272
- | Nội dung | Ghi chú |
273
- |---|---|
274
- | `Vue.component('FSheet', {...})` | Component chính — props/cột/wiring API chi tiết ở [fsheet.md](fsheet.md) |
275
- | 4 cell renderer dựng sẵn (`fsHtmlCellRenderer`/`fsLinkCellRenderer`/`fsButtonCellRenderer`/`fsMenuCellRenderer`) | Tương đương `t-html`/`t-link`/`t-button`/`t-menu` của `f-table` — xem [fsheet.md](fsheet.md) |
276
- | Hệ thống chọn vùng nhiều ô + fill handle + clipboard TSV tự viết | AG Grid Community không có Cell Selection (thuộc bản Enterprise) nên f-sheet tự điều khiển rồi gắn đúng bộ class CSS của AG Grid (`.ag-cell-range-*`, `.ag-selection-fill-*`, `.ag-fill-handle`) |
238
+ | Content | Notes |
239
+ | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
240
+ | `Vue.component('FSheet', {...})` | Main component — props/columns/API: [fsheet.md](fsheet.md) |
241
+ | 4 cell renderers (`fsHtmlCellRenderer`/`fsLinkCellRenderer`/`fsButtonCellRenderer`/`fsMenuCellRenderer`) | = `f-table`'s `t-html`/`t-link`/`t-button`/`t-menu` — [fsheet.md](fsheet.md) |
242
+ | Custom range selection + fill handle + TSV clipboard | AG Grid Community lacks Cell Selection (Enterprise), so f-sheet drives it and applies AG Grid classes (`.ag-cell-range-*`, `.ag-selection-fill-*`, `.ag-fill-handle`) |
277
243
 
278
- `:height` dùng cùng 3 chế độ (tự giãn / fill đáy / px cố định) — chi tiết: [fsheet.md](fsheet.md) §Chiều cao.
244
+ `:height` has the same 3 modes (auto-grow / fill to bottom / fixed px) — [fsheet.md](fsheet.md) §`:height`.
279
245
 
280
- Kiểm chứng `fsheet.js`: `component_preview` (render `f-sheet` cô lập với dữ liệu mẫu, không cần push lên server) hoặc `module_simulate({renderUI:true})` (kiểm trong module thật) — cả hai chạy browser thật, không cần harness riêng.
246
+ Verify `fsheet.js`: `fui component preview` (isolated `f-sheet` with sample data, no push) or `fui module simulate --render` (in a real module) — both real browser, no extra harness.
281
247
 
282
- ## 6) Tra cứu theo tác vụ
248
+ ## 6) Lookup by task
283
249
 
284
- > Cột "Mở file trước" ghi tên file V2. Nếu module là **V3**, thay bằng file `-3.0` tương ứng (xem quy tắc ở đầu tài liệu).
250
+ > Files listed are V2; for **V3** use the matching `-3.0` file.
285
251
 
286
- | Tác vụ cần làm | Mở file trước (V2 / V3) | Xem mục chính |
287
- |---|---|---|
288
- | Module không render đúng layout | `fastproject.js` / `fastproject-3.0.js` | `buildModuleUI`, `buildControl`, `bindData`. |
289
- | Action không chạy hoặc chạy sai nhánh | `fastproject.js` / `fastproject-3.0.js` | `runAction`, `vueAction`, `mapData`, `getVueData`. |
290
- | API không ra dữ liệu `OUT` | `fastproject.js` + `defaultfunction.js` (cùng bản V2/V3) | `callAPI`, `fixURL`, `ajaxCALL`. |
291
- | Table CRUD lỗi Add/Edit/Delete | `componentTable.js` / `componentTable-3.0.js` | `f-table` + `update-api`, `update-form`. |
292
- | Dialog dynamic không bind dữ liệu | `component.js` / `component-3.0.js` | `f-dialog`, `buildModuleUI` (ở fastproject). |
293
- | Upload ảnh, crop, lưu file | `component.js` / `component-3.0.js` | `f-image-update`. |
294
- | Export Excel/PDF | `defaultfunction.js` + `component.js` (cùng bản V2/V3) | `jsonToExcel`, `printPDF`, `f-pdfmake`, `f-excel-reader`. |
295
- | Sự cố đăng nhập/quyền/menu | `fastproject.js` + `defaultfunction.js` (cùng bản V2/V3) | `loadModuleInfo`, `loginFUN`, `rightTest`. |
296
- | `f-sheet` không hiện / báo "FSheet is not defined" | `fsheet.js` (dùng chung V2+V3) | Thiếu import — xem [component-quickref.md](component-quickref.md) hoặc [fsheet.md](fsheet.md). |
252
+ | Task | Open first | Look at |
253
+ | ------------------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------- |
254
+ | Layout renders wrong | `fastproject.js` | `buildModuleUI`, `buildControl`, `bindData` |
255
+ | Action not running / wrong branch | `fastproject.js` | `runAction`, `vueAction`, `mapData`, `getVueData` |
256
+ | API returns no `OUT` | `fastproject.js` + `defaultfunction.js` | `callAPI`, `fixURL`, `ajaxCALL` |
257
+ | Table Add/Edit/Delete fails | `componentTable.js` | `f-table` + `update-api`, `update-form` |
258
+ | Dynamic dialog not binding | `component.js` | `f-dialog`, `buildModuleUI` (fastproject) |
259
+ | Image upload/crop/save | `component.js` | `f-image-update` |
260
+ | Excel/PDF export | `defaultfunction.js` + `component.js` | `jsonToExcel`, `printPDF`, `f-pdfmake`, `f-excel-reader` |
261
+ | Login/rights/menu | `fastproject.js` + `defaultfunction.js` | `loadModuleInfo`, `loginFUN`, `rightTest` |
262
+ | `f-sheet` missing / "FSheet is not defined" | `fsheet.js` (shared V2+V3) | Missing import — [component-quickref.md](component-quickref.md) or [fsheet.md](fsheet.md) |