@fui-org/fui-cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/dist/fui.js +160 -43
- package/package.json +4 -2
- package/skills/fui/SKILL.md +131 -66
- package/skills/fui-skill/README.md +112 -0
- package/skills/fui-skill/SKILL.md +269 -0
- package/skills/fui-skill/assets/projectdefaultstyle.css +518 -0
- package/skills/fui-skill/design-md/airbnb/DESIGN.md +545 -0
- package/skills/fui-skill/design-md/airbnb/README.md +5 -0
- package/skills/fui-skill/design-md/airtable/DESIGN.md +554 -0
- package/skills/fui-skill/design-md/airtable/README.md +5 -0
- package/skills/fui-skill/design-md/apple/DESIGN.md +562 -0
- package/skills/fui-skill/design-md/apple/README.md +5 -0
- package/skills/fui-skill/design-md/asu/DESIGN.md +179 -0
- package/skills/fui-skill/design-md/asu/README.md +107 -0
- package/skills/fui-skill/design-md/binance/DESIGN.md +634 -0
- package/skills/fui-skill/design-md/binance/README.md +5 -0
- package/skills/fui-skill/design-md/bmw/DESIGN.md +544 -0
- package/skills/fui-skill/design-md/bmw/README.md +5 -0
- package/skills/fui-skill/design-md/bmw-m/DESIGN.md +503 -0
- package/skills/fui-skill/design-md/bmw-m/README.md +5 -0
- package/skills/fui-skill/design-md/bugatti/DESIGN.md +454 -0
- package/skills/fui-skill/design-md/bugatti/README.md +5 -0
- package/skills/fui-skill/design-md/cal/DESIGN.md +542 -0
- package/skills/fui-skill/design-md/cal/README.md +5 -0
- package/skills/fui-skill/design-md/claude/DESIGN.md +589 -0
- package/skills/fui-skill/design-md/claude/README.md +5 -0
- package/skills/fui-skill/design-md/clay/DESIGN.md +541 -0
- package/skills/fui-skill/design-md/clay/README.md +5 -0
- package/skills/fui-skill/design-md/clickhouse/DESIGN.md +544 -0
- package/skills/fui-skill/design-md/clickhouse/README.md +5 -0
- package/skills/fui-skill/design-md/cohere/DESIGN.md +451 -0
- package/skills/fui-skill/design-md/cohere/README.md +5 -0
- package/skills/fui-skill/design-md/coinbase/DESIGN.md +570 -0
- package/skills/fui-skill/design-md/coinbase/README.md +5 -0
- package/skills/fui-skill/design-md/composio/DESIGN.md +506 -0
- package/skills/fui-skill/design-md/composio/README.md +5 -0
- package/skills/fui-skill/design-md/cursor/DESIGN.md +537 -0
- package/skills/fui-skill/design-md/cursor/README.md +5 -0
- package/skills/fui-skill/design-md/elevenlabs/DESIGN.md +504 -0
- package/skills/fui-skill/design-md/elevenlabs/README.md +5 -0
- package/skills/fui-skill/design-md/expo/DESIGN.md +526 -0
- package/skills/fui-skill/design-md/expo/README.md +5 -0
- package/skills/fui-skill/design-md/ferrari/DESIGN.md +531 -0
- package/skills/fui-skill/design-md/ferrari/README.md +5 -0
- package/skills/fui-skill/design-md/figma/DESIGN.md +578 -0
- package/skills/fui-skill/design-md/figma/README.md +5 -0
- package/skills/fui-skill/design-md/framer/DESIGN.md +544 -0
- package/skills/fui-skill/design-md/framer/README.md +5 -0
- package/skills/fui-skill/design-md/fui/DESIGN.md +532 -0
- package/skills/fui-skill/design-md/hashicorp/DESIGN.md +575 -0
- package/skills/fui-skill/design-md/hashicorp/README.md +5 -0
- package/skills/fui-skill/design-md/ibm/DESIGN.md +550 -0
- package/skills/fui-skill/design-md/ibm/README.md +5 -0
- package/skills/fui-skill/design-md/intercom/DESIGN.md +546 -0
- package/skills/fui-skill/design-md/intercom/README.md +5 -0
- package/skills/fui-skill/design-md/kraken/DESIGN.md +125 -0
- package/skills/fui-skill/design-md/kraken/README.md +5 -0
- package/skills/fui-skill/design-md/lamborghini/DESIGN.md +288 -0
- package/skills/fui-skill/design-md/lamborghini/README.md +5 -0
- package/skills/fui-skill/design-md/linear.app/DESIGN.md +548 -0
- package/skills/fui-skill/design-md/linear.app/README.md +5 -0
- package/skills/fui-skill/design-md/lovable/DESIGN.md +298 -0
- package/skills/fui-skill/design-md/lovable/README.md +5 -0
- package/skills/fui-skill/design-md/mastercard/DESIGN.md +365 -0
- package/skills/fui-skill/design-md/mastercard/README.md +5 -0
- package/skills/fui-skill/design-md/meta/DESIGN.md +683 -0
- package/skills/fui-skill/design-md/meta/README.md +5 -0
- package/skills/fui-skill/design-md/minimax/DESIGN.md +746 -0
- package/skills/fui-skill/design-md/minimax/README.md +5 -0
- package/skills/fui-skill/design-md/mintlify/DESIGN.md +852 -0
- package/skills/fui-skill/design-md/mintlify/README.md +5 -0
- package/skills/fui-skill/design-md/miro/DESIGN.md +825 -0
- package/skills/fui-skill/design-md/miro/README.md +5 -0
- package/skills/fui-skill/design-md/mistral.ai/DESIGN.md +773 -0
- package/skills/fui-skill/design-md/mistral.ai/README.md +5 -0
- package/skills/fui-skill/design-md/mongodb/DESIGN.md +767 -0
- package/skills/fui-skill/design-md/mongodb/README.md +5 -0
- package/skills/fui-skill/design-md/nike/DESIGN.md +575 -0
- package/skills/fui-skill/design-md/nike/README.md +5 -0
- package/skills/fui-skill/design-md/notion/DESIGN.md +821 -0
- package/skills/fui-skill/design-md/notion/README.md +5 -0
- package/skills/fui-skill/design-md/nvidia/DESIGN.md +640 -0
- package/skills/fui-skill/design-md/nvidia/README.md +5 -0
- package/skills/fui-skill/design-md/ollama/DESIGN.md +539 -0
- package/skills/fui-skill/design-md/ollama/README.md +5 -0
- package/skills/fui-skill/design-md/opencode.ai/DESIGN.md +521 -0
- package/skills/fui-skill/design-md/opencode.ai/README.md +5 -0
- package/skills/fui-skill/design-md/pinterest/DESIGN.md +597 -0
- package/skills/fui-skill/design-md/pinterest/README.md +5 -0
- package/skills/fui-skill/design-md/playstation/DESIGN.md +661 -0
- package/skills/fui-skill/design-md/playstation/README.md +5 -0
- package/skills/fui-skill/design-md/posthog/DESIGN.md +690 -0
- package/skills/fui-skill/design-md/posthog/README.md +5 -0
- package/skills/fui-skill/design-md/raycast/DESIGN.md +669 -0
- package/skills/fui-skill/design-md/raycast/README.md +5 -0
- package/skills/fui-skill/design-md/renault/DESIGN.md +589 -0
- package/skills/fui-skill/design-md/renault/README.md +5 -0
- package/skills/fui-skill/design-md/replicate/DESIGN.md +616 -0
- package/skills/fui-skill/design-md/replicate/README.md +5 -0
- package/skills/fui-skill/design-md/resend/DESIGN.md +585 -0
- package/skills/fui-skill/design-md/resend/README.md +5 -0
- package/skills/fui-skill/design-md/revolut/DESIGN.md +636 -0
- package/skills/fui-skill/design-md/revolut/README.md +5 -0
- package/skills/fui-skill/design-md/runwayml/DESIGN.md +244 -0
- package/skills/fui-skill/design-md/runwayml/README.md +5 -0
- package/skills/fui-skill/design-md/sanity/DESIGN.md +357 -0
- package/skills/fui-skill/design-md/sanity/README.md +5 -0
- package/skills/fui-skill/design-md/sentry/DESIGN.md +551 -0
- package/skills/fui-skill/design-md/sentry/README.md +5 -0
- package/skills/fui-skill/design-md/shopify/DESIGN.md +516 -0
- package/skills/fui-skill/design-md/shopify/README.md +5 -0
- package/skills/fui-skill/design-md/slack/DESIGN.md +482 -0
- package/skills/fui-skill/design-md/spacex/DESIGN.md +363 -0
- package/skills/fui-skill/design-md/spacex/README.md +5 -0
- package/skills/fui-skill/design-md/spotify/DESIGN.md +246 -0
- package/skills/fui-skill/design-md/spotify/README.md +5 -0
- package/skills/fui-skill/design-md/starbucks/DESIGN.md +580 -0
- package/skills/fui-skill/design-md/starbucks/README.md +5 -0
- package/skills/fui-skill/design-md/stripe/DESIGN.md +487 -0
- package/skills/fui-skill/design-md/stripe/README.md +5 -0
- package/skills/fui-skill/design-md/supabase/DESIGN.md +462 -0
- package/skills/fui-skill/design-md/supabase/README.md +5 -0
- package/skills/fui-skill/design-md/superhuman/DESIGN.md +448 -0
- package/skills/fui-skill/design-md/superhuman/README.md +5 -0
- package/skills/fui-skill/design-md/tesla/DESIGN.md +286 -0
- package/skills/fui-skill/design-md/tesla/README.md +5 -0
- package/skills/fui-skill/design-md/theverge/DESIGN.md +339 -0
- package/skills/fui-skill/design-md/theverge/README.md +5 -0
- package/skills/fui-skill/design-md/together.ai/DESIGN.md +633 -0
- package/skills/fui-skill/design-md/together.ai/README.md +5 -0
- package/skills/fui-skill/design-md/uber/DESIGN.md +636 -0
- package/skills/fui-skill/design-md/uber/README.md +5 -0
- package/skills/fui-skill/design-md/vercel/DESIGN.md +736 -0
- package/skills/fui-skill/design-md/vercel/README.md +5 -0
- package/skills/fui-skill/design-md/vodafone/DESIGN.md +538 -0
- package/skills/fui-skill/design-md/vodafone/README.md +5 -0
- package/skills/fui-skill/design-md/voltagent/DESIGN.md +521 -0
- package/skills/fui-skill/design-md/voltagent/README.md +5 -0
- package/skills/fui-skill/design-md/warp/DESIGN.md +526 -0
- package/skills/fui-skill/design-md/warp/README.md +5 -0
- package/skills/fui-skill/design-md/webflow/DESIGN.md +588 -0
- package/skills/fui-skill/design-md/webflow/README.md +5 -0
- package/skills/fui-skill/design-md/wired/DESIGN.md +497 -0
- package/skills/fui-skill/design-md/wired/README.md +5 -0
- package/skills/fui-skill/design-md/wise/DESIGN.md +544 -0
- package/skills/fui-skill/design-md/wise/README.md +5 -0
- package/skills/fui-skill/design-md/x.ai/DESIGN.md +465 -0
- package/skills/fui-skill/design-md/x.ai/README.md +5 -0
- package/skills/fui-skill/design-md/zapier/DESIGN.md +537 -0
- package/skills/fui-skill/design-md/zapier/README.md +5 -0
- package/skills/fui-skill/examples/component.vue +162 -0
- package/skills/fui-skill/examples/f-table-patterns.json +331 -0
- package/skills/fui-skill/examples/module-patterns.json +973 -0
- package/skills/fui-skill/examples/project-patterns.json +222 -0
- package/skills/fui-skill/metadata.json +75 -0
- package/skills/fui-skill/references/INDEX.md +144 -0
- package/skills/fui-skill/references/advanced-techniques.md +160 -0
- package/skills/fui-skill/references/coding-standards.md +112 -0
- package/skills/fui-skill/references/component-design.md +455 -0
- package/skills/fui-skill/references/component-quickref.md +77 -0
- package/skills/fui-skill/references/component-table.md +276 -0
- package/skills/fui-skill/references/components-dialog.md +192 -0
- package/skills/fui-skill/references/components-display.md +147 -0
- package/skills/fui-skill/references/components-echart.md +391 -0
- package/skills/fui-skill/references/components-input.md +359 -0
- package/skills/fui-skill/references/controls-patterns.md +847 -0
- package/skills/fui-skill/references/controls-styling-vocabulary.md +140 -0
- package/skills/fui-skill/references/db-table-design.md +77 -0
- package/skills/fui-skill/references/db-workflow.md +504 -0
- package/skills/fui-skill/references/default-function.md +415 -0
- package/skills/fui-skill/references/design-modes.md +85 -0
- package/skills/fui-skill/references/echart-templates.md +481 -0
- package/skills/fui-skill/references/fastproject.md +97 -0
- package/skills/fui-skill/references/fsheet.md +218 -0
- package/skills/fui-skill/references/fullstack-workflow.md +351 -0
- package/skills/fui-skill/references/module-data-patterns.md +126 -0
- package/skills/fui-skill/references/module-json-anatomy.md +137 -0
- package/skills/fui-skill/references/module-structure.md +260 -0
- package/skills/fui-skill/references/new-session.md +108 -0
- package/skills/fui-skill/references/pdfmake.md +60 -0
- package/skills/fui-skill/references/permission-system.md +169 -0
- package/skills/fui-skill/references/platform-architecture.md +294 -0
- package/skills/fui-skill/references/project-config.md +335 -0
- package/skills/fui-skill/references/project-provisioning.md +383 -0
- package/skills/fui-skill/references/script-map.md +296 -0
- package/skills/fui-skill/references/sql-clr-functions.md +224 -0
- package/skills/fui-skill/references/system-design.md +116 -0
- package/skills/fui-skill/references/tapi-file-api.md +191 -0
- package/skills/fui-skill/references/tapi-permission-patterns.md +158 -0
- package/skills/fui-skill/references/tapi-reference.md +549 -0
- package/skills/fui-skill/references/tools-registry.md +460 -0
- package/skills/fui-skill/references/ui-crosswindow-patterns.md +317 -0
- package/skills/fui-skill/references/ui-dialog-patterns.md +229 -0
- package/skills/fui-skill/references/ui-layout-patterns.md +176 -0
- package/skills/fui-skill/references/ui-patterns.md +315 -0
- package/skills/fui-skill/references/ui-screenshot-review.md +94 -0
- package/skills/fui-skill/references/ui-table-cell-patterns.md +316 -0
- package/skills/fui-skill/references/ui-templates.md +29 -0
- package/skills/fui-skill/references/verification.md +246 -0
- package/skills/fui-skill/references/watcher-patterns.md +196 -0
- package/skills/fui-skill/references/websocket-realtime.md +254 -0
- package/skills/fui-skill/scripts/component-3.0.js +2549 -0
- package/skills/fui-skill/scripts/component.js +3142 -0
- package/skills/fui-skill/scripts/componentTable-3.0.js +909 -0
- package/skills/fui-skill/scripts/componentTable.js +769 -0
- package/skills/fui-skill/scripts/defaultfunction-3.0.js +781 -0
- package/skills/fui-skill/scripts/defaultfunction.js +966 -0
- package/skills/fui-skill/scripts/fastproject-3.0.js +870 -0
- package/skills/fui-skill/scripts/fastproject.js +828 -0
- package/skills/fui-skill/scripts/fechart.js +890 -0
- package/skills/fui-skill/scripts/fsheet.js +1330 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# module.json `data[]` — Khai báo state & value resolution (chuyên sâu)
|
|
2
|
+
|
|
3
|
+
> File này sở hữu: **pattern khai báo `data[]`: ba loại phần tử, thứ tự state → named action → auto-startup**. Value resolution xem [controls-patterns.md](controls-patterns.md) §0; cú pháp key lồng nhau (dot/bracket/`#PARENT`) xem [controls-patterns.md](controls-patterns.md) §1; trao đổi cross-window xem [ui-crosswindow-patterns.md](ui-crosswindow-patterns.md).
|
|
4
|
+
|
|
5
|
+
Cách FUI đọc `data[]`: xử lý **tuần tự từ trên xuống**, mỗi object gán/chạy dựa trên cách viết value. Ví dụ trong file này rút từ `ex/ex-v3-1SetData` + `ex-v3-2CauTruc` (module demo chính thức của FUI).
|
|
6
|
+
|
|
7
|
+
> Quy tắc value resolution hình thức: [controls-patterns.md](controls-patterns.md) §0. Tổng quan 4 thành phần: [module-json-anatomy.md](module-json-anatomy.md). Engine nền tảng: [platform-architecture.md](platform-architecture.md) §5.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. Ba loại phần tử trong `data[]`
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
"data": [
|
|
15
|
+
{ "keyword": "", "dsUser": [], "dlOpen": false }, // (a) khởi tạo state
|
|
16
|
+
{ "getUser": { "API": "...", "IN": {...}, "OUT": "dsUser" } }, // (b) named action
|
|
17
|
+
{ "API": "...", "OUT": "dsInit" }, // (c) action tự chạy khi load
|
|
18
|
+
{ "CALL": "getUser" } // (c) auto-startup
|
|
19
|
+
]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
- (a) không có key action → tạo biến reactive trong `vueData`.
|
|
23
|
+
- (b) key là **tên hàm** → định nghĩa action tái sử dụng (gọi bằng `CALL`).
|
|
24
|
+
- (c) object là chính một action (`API`/`CALL`/`FUN`…) → **chạy ngay khi trang load**, theo thứ tự.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 2. Value resolution — CÁCH VIẾT quyết định GIÁ TRỊ (điểm hay sai)
|
|
29
|
+
|
|
30
|
+
Bảng quy tắc đầy đủ (`getVueData`: backtick / `{{ }}` / chuỗi có dấu cách / chuỗi không dấu cách →
|
|
31
|
+
JS eval) nằm ở [controls-patterns.md §0](controls-patterns.md#0-value-resolution-rules-fundamental)
|
|
32
|
+
— file Tier A luôn được nạp sẵn, không chép lại ở đây.
|
|
33
|
+
|
|
34
|
+
> **Hệ quả cho AI khi viết `data[]`:** muốn gán **chuỗi cố định không dấu cách** (id, url, mã) →
|
|
35
|
+
> **bọc backtick** (`` "`winUser" ``) hoặc single-quote (`"'winUser'"`), nếu không FUI sẽ hiểu là
|
|
36
|
+
> biến. Đây là lỗi phổ biến nhất khi viết `data`/`IN`.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 3. Key là đường dẫn lồng nhau (deep set)
|
|
41
|
+
|
|
42
|
+
Key bên trái cũng được phân giải (dot / bracket / index động / `#PARENT`) — bảng cú pháp đầy đủ nằm ở
|
|
43
|
+
[controls-patterns.md §1](controls-patterns.md#1-khai-báo-và-gán-dữ-liệu-trong-data) *(Tier A, đã nạp sẵn)*,
|
|
44
|
+
không chép lại ở đây.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 4. Action tự chạy: inline `IN`/`OUT`/`API` khi load
|
|
49
|
+
|
|
50
|
+
Object là action đứng riêng trong `data[]` → chạy khi load. Không cần đặt tên:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{ "API": "https://tapi.example.vn/me/auth/ApplicationList", "OUT": "Mang" },
|
|
54
|
+
{ "IN": { "ABC": "`gdsgdsg", "DEF": "val5", "CBV": 1233 }, "OUT": "DoiTuong" }
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
→ dùng để nạp dữ liệu ban đầu của trang (danh mục, dropdown, dữ liệu bảng).
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 5. Named action + CALLBACK (tái sử dụng)
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"cmdSETData": [
|
|
66
|
+
{ "MESS": "Thông báo" },
|
|
67
|
+
{ "#Win1.GiaTriSetTuCHA": "Giá trị set từ CHA" }
|
|
68
|
+
],
|
|
69
|
+
"apiChart": {
|
|
70
|
+
"API": "/ts/TS_Report_ForChart/{{ab}}",
|
|
71
|
+
"IN": { "sachID": "apiLoadFBUser", "modeY": 12345 },
|
|
72
|
+
"OUT": "DSDoiQuaTang",
|
|
73
|
+
"CALLBACK": { "AAA": "val2" }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Gọi bằng `{ "CALL": "cmdSETData" }` từ `controls`, `watch`, hay action khác. `CALLBACK` chạy sau khi API xong (xem [ui-patterns.md](ui-patterns.md) §7).
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 6. `watch` với `v_old` — giá trị cũ
|
|
83
|
+
|
|
84
|
+
Trong `watch`, `v_old.<field>` cho giá trị **trước khi đổi**:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
"watch": {
|
|
88
|
+
"val4": {
|
|
89
|
+
"API": "ts/auth/QuanHuyen_Select",
|
|
90
|
+
"IN": { "MaTinhTP": "tinhID" },
|
|
91
|
+
"OUT": "DS_QUAN_HUYEN",
|
|
92
|
+
"CALLBACK": { "BAC": "v_old.abcdeID" }
|
|
93
|
+
},
|
|
94
|
+
"taoID": { "dungthu": "v_old.taoID" }
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Chi tiết `v_old`, `deep-watch`: [watcher-patterns.md](watcher-patterns.md).
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 7. Trao đổi cross-window ngay trong `data[]`
|
|
103
|
+
|
|
104
|
+
`data[]` có thể đọc/ghi cửa sổ khác bằng key/value `#PARENT.*` / `#WinID.*` — đặt **trước** các CALL fetch:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
"data": [
|
|
108
|
+
{
|
|
109
|
+
"LayDuLieuWinCha": "#PARENT.Win1", // đọc data cha
|
|
110
|
+
"#PARENT.abcdef": 1234567890, // ghi xuống cha
|
|
111
|
+
"#Win1": { "CALL": "cmdTHONGBao" } // gọi lệnh ở Win1
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Đầy đủ: [ui-crosswindow-patterns.md](ui-crosswindow-patterns.md).
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 8. Checklist viết `data[]`
|
|
121
|
+
|
|
122
|
+
1. Khởi tạo **mọi** biến state ở object đầu (kể cả `[]`, `false`, `null`) — để reactive hoạt động.
|
|
123
|
+
2. Named action nhóm giữa; auto-startup (`CALL`/`API`) đặt **cuối**.
|
|
124
|
+
3. Gán chuỗi cố định không dấu cách → **backtick**; đừng để FUI hiểu nhầm là biến.
|
|
125
|
+
4. `#PARENT.*` / biến từ URL đặt trước các CALL fetch.
|
|
126
|
+
5. Không nhồi logic phức tạp vào `data` — tách sang `script.js` (hàm) hoặc `EXE` dè xẻn.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# module.json Anatomy — 4 thành phần: data · watch · controls · set
|
|
2
|
+
|
|
3
|
+
> File này sở hữu: **4 thành phần `module.json` (data/watch/controls/set) — vai trò và cách chúng tương tác, checklist cấu trúc**. Cú pháp action/control chi tiết xem [controls-patterns.md](controls-patterns.md).
|
|
4
|
+
|
|
5
|
+
`module.json` mô tả một trang FUI. Nó có đúng **4 khối cấp 1**. File này giải thích *vai trò, cách cấu hình, tác động* và *tương tác* giữa chúng, rồi trỏ tới file chuyên sâu cho từng loại pattern.
|
|
6
|
+
|
|
7
|
+
> Cơ chế nền tảng (runtime đọc module.json thế nào): [platform-architecture.md](platform-architecture.md). Pattern UI thực tế (ưu tiên cao, đã tinh chỉnh qua thực chiến): [ui-patterns.md](ui-patterns.md).
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"data": [ /* state + action */ ],
|
|
12
|
+
"watch": { /* observer → action */ },
|
|
13
|
+
"controls": [ /* layout UI: container > rows > cols */ ],
|
|
14
|
+
"set": { /* override config trang (tùy chọn) */ }
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Runtime chạy: `runAction(data)` → `buildModuleUI(controls)` → gắn `watch` → merge `set` vào config trang. Tất cả state sống trong `vueData`.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 1. `data` — Mảng khởi tạo state + định nghĩa Action
|
|
23
|
+
|
|
24
|
+
**Là gì:** một **mảng**. FUI xử lý tuần tự từ trên xuống khi trang load.
|
|
25
|
+
|
|
26
|
+
**Ba loại phần tử trong `data[]`:**
|
|
27
|
+
|
|
28
|
+
| Loại object | Nhận biết | Tác động |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| Khởi tạo state | Không có key action (`API`/`CALL`/`IF`...) | Tạo biến reactive trong `vueData` |
|
|
31
|
+
| Named action | Key là tên hàm, value là object action | Định nghĩa action tái sử dụng (gọi qua `CALL`) |
|
|
32
|
+
| Auto-startup | `{ "API": ... }` hoặc `{ "CALL": ... }` đứng riêng | **Tự chạy** ngay khi load |
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
"data": [
|
|
36
|
+
{ "dsUser": [], "sGroup": null, "dlUserInfo": false },
|
|
37
|
+
{
|
|
38
|
+
"getUser": { "API": "SM_Users_SelectByDepGroup", "IN": { "GroupID": "sGroup" }, "OUT": "dsUser" }
|
|
39
|
+
},
|
|
40
|
+
{ "CALL": "getUser" }
|
|
41
|
+
]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Tác động:** mọi biến khai báo ở đây thành reactive state; action đặt tên ở đây gọi được từ `watch`, `controls`, hay action khác. Auto-startup ở cuối = dữ liệu ban đầu của trang.
|
|
45
|
+
|
|
46
|
+
**Chi tiết:** khai báo `data[]` + value resolution (chuỗi/biến/backtick/`{{ }}`/deep key, action tự chạy, named action, `v_old`) → **[module-data-patterns.md](module-data-patterns.md)**; engine action → [controls-patterns.md](controls-patterns.md); tổ chức data thực tế → [ui-patterns.md](ui-patterns.md) §1–2.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 2. `watch` — Observer: state đổi → chạy action
|
|
51
|
+
|
|
52
|
+
**Là gì:** một **object** `{ "tênBiến": action }`. Khi biến đổi giá trị, action chạy.
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
"watch": {
|
|
56
|
+
"sGroup": { "CALL": "getUser" },
|
|
57
|
+
"sDepartment": { "CALL": "getUser" },
|
|
58
|
+
"sModuleID": [ { "CALL": "getSysRight" }, { "CALL": "getFunctionRight" } ]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Tác động & mẫu dùng:**
|
|
63
|
+
- **Cascading filter**: mỗi dropdown lọc có một watch → tự reload bảng khi đổi.
|
|
64
|
+
- Nhiều action cho một biến → dùng **mảng**.
|
|
65
|
+
- **`deep-watch`**: theo dõi thay đổi sâu bên trong object/array (runtime hỗ trợ key `deep-watch`).
|
|
66
|
+
|
|
67
|
+
**Chi tiết:** [watcher-patterns.md](watcher-patterns.md) (v_old, deep-watch, cascading), [ui-patterns.md](ui-patterns.md) §3.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 3. `controls` — Layout UI (bắt buộc grid container > rows > cols)
|
|
72
|
+
|
|
73
|
+
**Là gì:** một **mảng** container. Runtime dựng: `container (v-container)` → `rows (v-layout)` → `cols` → mỗi phần tử là một **Control Object**.
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
"controls": [
|
|
77
|
+
{
|
|
78
|
+
"prop": "fluid grid-list-md",
|
|
79
|
+
"rows": [
|
|
80
|
+
{ "prop": "row", "cols": [ /* Control Objects */ ] }
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Control Object** — các key chính:
|
|
87
|
+
|
|
88
|
+
| Key | Vai trò |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `el` | Tag/component: `div`, `v-*` (Vuetify), `f-*`/`t-*` (FUI), `uc-*` (custom) |
|
|
91
|
+
| `attr` | Thuộc tính/directive (`class`, `style`, `v-model`, `v-on:click`) — **dùng `v-on:click`, KHÔNG `@click`** |
|
|
92
|
+
| `w` | Bề rộng cột: `1–12` (grid) hoặc `>= 25` (px, **bắt buộc kèm `col: { "class": "shrink" }`**). Không dùng 13–24. Bắt buộc cho item trong `cols` |
|
|
93
|
+
| `col` | Cấu hình cột grid bao ngoài (`class`, `style`, `v-if`) |
|
|
94
|
+
| `innerHTML` | Nội dung: string (hỗ trợ `{{ }}`) hoặc mảng Control Object lồng nhau |
|
|
95
|
+
|
|
96
|
+
**Tác động:** đây là toàn bộ giao diện trang. Quy tắc bắt buộc: luôn bắt đầu bằng grid wrapper; dùng `innerHTML` (mảng) để lồng, không dùng `children`; dialog đặt trong container `prop: "hidden-container"`.
|
|
97
|
+
|
|
98
|
+
**Chi tiết:** cấu trúc & grid → [controls-patterns.md](controls-patterns.md) §6; **class/prop/style được dùng (đừng tự thêm style)** → [controls-styling-vocabulary.md](controls-styling-vocabulary.md); chọn component → [component-quickref.md](component-quickref.md); pattern layout/table/dialog → [ui-patterns.md](ui-patterns.md), [ui-table-cell-patterns.md](ui-table-cell-patterns.md), [ui-dialog-patterns.md](ui-dialog-patterns.md), [ui-layout-patterns.md](ui-layout-patterns.md).
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 4. `set` — Override config cho riêng trang (tùy chọn)
|
|
103
|
+
|
|
104
|
+
**Là gì:** một **object** override config cấp project cho trang này. Runtime trộn `project.json` rồi `set` (module thắng) — xem [platform-architecture.md](platform-architecture.md) §2.1.
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
"set": {
|
|
108
|
+
"title": "Quản lý sinh viên",
|
|
109
|
+
"menu": false
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Tác động:** chỉ khai báo field khác với project. Thường dùng: `title` (tiêu đề trang), `menu: false` (ẩn header — sub-window/landing), `menuLeft` (sidebar riêng), `apiDomain` (đổi backend trang đó). Trang bình thường **không cần `set`** (kế thừa hết project).
|
|
114
|
+
|
|
115
|
+
**Chi tiết & danh mục thuộc tính đầy đủ:** [project-config.md](project-config.md).
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Tương tác giữa 4 thành phần
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
URL ?param ──► vueData[param] (inject trước khi data chạy)
|
|
123
|
+
data[] ──► tạo state + action, auto-startup fetch
|
|
124
|
+
controls ──► bind hai chiều vào state (v-model), gọi action (:action / v-on)
|
|
125
|
+
watch ──► state đổi → chạy action → cập nhật state khác → UI re-render
|
|
126
|
+
set ──► quyết định khung trang (title/menu/apiDomain) bao quanh controls
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Vòng lặp điển hình: user thao tác trên `controls` → đổi state → `watch` bắt → gọi `API` action trong `data` → `OUT` cập nhật state → `controls` render lại.
|
|
130
|
+
|
|
131
|
+
## Checklist khi viết module.json
|
|
132
|
+
|
|
133
|
+
1. `data[]`: state trước → named action → `{ "CALL": ... }` auto-startup cuối
|
|
134
|
+
2. `watch`: mọi filter/dropdown đều có watch → reload
|
|
135
|
+
3. `controls`: bắt đầu bằng grid wrapper; `w` cho mọi item; dialog trong `hidden-container`; `v-on:click` không `@click`
|
|
136
|
+
4. `set`: chỉ khai báo khi trang khác project default
|
|
137
|
+
5. Tham chiếu state bằng `vueData.` trong controls/attr; JSON hợp lệ (không trailing comma)
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Module Structure (Canonical for Workspace and Chat)
|
|
2
|
+
|
|
3
|
+
> File này sở hữu: **cây thư mục project/module, trách nhiệm từng file, `_moduleInfo.json`/`mTitle`, chế độ `HTMLOnly`, meta tag mặc định**. Quy tắc viết `uc-*.vue` xem [component-design.md](component-design.md); nội dung bên trong `module.json` xem [controls-patterns.md](controls-patterns.md). *(Tier A — luôn nạp cùng `skill_get`.)*
|
|
4
|
+
|
|
5
|
+
Use this structure when creating, refactoring, or reviewing a FUI module.
|
|
6
|
+
|
|
7
|
+
- In editor or extension contexts with workspace access, apply it as the real local folder structure.
|
|
8
|
+
- In chat or agent-chat contexts, use it to virtualize the same module structure and organize the response, without assuming the files already exist on disk.
|
|
9
|
+
|
|
10
|
+
## Canonical Local Structure
|
|
11
|
+
|
|
12
|
+
The workspace is organized at two levels: **project** and **module**.
|
|
13
|
+
|
|
14
|
+
### Project-level (root of a checked-out project)
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
{projectId}/
|
|
18
|
+
|-- _projectInfo.json # Project metadata (ProjectID, ProjectName, Framework, etc.)
|
|
19
|
+
|-- project.json # Full project config (data/watch/controls/set at project scope)
|
|
20
|
+
|-- imports/ # Project-scope import files
|
|
21
|
+
| `-- _imports.json # Declared project-level JS/CSS imports
|
|
22
|
+
|-- components/ # Project-scope Vue components
|
|
23
|
+
| |-- _components.json # Component registry
|
|
24
|
+
| `-- uc-*.vue # Project-level custom components
|
|
25
|
+
|-- modules/ # All modules in this project
|
|
26
|
+
| |-- _modules.json # Module list metadata
|
|
27
|
+
| `-- {moduleId}/ # One folder per module (see module-level below)
|
|
28
|
+
`-- skills/ # FUI skill files (auto-copied on checkout)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Module-level (inside `modules/{moduleId}/`)
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
{moduleId}/
|
|
35
|
+
|-- _moduleInfo.json # Required: module metadata + mTitle (page title) + HTMLOnly
|
|
36
|
+
|-- module.json # Required: data/watch/controls/set (unused when HTMLOnly=true)
|
|
37
|
+
|-- script.js # Recommended: helper logic for FUN/EXE/chart/transform
|
|
38
|
+
|-- style.css # Optional: module-wide CSS (published via module_publish_css)
|
|
39
|
+
|-- header.html # Full <head> content: <link>, <style>, <script> tags
|
|
40
|
+
|-- body.html # HTMLOnly=false: supplementary body HTML
|
|
41
|
+
| # HTMLOnly=true: entire page content (custom HTML/Vue app)
|
|
42
|
+
|-- imports/ # Module-scope import files
|
|
43
|
+
| `-- _imports.json # Declared module-level JS/CSS imports
|
|
44
|
+
`-- components/ # Optional: custom Vue components
|
|
45
|
+
|-- _components.json # Required when using custom components
|
|
46
|
+
`-- uc-*.vue # Custom components (prefix uc-)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Chat-Safe Usage
|
|
50
|
+
|
|
51
|
+
When working without local workspace access:
|
|
52
|
+
|
|
53
|
+
1. Present this tree as the canonical module layout, not as a claimed filesystem state.
|
|
54
|
+
2. Return file contents in separate code blocks or clearly labeled sections.
|
|
55
|
+
3. Ask the user to paste `_moduleInfo.json`, `module.json`, `script.js`, or component files when a review or patch depends on existing code.
|
|
56
|
+
4. Scope recommendations to the files actually provided instead of inventing unseen surrounding files.
|
|
57
|
+
|
|
58
|
+
## Required vs Optional
|
|
59
|
+
|
|
60
|
+
1. Required (module-level):
|
|
61
|
+
- `_moduleInfo.json`
|
|
62
|
+
- `module.json`
|
|
63
|
+
|
|
64
|
+
2. Recommended:
|
|
65
|
+
- `script.js`
|
|
66
|
+
- `imports/_imports.json`
|
|
67
|
+
|
|
68
|
+
3. Optional by use-case:
|
|
69
|
+
- `header.html`
|
|
70
|
+
- `body.html`
|
|
71
|
+
- `style.css`
|
|
72
|
+
- `components/` (with `_components.json` and `uc-*.vue`)
|
|
73
|
+
|
|
74
|
+
## File Responsibilities
|
|
75
|
+
|
|
76
|
+
### module.json (core)
|
|
77
|
+
- Keep all runtime config in `data`, `watch`, `controls`, `set`.
|
|
78
|
+
- Keep `controls` under FUI grid wrapper (`container > rows > cols`).
|
|
79
|
+
- Keep business actions in `data` and trigger with `CALL`.
|
|
80
|
+
- **When `HTMLOnly=true`: leave this file empty (`data:[], watch:{}, controls:[], set:{}`). The FUI runtime does not use it.**
|
|
81
|
+
- **JSON content patterns** (data[], watch, controls, actions, dialogs, navigation): see [`examples/module-patterns.json`](../examples/module-patterns.json)
|
|
82
|
+
- **f-table props and header types**: see [`examples/f-table-patterns.json`](../examples/f-table-patterns.json)
|
|
83
|
+
|
|
84
|
+
### script.js (helper logic)
|
|
85
|
+
- Move complex transforms, chart builders, debounce helpers, parsing logic here.
|
|
86
|
+
- Expose functions for `FUN` actions or template helpers.
|
|
87
|
+
- Avoid large inline `EXE` blocks in `module.json` when reusable function is possible.
|
|
88
|
+
|
|
89
|
+
### style.css (module-wide CSS)
|
|
90
|
+
- CSS not tied to a single component — shared/global rules for the module.
|
|
91
|
+
- Published via `module_publish_css` (mirrors `script.js`/`module_publish_script`); does not auto-clear on `module_publish_html` if left empty.
|
|
92
|
+
- Component-local CSS belongs in the component's own `<style scoped>` (see [component-design.md](component-design.md)), not here.
|
|
93
|
+
|
|
94
|
+
### _moduleInfo.json (metadata)
|
|
95
|
+
- Keep `ProjectID`, `ModuleID`, `ModuleName`, `Framework` accurate.
|
|
96
|
+
- Contains `mTitle` (page title). To update the module's page title, edit the `mTitle` field in `_moduleInfo.json`. This value is sent to the server as `title` when publishing via `module_publish_html`.
|
|
97
|
+
- Contains `HTMLOnly` (boolean). **Read this first before deciding how to structure the module.**
|
|
98
|
+
|
|
99
|
+
### header.html (head content)
|
|
100
|
+
- Contains everything that goes **inside** the `<head>` tag — do NOT include the `<head>` wrapper itself.
|
|
101
|
+
- Can contain: `<link>` CSS imports, `<style>` blocks, `<script>` imports, `<meta>` tags.
|
|
102
|
+
- Do NOT put a `<title>` tag here — page title is managed via `mTitle` in `_moduleInfo.json`.
|
|
103
|
+
- **Default meta tags — already present on every FUI page, do NOT repeat them in header.html:**
|
|
104
|
+
```html
|
|
105
|
+
<meta charset="UTF-8"/>
|
|
106
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"/>
|
|
107
|
+
```
|
|
108
|
+
These defaults affect UI design decisions: `user-scalable=no, maximum-scale=1` means users **cannot pinch-zoom** — fonts/buttons must be readable and tappable at natural size on mobile; `width=device-width, initial-scale=1` makes Vuetify breakpoints behave per real device CSS pixels; `viewport-fit=cover` lets the page extend into the iOS notch/home-indicator area — fullscreen/`HTMLOnly` layouts touching top/bottom edges need `env(safe-area-inset-*)` padding.
|
|
109
|
+
- For `HTMLOnly=false`: typically only CSS (`<link>` and `<style>`). Framework and project-level scripts are injected automatically by the server.
|
|
110
|
+
- For `HTMLOnly=true`: **you must bring your own runtime** — see [HTMLOnly=true: KHÔNG có thư viện nào được nhúng sẵn](#htmlonlytrue-không-có-thư-viện-nào-được-nhúng-sẵn) below before writing a single tag.
|
|
111
|
+
|
|
112
|
+
### body.html (body content)
|
|
113
|
+
- Contains everything that goes **inside** the `<body>` tag — do NOT include the `<body>` wrapper itself.
|
|
114
|
+
- **When `HTMLOnly=false`**: supplementary HTML rendered alongside the FUI Vue runtime. Usually empty or minimal.
|
|
115
|
+
- **When `HTMLOnly=true`**: the **entire page content**. Can be plain HTML or a fully custom Vue app (own `<div id="app">`, own `<v-app>`, etc.). The FUI default Vue mount point is hidden in this mode.
|
|
116
|
+
- Both `header.html` and `body.html` store only the **inner content** (no wrapper tags). The server strips wrappers automatically on save, and the publish tool does the same preprocessing.
|
|
117
|
+
|
|
118
|
+
### imports/_imports.json (module imports)
|
|
119
|
+
- Declares module-scope JS/CSS import files.
|
|
120
|
+
- Each entry: `{ name, type, contentType, fileID, scope, sort }`.
|
|
121
|
+
- `sort` — thứ tự load. **Khi thêm import mới: đặt `sort` từ 40 trở lên** (40, 50, 60...). Giá trị nhỏ (1–39) dành cho import hệ thống/framework được load trước — không dùng để tránh xung đột.
|
|
122
|
+
- Only module-scope imports are stored here (project-scope imports are at `{projectId}/imports/_imports.json`).
|
|
123
|
+
|
|
124
|
+
### components/_components.json
|
|
125
|
+
- Register `uc-*` components.
|
|
126
|
+
- Follow upsert rule:
|
|
127
|
+
- Before publish: may only have `comName`.
|
|
128
|
+
- After publish/sync: `comID` is server-managed.
|
|
129
|
+
- Do not handcraft random `comID`.
|
|
130
|
+
|
|
131
|
+
### components/uc-*.vue
|
|
132
|
+
- Use `uc-` prefix for custom components.
|
|
133
|
+
- Keep component-specific UI complexity here instead of bloating `module.json`.
|
|
134
|
+
- Prefer reusable component contracts: props for input, emits for output, slots for extensibility.
|
|
135
|
+
- Avoid baking page-specific API calls or route logic into the component unless that coupling is intentional and unavoidable.
|
|
136
|
+
- `<style scoped>` blocks are allowed, but `scoped` has no real scoping effect — every selector must be manually prefixed with a unique class matching the component name. See [component-design.md](component-design.md) for the full rule and example.
|
|
137
|
+
- Never use backtick template strings inside the component `<template>`.
|
|
138
|
+
|
|
139
|
+
### _projectInfo.json (project metadata)
|
|
140
|
+
- Saved at project root on checkout (`{projectId}/_projectInfo.json`).
|
|
141
|
+
- Contains `ProjectID`, `ProjectName`, `GroupName`, `Framework`, `pDomain`, `fetchedAt`.
|
|
142
|
+
- Read-only for module editing — do not modify.
|
|
143
|
+
|
|
144
|
+
### project.json (project config)
|
|
145
|
+
- Contains a single `data` object — project-level defaults for all modules: `apiDomain`, `login`, `userInfo`, `menu`, `menuLeft`, `menuStyle`, `menuComponent`, `domainSetting`, etc.
|
|
146
|
+
- **Relationship with `module.json` `set`**: runtime merges `project.json data` + `module.json set`, with module values taking priority. A module only needs to declare fields that differ from the project default.
|
|
147
|
+
- See [project-config.md](project-config.md) for full field reference, menu item structure, and `right` permission rules.
|
|
148
|
+
|
|
149
|
+
## Naming and Prefix Rules
|
|
150
|
+
|
|
151
|
+
1. Module folder name:
|
|
152
|
+
- Use the same module ID naming used by project conventions.
|
|
153
|
+
|
|
154
|
+
2. Custom component file:
|
|
155
|
+
- Use `uc-*.vue` kebab-case.
|
|
156
|
+
|
|
157
|
+
3. Component usage in `module.json`:
|
|
158
|
+
- Use `el: "uc-..."` for custom components.
|
|
159
|
+
- Keep prop binding in `attr` with kebab-case prop names.
|
|
160
|
+
|
|
161
|
+
## HTMLOnly Mode
|
|
162
|
+
|
|
163
|
+
`HTMLOnly` is a boolean flag in `_moduleInfo.json`. **Always check this first** before editing a module.
|
|
164
|
+
|
|
165
|
+
### HTMLOnly=false (default — FUI Vue module)
|
|
166
|
+
|
|
167
|
+
- `module.json` is the core: FUI runtime reads `data`, `watch`, `controls`, `set` and bootstraps a Vue app.
|
|
168
|
+
- `body.html` is supplementary HTML rendered in the body alongside the Vue controls (often empty).
|
|
169
|
+
- `header.html` typically contains CSS only (`<link>`, `<style>`). Framework and project-level scripts are auto-injected by the server.
|
|
170
|
+
- Vue components (`uc-*.vue`) are fully supported.
|
|
171
|
+
- `script.js` exposes helper functions used by `FUN`/`EXE` actions.
|
|
172
|
+
|
|
173
|
+
### HTMLOnly=true (custom HTML/Vue page)
|
|
174
|
+
|
|
175
|
+
- `module.json` is **ignored** at runtime — keep it empty (`data:[], watch:{}, controls:[], set:{}`).
|
|
176
|
+
- `body.html` is the **entire page content**. The developer has full control — can write plain HTML or a completely custom Vue app (own `<div id="app">`, own `<v-app>`, own Vue instance).
|
|
177
|
+
- Do NOT attempt to use FUI's `controls`/`data`/`watch` JSON system — it has no effect.
|
|
178
|
+
- Use this mode for: standalone tools, custom editors, pages that need their own runtime or layout that doesn't fit the FUI grid system.
|
|
179
|
+
- **Full-height layout**: nếu trang có `menu` hiển thị (không phải `set.menu: false`), thanh menu chiếm 48px cố định — mọi CSS `height: 100vh` hay `calc(100vh - Npx)` trên container gốc phải cộng thêm 48px vào phần trừ. Xem [project-config.md](project-config.md) §menu.
|
|
180
|
+
|
|
181
|
+
#### HTMLOnly=true: KHÔNG có thư viện nào được nhúng sẵn
|
|
182
|
+
|
|
183
|
+
Đây là điều hay bị hiểu sai nhất về chế độ này, và hiểu sai thì **không có lỗi nào nổi lên lúc
|
|
184
|
+
viết** — chỉ là trang trắng sau khi deploy.
|
|
185
|
+
|
|
186
|
+
Với `HTMLOnly=true`, server chỉ phát ra **ba** thứ:
|
|
187
|
+
|
|
188
|
+
1. import **của chính module này** (`{moduleId}/imports/_imports.json`),
|
|
189
|
+
2. StyleCSS **cấp module** (`style.css` + `<style>` của `uc-*.vue` cấp module),
|
|
190
|
+
3. bundle `moduledata` (`$moduleUI` + `script.js` + component cấp module).
|
|
191
|
+
|
|
192
|
+
Tất cả những thứ sau **KHÔNG** được nhúng — kể cả khi project đang khai chúng:
|
|
193
|
+
|
|
194
|
+
| Không có | Hệ quả nếu bạn cứ giả định là có |
|
|
195
|
+
|---|---|
|
|
196
|
+
| Framework V2/V3 — `vue.global.min.js`, `vuetify*.js/css`, `fastproject*.js`, `component*.js`, `defaultfunction*.js` | `Vue is not defined`, `<v-btn>` không render, `f-*`/`t-*` không tồn tại |
|
|
197
|
+
| jQuery, lodash (`_`), `moment`/`dayjs`, `numeral`, `jquery-confirm` | `$ is not defined`, `_ is not defined` |
|
|
198
|
+
| Roboto, Material Design Icons (`mdi-*`) | chữ sai font, icon thành ô vuông trống |
|
|
199
|
+
| `projectdata` bundle — `$projectData`, `$projectGroupSetting`, component cấp **project** | `apiDomain`/`menu`/`login` đều undefined; `uc-*` cấp project là unknown element |
|
|
200
|
+
| StyleCSS cấp **project**, `projectdefaultstyle.css` | mất toàn bộ class dùng chung của project (kể cả `.shrink`) |
|
|
201
|
+
| `<div id="fastProjectAPP">` | không có mount point sẵn — bạn phải tự dựng gốc trong `body.html` |
|
|
202
|
+
|
|
203
|
+
**Quy tắc:** cần thư viện nào thì tự khai thư viện đó, **cho từng module HTMLOnly một** — khai ở
|
|
204
|
+
cấp project không giúp gì cả. Hai cách, dùng cách nào cũng được:
|
|
205
|
+
|
|
206
|
+
- khai vào `imports/_imports.json` của module (`file_import_new`, `sort >= 40`) — nên dùng, vì
|
|
207
|
+
nó hiện ra trong `file_import_list` và trong báo cáo `module_simulate({renderUI:true})`;
|
|
208
|
+
- hoặc viết thẳng `<link>`/`<script>` vào `header.html` — tự do hơn, nhưng không tool nào liệt kê
|
|
209
|
+
được cho bạn.
|
|
210
|
+
|
|
211
|
+
Hệ quả bị bỏ sót thường xuyên: **[script-map.md](script-map.md) không áp dụng ở chế độ này.** File
|
|
212
|
+
đó liệt kê thư viện "đã bundle sẵn, cấm thêm CDN trùng" — điều đó chỉ đúng với `HTMLOnly=false`.
|
|
213
|
+
Ở HTMLOnly, thêm CDN không phải là trùng lặp, mà là **điều kiện để trang chạy**.
|
|
214
|
+
|
|
215
|
+
`module_simulate({ renderUI: true })` dựng trang **đúng như production** cho module HTMLOnly (bỏ
|
|
216
|
+
framework, bỏ projectdata, bỏ `#fastProjectAPP`) và in một dòng cảnh báo nói rõ điều đó — nên nếu
|
|
217
|
+
bạn quên khai một thư viện, ảnh render sẽ hỏng y hệt trang thật thay vì đẹp giả tạo.
|
|
218
|
+
|
|
219
|
+
## Practical Patterns
|
|
220
|
+
|
|
221
|
+
### Pattern A: Simple module (no custom component)
|
|
222
|
+
|
|
223
|
+
Use:
|
|
224
|
+
- `_moduleInfo.json`
|
|
225
|
+
- `module.json`
|
|
226
|
+
- `script.js`
|
|
227
|
+
- `imports/_imports.json`
|
|
228
|
+
|
|
229
|
+
Skip `components/` unless needed.
|
|
230
|
+
|
|
231
|
+
### Pattern B: Dashboard/report module (recommended split)
|
|
232
|
+
|
|
233
|
+
Use:
|
|
234
|
+
- `module.json` for filters + action orchestration
|
|
235
|
+
- `script.js` for conversion/chart utilities
|
|
236
|
+
- `components/uc-*.vue` for chart/table dashboard presentation
|
|
237
|
+
- `header.html` for module-scoped and component-scoped CSS
|
|
238
|
+
|
|
239
|
+
This pattern matches large report modules and keeps `module.json` maintainable.
|
|
240
|
+
|
|
241
|
+
### Pattern C: HTMLOnly custom page
|
|
242
|
+
|
|
243
|
+
Use:
|
|
244
|
+
- `_moduleInfo.json` (with `HTMLOnly: true`)
|
|
245
|
+
- `module.json` (empty skeleton only)
|
|
246
|
+
- `header.html` for all CSS + JS library imports
|
|
247
|
+
- `body.html` for the entire page — plain HTML or a self-contained Vue app
|
|
248
|
+
|
|
249
|
+
Skip `components/` and `script.js` unless the custom app needs them.
|
|
250
|
+
|
|
251
|
+
## Review Checklist (Structure)
|
|
252
|
+
|
|
253
|
+
1. Check `HTMLOnly` in `_moduleInfo.json` first — it determines which files matter.
|
|
254
|
+
2. If `HTMLOnly=false`: does `module.json` have valid `data/watch/controls/set`?
|
|
255
|
+
3. If `HTMLOnly=true`: is `module.json` empty? Is all content in `body.html`?
|
|
256
|
+
4. Is heavy logic moved to `script.js` instead of oversized `EXE`?
|
|
257
|
+
5. If custom UI exists, is it moved to `components/uc-*.vue`?
|
|
258
|
+
6. If `components/` exists, does `_components.json` register them correctly?
|
|
259
|
+
7. Are imports declared in `imports/_imports.json`?
|
|
260
|
+
8. Do `header.html` and `body.html` contain only inner content (no `<head>`/`<body>` wrapper tags)?
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Mở phiên Claude Code CLI mới
|
|
2
|
+
|
|
3
|
+
> File này sở hữu: **cách mở thêm một phiên Claude Code CLI trong cửa sổ terminal riêng, và cách lấy đúng thư mục workspace cho phiên đó**. Trao đổi giữa các phiên đang chạy xem mục cuối file. Quy trình dựng dự án mới xem [project-provisioning.md](project-provisioning.md).
|
|
4
|
+
|
|
5
|
+
User nói **"new session" / "phiên mới" / "cửa sổ mới" / "mở thêm một session"** → chạy lệnh shell mở
|
|
6
|
+
một cửa sổ terminal mới chạy Claude Code tại thư mục workspace.
|
|
7
|
+
|
|
8
|
+
**Không hỏi lại, không xác nhận.** Đây là thao tác cục bộ, không ghi đè gì, mở nhầm thì đóng cửa sổ
|
|
9
|
+
là xong. Hỏi lại ở đây chỉ làm chậm một việc đáng lẽ một lượt là xong.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Thư mục — LẤY ĐỘNG, không hard-code
|
|
14
|
+
|
|
15
|
+
Workspace root khác nhau ở từng máy. **Không bao giờ viết sẵn một đường dẫn tuyệt đối vào lệnh.**
|
|
16
|
+
Ba nguồn, theo thứ tự ưu tiên:
|
|
17
|
+
|
|
18
|
+
1. **User nêu rõ** trong câu lệnh ("mở session mới ở project X") → dùng đúng cái đó.
|
|
19
|
+
2. **Dòng `Workspace root:`** mà các tool FUI MCP vừa in ra (`module_get`, `skill_sync`,
|
|
20
|
+
`project_sync`… đều in). Đây là nguồn đáng tin nhất vì nó là workspace server đang thực sự dùng.
|
|
21
|
+
3. **Biến môi trường `FUI_MCP_WORKDIR`** — `$env:FUI_MCP_WORKDIR` (PowerShell) /
|
|
22
|
+
`$FUI_MCP_WORKDIR` (bash). Không đặt thì mặc định `~/.fui-mcp/workspaces`.
|
|
23
|
+
|
|
24
|
+
Cả ba đều không ra → **hỏi user**, đừng đoán.
|
|
25
|
+
|
|
26
|
+
Mở phiên cho **một project cụ thể** thì trỏ vào `{workspaceRoot}/{projectId}`; mở để làm việc chung
|
|
27
|
+
thì trỏ vào chính `{workspaceRoot}`.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 2. Lệnh theo hệ điều hành
|
|
32
|
+
|
|
33
|
+
**Windows (PowerShell)** — dạng dùng nhiều nhất:
|
|
34
|
+
|
|
35
|
+
```powershell
|
|
36
|
+
powershell -Command "Start-Process powershell -ArgumentList '-NoExit', '-Command', 'cd ''<THƯ-MỤC>''; claude --rc'"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**macOS:**
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
osascript -e 'tell app "Terminal" to do script "cd \"<THƯ-MỤC>\" && claude --rc"'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Linux** (thay `gnome-terminal` bằng terminal đang dùng):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
gnome-terminal -- bash -c 'cd "<THƯ-MỤC>" && claude --rc; exec bash'
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Mặc định của nhóm là **`claude --rc`**. User nêu flag khác (`-c`, `-r`, `--resume <id>`…) hoặc kèm
|
|
52
|
+
prompt mở đầu thì thay vào chỗ đó.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 3. Xác nhận trước khi báo thành công
|
|
57
|
+
|
|
58
|
+
Lệnh mở cửa sổ **trả về ngay lập tức**, không chờ phiên mới khởi động xong — nên "lệnh chạy xong"
|
|
59
|
+
KHÔNG có nghĩa là phiên đã mở. Kiểm bằng một lượt nữa rồi mới báo:
|
|
60
|
+
|
|
61
|
+
```powershell
|
|
62
|
+
Get-Process powershell -ErrorAction SilentlyContinue | Sort-Object StartTime -Descending |
|
|
63
|
+
Select-Object -First 3 Id, StartTime, MainWindowTitle | Format-Table -AutoSize
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
ps -eo pid,lstart,args | grep -i "[c]laude" | tail -3
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Báo lại **PID + thư mục**. Không thấy tiến trình mới ⇒ nói thẳng là không mở được, **đừng báo thành
|
|
71
|
+
công** — user sẽ đi tìm một cửa sổ không tồn tại.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 4. Quy tắc
|
|
76
|
+
|
|
77
|
+
**Flag của user là đúng, KHÔNG đi kiểm chứng.** User đưa flag nào thì dùng nguyên flag đó. Đừng chạy
|
|
78
|
+
`claude --help` để "xác minh", đừng tự đổi sang flag mình quen hơn, đừng cảnh báo.
|
|
79
|
+
|
|
80
|
+
> Đã có tiền lệ: `claude --rc --help` trả exit 255 + Usage, và điều đó **không** chứng minh `--rc`
|
|
81
|
+
> sai — `--help` bị nuốt làm giá trị của `--rc`. Một phép thử hỏng đem ra bác bỏ cấu hình đang chạy
|
|
82
|
+
> tốt của user là tệ hơn không thử. Đừng lặp lại nó.
|
|
83
|
+
|
|
84
|
+
**Giữ nguyên dạng nháy.** `''<đường dẫn>''` là escape nháy đơn của PowerShell, sống sót qua cả ba
|
|
85
|
+
tầng `cmd → powershell → powershell`, và là thứ giúp đường dẫn **có khoảng trắng** vẫn chạy. Thấy
|
|
86
|
+
"thừa" mà bỏ đi là vỡ đúng ca thư mục có dấu cách.
|
|
87
|
+
|
|
88
|
+
**`-NoExit` bắt buộc giữ** (và `exec bash` ở Linux): thiếu nó thì phiên Claude vừa kết thúc là cửa sổ
|
|
89
|
+
đóng ngay, không đọc được gì.
|
|
90
|
+
|
|
91
|
+
**Trên Windows phải đi qua `powershell`.** `claude` thường được cài dạng `claude.ps1` (script
|
|
92
|
+
PowerShell, không phải `.exe`) nên gọi thẳng từ `cmd` không chạy.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 5. Phiên mới là tiến trình ĐỘC LẬP
|
|
97
|
+
|
|
98
|
+
Hệ quả cần nhớ:
|
|
99
|
+
|
|
100
|
+
- **Session riêng**: active module target, cờ đã-nạp-skill, approval… đều tách biệt (mỗi PID một
|
|
101
|
+
session file). Phiên mới phải tự `skill_get` và tự `session_set`.
|
|
102
|
+
- **Nạp bản build MCP mới nhất**: nếu vừa sửa code MCP mà chưa restart, phiên hiện tại vẫn chạy bản
|
|
103
|
+
cũ còn phiên mới thì chạy bản mới. Đây là cách **kiểm chứng tool vừa thêm** mà không phải restart
|
|
104
|
+
phiên đang làm dở.
|
|
105
|
+
- **Không gõ lệnh vào cửa sổ đó được.** Muốn trao đổi thì dùng `ListAgents` → `SendMessage`: phiên
|
|
106
|
+
mới sẽ hiện ra như một peer session và nhắn qua lại được.
|
|
107
|
+
- **Ranh giới quyền là theo từng phiên.** Không nhờ phiên khác chạy hộ một thao tác vừa bị chặn ở
|
|
108
|
+
phiên này — đó là đi vòng quanh quyết định của user, không phải giải pháp.
|