@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.
- package/README.md +19 -3
- package/dist/fui-bmg5pnmq.js +379 -0
- package/dist/fui.js +1 -1
- package/package.json +7 -6
- package/skills/fui/SKILL.md +9 -41
- package/skills/fui-skill/SKILL.md +95 -225
- package/skills/fui-skill/assets/projectdefaultstyle-3.0.css +555 -0
- package/skills/fui-skill/assets/projectdefaultstyle.css +207 -235
- package/skills/fui-skill/references/INDEX.md +105 -137
- package/skills/fui-skill/references/advanced-techniques.md +76 -68
- package/skills/fui-skill/references/coding-standards.md +56 -56
- package/skills/fui-skill/references/component-design.md +166 -173
- package/skills/fui-skill/references/component-quickref.md +61 -60
- package/skills/fui-skill/references/component-table.md +128 -117
- package/skills/fui-skill/references/components-dialog.md +55 -56
- package/skills/fui-skill/references/components-display.md +24 -30
- package/skills/fui-skill/references/components-echart.md +186 -261
- package/skills/fui-skill/references/components-input.md +72 -96
- package/skills/fui-skill/references/controls-patterns.md +196 -342
- package/skills/fui-skill/references/controls-styling-vocabulary.md +130 -97
- package/skills/fui-skill/references/db-table-design.md +24 -28
- package/skills/fui-skill/references/db-workflow.md +191 -390
- package/skills/fui-skill/references/default-function.md +169 -128
- package/skills/fui-skill/references/design-modes.md +35 -63
- package/skills/fui-skill/references/echart-templates.md +204 -196
- package/skills/fui-skill/references/fastproject.md +62 -60
- package/skills/fui-skill/references/fsheet.md +109 -124
- package/skills/fui-skill/references/fullstack-workflow.md +90 -128
- package/skills/fui-skill/references/module-data-patterns.md +31 -40
- package/skills/fui-skill/references/module-json-anatomy.md +47 -52
- package/skills/fui-skill/references/module-structure.md +80 -196
- package/skills/fui-skill/references/new-session.md +49 -51
- package/skills/fui-skill/references/pdfmake.md +17 -17
- package/skills/fui-skill/references/permission-system.md +89 -108
- package/skills/fui-skill/references/platform-architecture.md +128 -153
- package/skills/fui-skill/references/project-config.md +102 -134
- package/skills/fui-skill/references/project-provisioning.md +139 -244
- package/skills/fui-skill/references/script-map.md +208 -242
- package/skills/fui-skill/references/sql-clr-functions.md +98 -97
- package/skills/fui-skill/references/system-design.md +63 -88
- package/skills/fui-skill/references/tapi-file-api.md +46 -52
- package/skills/fui-skill/references/tapi-permission-patterns.md +51 -53
- package/skills/fui-skill/references/tapi-reference.md +132 -207
- package/skills/fui-skill/references/tools-registry.md +84 -460
- package/skills/fui-skill/references/ui-crosswindow-patterns.md +79 -75
- package/skills/fui-skill/references/ui-dialog-patterns.md +98 -72
- package/skills/fui-skill/references/ui-layout-patterns.md +26 -26
- package/skills/fui-skill/references/ui-patterns.md +71 -83
- package/skills/fui-skill/references/ui-screenshot-review.md +63 -62
- package/skills/fui-skill/references/ui-table-cell-patterns.md +61 -59
- package/skills/fui-skill/references/ui-templates.md +16 -23
- package/skills/fui-skill/references/verification.md +236 -246
- package/skills/fui-skill/references/watcher-patterns.md +30 -63
- package/skills/fui-skill/references/websocket-realtime.md +83 -66
- package/skills/fui-skill/scripts/component-3.0.js +298 -131
- package/skills/fui-skill/scripts/component.js +277 -271
- package/skills/fui-skill/scripts/componentTable-3.0.js +182 -53
- package/skills/fui-skill/scripts/componentTable.js +171 -49
- package/skills/fui-skill/scripts/defaultfunction-3.0.js +88 -3
- package/skills/fui-skill/scripts/defaultfunction.js +88 -3
- package/skills/fui-skill/scripts/fsheet.js +38 -0
- package/dist/fui-x7kph78r.js +0 -420
- package/skills/fui-skill/README.md +0 -112
- package/skills/fui-skill/metadata.json +0 -75
- package/skills/fui-skill-cli/SKILL.md +0 -139
- package/skills/fui-skill-cli/references/INDEX.md +0 -110
- package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
- package/skills/fui-skill-cli/references/coding-standards.md +0 -112
- package/skills/fui-skill-cli/references/component-design.md +0 -448
- package/skills/fui-skill-cli/references/component-quickref.md +0 -78
- package/skills/fui-skill-cli/references/component-table.md +0 -248
- package/skills/fui-skill-cli/references/components-dialog.md +0 -191
- package/skills/fui-skill-cli/references/components-display.md +0 -141
- package/skills/fui-skill-cli/references/components-echart.md +0 -316
- package/skills/fui-skill-cli/references/components-input.md +0 -335
- package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
- package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
- package/skills/fui-skill-cli/references/db-table-design.md +0 -73
- package/skills/fui-skill-cli/references/db-workflow.md +0 -288
- package/skills/fui-skill-cli/references/default-function.md +0 -425
- package/skills/fui-skill-cli/references/design-modes.md +0 -57
- package/skills/fui-skill-cli/references/echart-templates.md +0 -489
- package/skills/fui-skill-cli/references/fastproject.md +0 -99
- package/skills/fui-skill-cli/references/fsheet.md +0 -203
- package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
- package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
- package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
- package/skills/fui-skill-cli/references/module-structure.md +0 -141
- package/skills/fui-skill-cli/references/new-session.md +0 -85
- package/skills/fui-skill-cli/references/pdfmake.md +0 -60
- package/skills/fui-skill-cli/references/permission-system.md +0 -150
- package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
- package/skills/fui-skill-cli/references/project-config.md +0 -303
- package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
- package/skills/fui-skill-cli/references/script-map.md +0 -262
- package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
- package/skills/fui-skill-cli/references/system-design.md +0 -89
- package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
- package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
- package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
- package/skills/fui-skill-cli/references/tools-registry.md +0 -84
- package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
- package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
- package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
- package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
- package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
- package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
- package/skills/fui-skill-cli/references/ui-templates.md +0 -22
- package/skills/fui-skill-cli/references/verification.md +0 -236
- package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
- package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
|
@@ -1,48 +1,20 @@
|
|
|
1
|
-
# Watcher Patterns
|
|
1
|
+
# Watcher Patterns
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Owns: **`watch`: `v_old`, deep-watch, cascading, race control**. Action syntax: [controls-patterns.md](controls-patterns.md).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- Form phụ thuộc nhiều cấp (Tỉnh/Thành -> Quận/Huyện -> Phường/Xã)
|
|
7
|
-
- Bộ lọc theo thuộc tính (status, loại, ngày, keyword, ...)
|
|
5
|
+
Use for multi-level dependent forms (Province → District → Ward) and attribute filters (status, type, date, keyword...). Goals: correct FUI structure (`data`, `watch`, `controls`, `set`), no watcher loops, fewer redundant API calls, maintainable large modules.
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
- Đúng cấu trúc FUI (`module.json`: `data`, `watch`, `controls`, `set`)
|
|
11
|
-
- Tránh vòng lặp watcher
|
|
12
|
-
- Giảm gọi API thừa
|
|
13
|
-
- Dễ bảo trì khi module lớn
|
|
7
|
+
## 1. Rules
|
|
14
8
|
|
|
15
|
-
|
|
9
|
+
1. **Watch the smallest input key** — an ID or filter field (`provinceID`, `districtID`, `filter.status`), not a large object unless needed.
|
|
10
|
+
2. **Split actions by level** — `handleProvinceChange` only resets dependents and calls `apiLoadDistricts`; `handleDistrictChange` only resets the level below and calls `apiLoadWards`; `applyFilters` holds the final list-loading logic.
|
|
11
|
+
3. **`deep-watch` selectively** — only small filter objects (e.g. `filter`). Never deep-watch large arrays like `items`, `tableData`.
|
|
12
|
+
4. **No self-made loops** — never watch the action's own output var; never watch `items` and write `items` in the callback.
|
|
13
|
+
5. **Guard before API calls** — `IF/THEN/ELSE` to validate input (e.g. no province selected → don't load districts).
|
|
14
|
+
6. **Debounce/race control in `script.js`** — watchers only orchestrate; debounce and stale-response-overwrite protection live in JS helpers.
|
|
15
|
+
7. **Force literal strings only via `IN`** — in an action with `IN`, a string without spaces may be read as an expression → use `` `value`` or `"'value'"`. Full rules: [controls-patterns.md §0](controls-patterns.md#0-value-resolution-rules-fundamental).
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
- Watch ID hoặc field filter (`provinceID`, `districtID`, `filter.status`), không watch cả object lớn nếu không cần.
|
|
19
|
-
|
|
20
|
-
2. Tách action theo tầng
|
|
21
|
-
- `handleProvinceChange` chỉ reset dữ liệu phụ thuộc và gọi `apiLoadDistricts`.
|
|
22
|
-
- `handleDistrictChange` chỉ reset cấp dưới và gọi `apiLoadWards`.
|
|
23
|
-
- `applyFilters` gom logic tải list cuối.
|
|
24
|
-
|
|
25
|
-
3. Dùng `deep-watch` có chọn lọc
|
|
26
|
-
- Chỉ dùng cho object filter nhỏ (ví dụ `filter`).
|
|
27
|
-
- Không deep-watch mảng lớn như `items`, `tableData`.
|
|
28
|
-
|
|
29
|
-
4. Không để watcher tự tạo loop
|
|
30
|
-
- Không watch biến output của chính action đó.
|
|
31
|
-
- Không watch `items` rồi trong callback lại ghi `items`.
|
|
32
|
-
|
|
33
|
-
5. Gắn điều kiện trước khi gọi API
|
|
34
|
-
- Dùng `IF/THEN/ELSE` để kiểm tra đầu vào hợp lệ (ví dụ chưa chọn tỉnh thì không gọi huyện).
|
|
35
|
-
|
|
36
|
-
6. Tách debounce/race-control sang `script.js`
|
|
37
|
-
- Watcher giữ vai trò điều phối.
|
|
38
|
-
- Debounce hoặc chống response cũ ghi đè response mới đặt trong helper JS.
|
|
39
|
-
|
|
40
|
-
7. Literal string chỉ ép khi truyền qua `IN`
|
|
41
|
-
- Trong action có `IN`, chuỗi không có khoảng trắng có thể bị core hiểu là expression → dùng
|
|
42
|
-
`` `value`` hoặc `"'value'"`. Quy tắc đầy đủ:
|
|
43
|
-
[controls-patterns.md §0](controls-patterns.md#0-value-resolution-rules-fundamental).
|
|
44
|
-
|
|
45
|
-
## 2. Pattern A: Cascading địa giới hành chính
|
|
17
|
+
## 2. Pattern A: administrative-area cascade
|
|
46
18
|
|
|
47
19
|
```json
|
|
48
20
|
{
|
|
@@ -108,12 +80,9 @@ Mục tiêu:
|
|
|
108
80
|
}
|
|
109
81
|
```
|
|
110
82
|
|
|
111
|
-
|
|
112
|
-
- Watch theo key cụ thể.
|
|
113
|
-
- Reset cấp dưới trước khi gọi API cấp dưới.
|
|
114
|
-
- Có điều kiện tránh gọi API khi null.
|
|
83
|
+
Key points: watch specific keys; reset lower levels before calling their API; guard against calling with null.
|
|
115
84
|
|
|
116
|
-
## 3. Pattern B:
|
|
85
|
+
## 3. Pattern B: filter object + deep-watch
|
|
117
86
|
|
|
118
87
|
```json
|
|
119
88
|
{
|
|
@@ -153,26 +122,24 @@ Mục tiêu:
|
|
|
153
122
|
}
|
|
154
123
|
```
|
|
155
124
|
|
|
156
|
-
|
|
157
|
-
- `filter` nên nhỏ và ổn định.
|
|
158
|
-
- Nếu có text search nhập liên tục, nên debounce trong `script.js`.
|
|
125
|
+
Keep `filter` small and stable. Continuous text-search input → debounce in `script.js`.
|
|
159
126
|
|
|
160
|
-
## 4.
|
|
127
|
+
## 4. Recommended debounce (script.js)
|
|
161
128
|
|
|
162
129
|
```javascript
|
|
163
130
|
var filterTimer = null;
|
|
164
131
|
|
|
165
132
|
function debounceFilter(input) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
133
|
+
var callActionName = input && input.callActionName;
|
|
134
|
+
var waitMs = input && input.waitMs;
|
|
135
|
+
clearTimeout(filterTimer);
|
|
136
|
+
filterTimer = setTimeout(function () {
|
|
137
|
+
CALL(vueData[callActionName]);
|
|
138
|
+
}, waitMs || 350);
|
|
172
139
|
}
|
|
173
140
|
```
|
|
174
141
|
|
|
175
|
-
|
|
142
|
+
Action in `module.json`:
|
|
176
143
|
|
|
177
144
|
```json
|
|
178
145
|
{
|
|
@@ -186,11 +153,11 @@ Ví dụ action trong `module.json`:
|
|
|
186
153
|
}
|
|
187
154
|
```
|
|
188
155
|
|
|
189
|
-
## 5.
|
|
156
|
+
## 5. Watcher QA checklist
|
|
190
157
|
|
|
191
|
-
1. Watch key
|
|
192
|
-
2.
|
|
193
|
-
3.
|
|
194
|
-
4.
|
|
195
|
-
5.
|
|
196
|
-
6.
|
|
158
|
+
1. Watch key small enough (ID/field, not a large object)?
|
|
159
|
+
2. Dependents reset before calling the API?
|
|
160
|
+
3. `IF` guard before API when input is null/empty?
|
|
161
|
+
4. Any watcher loop risk?
|
|
162
|
+
5. Text input needs debounce?
|
|
163
|
+
6. Action with `IN`: literal string rule applied to space-free text values?
|
|
@@ -1,47 +1,41 @@
|
|
|
1
1
|
# FUI Real-time Messaging — WebSocket (SignalR)
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Owns: **real-time/SignalR: `webSocketJoinGroup`, `webSocket_Send`**.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Real-time uses **SignalR** (not the browser WebSocket API), hosted at `ws.fui.vn`. Client logic is already global in `defaultfunction.js` — do not rewrite it. Declare the right structure in `module.json` and use the 3 built-ins: `webSocketConnection`, `webSocketJoinGroup`, `webSocket_Send`.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
## 1.
|
|
9
|
+
## 1. Required imports
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Add 2 JS files with `fui import new` — **in this order** (second depends on first):
|
|
12
12
|
|
|
13
|
-
|
|
|
14
|
-
|
|
15
|
-
| 1 (sort
|
|
16
|
-
| 2 (sort
|
|
13
|
+
| Order | File | Note |
|
|
14
|
+
| --------------- | ------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
15
|
+
| 1 (lower sort) | `https://ws.fui.vn/Scripts/jquery.signalR-2.4.1.min.js` | SignalR client core |
|
|
16
|
+
| 2 (higher sort) | `https://ws.fui.vn/signalr/hubs` | Server-generated hub proxy — JS content despite no `.js` extension |
|
|
17
17
|
|
|
18
|
+
```bash
|
|
19
|
+
fui import new --type .js --content-type link --name "https://ws.fui.vn/Scripts/jquery.signalR-2.4.1.min.js" --sort 100
|
|
20
|
+
fui import new --type .js --content-type link --name "https://ws.fui.vn/signalr/hubs" --sort 110
|
|
18
21
|
```
|
|
19
|
-
file_import_new({
|
|
20
|
-
fileType: ".js", contentType: "link",
|
|
21
|
-
fileName: "https://ws.fui.vn/Scripts/jquery.signalR-2.4.1.min.js",
|
|
22
|
-
fileSort: 100
|
|
23
|
-
})
|
|
24
|
-
file_import_new({
|
|
25
|
-
fileType: ".js", contentType: "link",
|
|
26
|
-
fileName: "https://ws.fui.vn/signalr/hubs",
|
|
27
|
-
fileSort: 110
|
|
28
|
-
})
|
|
29
|
-
```
|
|
30
22
|
|
|
31
|
-
|
|
23
|
+
See `fui import new --help`.
|
|
24
|
+
|
|
25
|
+
> jQuery is already in the FUI runtime — do not import it. Run `fui import list` first to avoid duplicates (same flow as `f-echart` in [components-echart.md](components-echart.md)).
|
|
32
26
|
|
|
33
27
|
---
|
|
34
28
|
|
|
35
|
-
## 2.
|
|
29
|
+
## 2. Auto-connect on module load
|
|
36
30
|
|
|
37
|
-
FUI
|
|
31
|
+
FUI bootstrap (`buildApp` in `fastproject.js`) checks `vueData.webSocket` right after `data[]` runs:
|
|
38
32
|
|
|
39
|
-
-
|
|
40
|
-
- `webSocketState.text
|
|
33
|
+
- If `vueData.webSocket` exists → creates `vueData.webSocketState = { code, text }` and calls `webSocketConnection('https://ws.fui.vn/signalr', vueData.webSocket, vueData.webSocketState)` + `webSocketJoinGroup(vueData.webSocket)`. **Do not call these yourself at bootstrap** — just declare `webSocket` in `data[]`.
|
|
34
|
+
- `webSocketState.text`: `Reconnecting` / `Connected` / `Disconnected`. Bind to UI for debugging (`innerHTML: "{{webSocketState}}"`).
|
|
41
35
|
|
|
42
36
|
---
|
|
43
37
|
|
|
44
|
-
## 3.
|
|
38
|
+
## 3. Declare groups to join — in `data[]`
|
|
45
39
|
|
|
46
40
|
```json
|
|
47
41
|
"data": [
|
|
@@ -57,18 +51,18 @@ FUI's bootstrap (`buildApp` trong `fastproject.js`) kiểm tra `vueData.webSocke
|
|
|
57
51
|
]
|
|
58
52
|
```
|
|
59
53
|
|
|
60
|
-
-
|
|
61
|
-
- **
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
- Group name
|
|
65
|
-
- `` `ThuNha `` / `` `device-abc ``
|
|
54
|
+
- Each **key** of `webSocket` = a group joined on load.
|
|
55
|
+
- **Value type sets receive behavior:**
|
|
56
|
+
- **array** (`[]`) → new messages **pushed** to the end (history: chat log, event list...).
|
|
57
|
+
- **`null` or object** (`{}`) → new message **overwrites** (latest only: status/counter/single notification).
|
|
58
|
+
- Group name: literal (`nhom1`) or **dynamic via `{{ }}` in the key** — `"{{DGroup}}"` resolves to `DGroup`'s current value (e.g. `device-abc`), for per-user/device groups.
|
|
59
|
+
- `` `ThuNha `` / `` `device-abc `` use backtick to force a literal string — see [Value Resolution Rules](controls-patterns.md#0-value-resolution-rules-fundamental).
|
|
66
60
|
|
|
67
61
|
---
|
|
68
62
|
|
|
69
|
-
## 4. Join
|
|
63
|
+
## 4. Join more groups at runtime — `FUN: webSocketJoinGroup`
|
|
70
64
|
|
|
71
|
-
|
|
65
|
+
Join any time, including as an auto-run action in `data[]` (see [ui-patterns.md §1](ui-patterns.md)):
|
|
72
66
|
|
|
73
67
|
```json
|
|
74
68
|
{
|
|
@@ -80,14 +74,14 @@ Ngoài khai báo tĩnh ở mục 3, có thể join thêm group bất cứ lúc n
|
|
|
80
74
|
}
|
|
81
75
|
```
|
|
82
76
|
|
|
83
|
-
- `IN`
|
|
84
|
-
-
|
|
77
|
+
- `IN` **is the `groupObj`** (first param of `webSocketJoinGroup(groupObj, timeout, callBackFunc)`), not mapped by param name. So `FUN` + `IN` **cannot pass `timeout`/`callBackFunc`** — for those use raw `EXE`: `"EXE": "webSocketJoinGroup({Nhom3:null}, 3000, function(){ ... })"`.
|
|
78
|
+
- Use for groups that are **conditional** or known only **after** load (e.g. after an API returns a room/chat ID), instead of static `webSocket: {}`.
|
|
85
79
|
|
|
86
80
|
---
|
|
87
81
|
|
|
88
|
-
## 5.
|
|
82
|
+
## 5. Receive messages
|
|
89
83
|
|
|
90
|
-
### watch (
|
|
84
|
+
### watch (recommended — run logic on new message)
|
|
91
85
|
|
|
92
86
|
```json
|
|
93
87
|
"watch": {
|
|
@@ -96,9 +90,9 @@ Ngoài khai báo tĩnh ở mục 3, có thể join thêm group bất cứ lúc n
|
|
|
96
90
|
}
|
|
97
91
|
```
|
|
98
92
|
|
|
99
|
-
> **
|
|
93
|
+
> **Important:** `watch` keys **cannot** use `{{ }}` (literal, not interpolated) — write the resolved group (`webSocket.device-abc`, not `webSocket.{{DGroup}}`).
|
|
100
94
|
|
|
101
|
-
### Bind
|
|
95
|
+
### Bind directly to UI (raw, no watch)
|
|
102
96
|
|
|
103
97
|
```json
|
|
104
98
|
{
|
|
@@ -107,7 +101,7 @@ Ngoài khai báo tĩnh ở mục 3, có thể join thêm group bất cứ lúc n
|
|
|
107
101
|
}
|
|
108
102
|
```
|
|
109
103
|
|
|
110
|
-
### Debug
|
|
104
|
+
### Debug all state
|
|
111
105
|
|
|
112
106
|
```json
|
|
113
107
|
{ "el": "div", "attr": {}, "innerHTML": "{{webSocket}}" }
|
|
@@ -115,11 +109,11 @@ Ngoài khai báo tĩnh ở mục 3, có thể join thêm group bất cứ lúc n
|
|
|
115
109
|
|
|
116
110
|
---
|
|
117
111
|
|
|
118
|
-
## 6.
|
|
112
|
+
## 6. Send — `webSocket_Send`
|
|
119
113
|
|
|
120
|
-
`webSocket_Send(obj)`
|
|
114
|
+
`webSocket_Send(obj)` takes **one object** `{ group, data }`; `data` may be object, array or string — the function picks the SignalR API (`messageSendObject` / `messageSendArray` / `messageSend`).
|
|
121
115
|
|
|
122
|
-
###
|
|
116
|
+
### Way 1 — `FUN` + `IN` (object payload)
|
|
123
117
|
|
|
124
118
|
```json
|
|
125
119
|
{
|
|
@@ -131,13 +125,13 @@ Ngoài khai báo tĩnh ở mục 3, có thể join thêm group bất cứ lúc n
|
|
|
131
125
|
}
|
|
132
126
|
```
|
|
133
127
|
|
|
134
|
-
###
|
|
128
|
+
### Way 2 — raw `EXE` (read dynamic vueData values)
|
|
135
129
|
|
|
136
130
|
```json
|
|
137
131
|
{ "EXE": "webSocket_Send({ group:'nhom2', data:vueData.messText })" }
|
|
138
132
|
```
|
|
139
133
|
|
|
140
|
-
###
|
|
134
|
+
### Way 3 — array payload
|
|
141
135
|
|
|
142
136
|
```json
|
|
143
137
|
{
|
|
@@ -146,15 +140,15 @@ Ngoài khai báo tĩnh ở mục 3, có thể join thêm group bất cứ lúc n
|
|
|
146
140
|
}
|
|
147
141
|
```
|
|
148
142
|
|
|
149
|
-
###
|
|
143
|
+
### Directly in `script.js` (outside the action engine)
|
|
150
144
|
|
|
151
145
|
```js
|
|
152
|
-
webSocket_Send({ group:
|
|
146
|
+
webSocket_Send({ group: "Nhom3", data: "Gui noi dung từ JS" });
|
|
153
147
|
```
|
|
154
148
|
|
|
155
|
-
###
|
|
149
|
+
### Way 4 — HTTP API (no client SignalR connection needed)
|
|
156
150
|
|
|
157
|
-
|
|
151
|
+
REST endpoint to send to a group:
|
|
158
152
|
|
|
159
153
|
```json
|
|
160
154
|
{
|
|
@@ -163,17 +157,17 @@ FUI cũng expose endpoint REST để gửi tin nhắn tới group mà không c
|
|
|
163
157
|
}
|
|
164
158
|
```
|
|
165
159
|
|
|
166
|
-
Group name
|
|
160
|
+
Group name interpolates in the URL:
|
|
167
161
|
|
|
168
162
|
```json
|
|
169
163
|
{ "API": "https://ws.fui.vn/api/messageSend/{{DGroup}}" }
|
|
170
164
|
```
|
|
171
165
|
|
|
172
|
-
|
|
166
|
+
Use when `FUN`/`EXE` is inconvenient (e.g. server-side sends, or decoupling sending from whether the client holds a SignalR connection).
|
|
173
167
|
|
|
174
168
|
---
|
|
175
169
|
|
|
176
|
-
## 7.
|
|
170
|
+
## 7. Full example
|
|
177
171
|
|
|
178
172
|
```json
|
|
179
173
|
{
|
|
@@ -211,7 +205,10 @@ Dùng cách này khi muốn gửi tin nhắn từ một action/nơi không tiệ
|
|
|
211
205
|
"attr": {
|
|
212
206
|
"label": "send - nhom2",
|
|
213
207
|
":action": [
|
|
214
|
-
{
|
|
208
|
+
{
|
|
209
|
+
"FUN": "webSocket_Send",
|
|
210
|
+
"IN": { "group": "`nhom1", "data": { "text": "doi tuong 1", "text2": "doi tuong 2" } }
|
|
211
|
+
},
|
|
215
212
|
{ "EXE": "webSocket_Send({ group:'nhom2', data:vueData.messText})" },
|
|
216
213
|
{ "FUN": "webSocket_Send", "IN": { "group": "`nhom3", "data": ["mang 1", "mang 2"] } }
|
|
217
214
|
]
|
|
@@ -222,18 +219,38 @@ Dùng cách này khi muốn gửi tin nhắn từ một action/nơi không tiệ
|
|
|
222
219
|
{
|
|
223
220
|
"prop": "",
|
|
224
221
|
"cols": [
|
|
225
|
-
{
|
|
222
|
+
{
|
|
223
|
+
"el": "v-textarea",
|
|
224
|
+
"col": {},
|
|
225
|
+
"attr": { "v-model": "webSocket.nhom2", "label": "Nội dung nhận nhom2", ":required": false, "rows": 5 }
|
|
226
|
+
}
|
|
226
227
|
]
|
|
227
228
|
},
|
|
228
|
-
{ "prop": "", "cols": [
|
|
229
|
+
{ "prop": "", "cols": [{ "el": "div", "col": {}, "attr": {}, "innerHTML": "{{webSocket}}" }] },
|
|
229
230
|
{
|
|
230
231
|
"prop": "",
|
|
231
232
|
"cols": [
|
|
232
|
-
{
|
|
233
|
-
|
|
233
|
+
{
|
|
234
|
+
"el": "f-button",
|
|
235
|
+
"col": {},
|
|
236
|
+
"attr": {
|
|
237
|
+
"label": "send by API - nhom1",
|
|
238
|
+
":action": [
|
|
239
|
+
{ "API": "https://ws.fui.vn/api/messageSend/nhom1", "IN": { "text": "test 1", "text2": "test 2" } }
|
|
240
|
+
]
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"el": "f-button",
|
|
245
|
+
"col": {},
|
|
246
|
+
"attr": {
|
|
247
|
+
":label": "'send by API - ' + DGroup",
|
|
248
|
+
":action": [{ "API": "https://ws.fui.vn/api/messageSend/{{DGroup}}" }]
|
|
249
|
+
}
|
|
250
|
+
}
|
|
234
251
|
]
|
|
235
252
|
},
|
|
236
|
-
{ "prop": "", "cols": [
|
|
253
|
+
{ "prop": "", "cols": [{ "el": "div", "col": {}, "attr": {}, "innerHTML": "{{webSocketState}}" }] }
|
|
237
254
|
]
|
|
238
255
|
}
|
|
239
256
|
],
|
|
@@ -243,12 +260,12 @@ Dùng cách này khi muốn gửi tin nhắn từ một action/nơi không tiệ
|
|
|
243
260
|
|
|
244
261
|
---
|
|
245
262
|
|
|
246
|
-
## 8. Checklist
|
|
263
|
+
## 8. Checklist
|
|
247
264
|
|
|
248
|
-
- [ ] `
|
|
249
|
-
- [ ]
|
|
250
|
-
- [ ]
|
|
251
|
-
- [ ]
|
|
252
|
-
- [ ]
|
|
253
|
-
- [ ]
|
|
254
|
-
- [ ]
|
|
265
|
+
- [ ] `fui import list`: are `jquery.signalR-2.4.1.min.js` + `signalr/hubs` present?
|
|
266
|
+
- [ ] Missing → `fui import new` both, sort order signalR first, hubs second
|
|
267
|
+
- [ ] Declare `data[].webSocket = { groupName: [] | null | {} }` — value type by need (history vs latest)
|
|
268
|
+
- [ ] Runtime/conditional groups → `FUN: webSocketJoinGroup` (no `timeout`/`callBackFunc` via `IN`; use `EXE` if needed)
|
|
269
|
+
- [ ] Receive: `watch` (literal key, no `{{ }}`) or bind `v-model="webSocket.<group>"`
|
|
270
|
+
- [ ] Send: `FUN: webSocket_Send` (object/array), `EXE` for dynamic `vueData`, or `API: https://ws.fui.vn/api/messageSend/<group>` for HTTP instead of client SignalR
|
|
271
|
+
- [ ] Use `vueData.webSocketState` if the user needs to see connection status
|