@fui-org/fui-cli 1.3.2 → 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 +3 -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-y8an39cn.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,425 +0,0 @@
|
|
|
1
|
-
# Default Functions
|
|
2
|
-
|
|
3
|
-
> Owns: **FUI utility functions usable in `FUN`/`EXE`/`script.js`** (openWindow, ajaxCALL, jsonToExcel, groupBy...). Source locations: [script-map.md](script-map.md).
|
|
4
|
-
|
|
5
|
-
Globals defined in `defaultfunction.js`, auto-loaded in every FUI V2 module.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Global Variables
|
|
10
|
-
|
|
11
|
-
| Variable | Meaning |
|
|
12
|
-
| ----------- | ------------------------------------------- |
|
|
13
|
-
| `$isMobile` | `true` if mobile user agent |
|
|
14
|
-
| `$isPhone` | `true` if phone (not tablet) |
|
|
15
|
-
| `$isApple` | `true` if Apple device (iPad, iPhone, iPod) |
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Dialogs & Messages
|
|
20
|
-
|
|
21
|
-
### confirm(obj)
|
|
22
|
-
|
|
23
|
-
Styled OK/Cancel dialog; wraps `$.confirm` (jquery-confirm).
|
|
24
|
-
|
|
25
|
-
| Param | Meaning |
|
|
26
|
-
| --------- | --------------------------------------------------------- |
|
|
27
|
-
| `title` | Title |
|
|
28
|
-
| `message` | Body |
|
|
29
|
-
| `action` | Function run on OK |
|
|
30
|
-
| `cancel` | Function run on Cancel (optional) |
|
|
31
|
-
| `type` | Color: `'blue'` (default), `'red'`, `'green'`, `'orange'` |
|
|
32
|
-
| `icon` | Icon class, e.g. `'mdi mdi-delete'` |
|
|
33
|
-
|
|
34
|
-
```js
|
|
35
|
-
confirm({
|
|
36
|
-
title: "Xác nhận xóa",
|
|
37
|
-
message: "Bạn có chắc muốn xóa bản ghi này không?",
|
|
38
|
-
type: "red",
|
|
39
|
-
icon: "mdi mdi-delete",
|
|
40
|
-
action: function () {
|
|
41
|
-
CALL(vueData.actDelete);
|
|
42
|
-
},
|
|
43
|
-
});
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
### showMessage(obj)
|
|
49
|
-
|
|
50
|
-
Message dialog (Close button only); wraps `$.dialog`.
|
|
51
|
-
|
|
52
|
-
| Param | Meaning |
|
|
53
|
-
| --------- | ----------------------------------- |
|
|
54
|
-
| `title` | Title |
|
|
55
|
-
| `message` | Body |
|
|
56
|
-
| `type` | Color: `'blue'`, `'red'`, `'green'` |
|
|
57
|
-
| `icon` | Icon class |
|
|
58
|
-
| `onclose` | FUI action object run after close |
|
|
59
|
-
|
|
60
|
-
```js
|
|
61
|
-
showMessage({ title: "Thông báo", message: "Lưu thành công!" });
|
|
62
|
-
|
|
63
|
-
showMessage({
|
|
64
|
-
title: "Lỗi",
|
|
65
|
-
message: "Không tìm thấy dữ liệu",
|
|
66
|
-
type: "red",
|
|
67
|
-
icon: "mdi mdi-alert-circle",
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// Chạy action sau khi đóng
|
|
71
|
-
showMessage({
|
|
72
|
-
title: "Hoàn tất",
|
|
73
|
-
message: "Import xong!",
|
|
74
|
-
onclose: vueData.actReload,
|
|
75
|
-
});
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
## Navigation & Window
|
|
81
|
-
|
|
82
|
-
### pushRouter(router)
|
|
83
|
-
|
|
84
|
-
Updates the browser URL without reload — sync URL with UI state.
|
|
85
|
-
|
|
86
|
-
```js
|
|
87
|
-
pushRouter("/fp/don-hang/danh-sach");
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
### openWindow(obj)
|
|
93
|
-
|
|
94
|
-
Opens an FUI window (`f-window`) overlay.
|
|
95
|
-
|
|
96
|
-
| Param | Meaning |
|
|
97
|
-
| -------- | --------------------------------------------------------- |
|
|
98
|
-
| `url` | Content URL (required) |
|
|
99
|
-
| `title` | Window title |
|
|
100
|
-
| `id` | Identifier (auto if omitted) — prevents duplicate windows |
|
|
101
|
-
| `width` | Width (px or %) |
|
|
102
|
-
| `height` | Height |
|
|
103
|
-
|
|
104
|
-
```js
|
|
105
|
-
// Cách đơn giản — chỉ truyền URL
|
|
106
|
-
openWindow("/fp/san-pham/chi-tiet?id=123");
|
|
107
|
-
|
|
108
|
-
// Đầy đủ options
|
|
109
|
-
openWindow({
|
|
110
|
-
id: "winChiTiet",
|
|
111
|
-
url: "/fp/san-pham/chi-tiet?id=" + vueData.selectedId,
|
|
112
|
-
title: "Chi tiết sản phẩm",
|
|
113
|
-
width: "80%",
|
|
114
|
-
});
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
> Called inside an `f-window` (iframe) → FUI switches to `windowSendMessage('#PARENT', 'openWindow', obj)` to open in the parent.
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
### redirect(obj, query)
|
|
122
|
-
|
|
123
|
-
Navigates the current page to another URL.
|
|
124
|
-
|
|
125
|
-
```js
|
|
126
|
-
redirect("/fp/trang-chu");
|
|
127
|
-
redirect({ url: "/fp/don-hang", query: true }); // giữ lại query params hiện tại
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
### reload()
|
|
133
|
-
|
|
134
|
-
Reloads the page.
|
|
135
|
-
|
|
136
|
-
```js
|
|
137
|
-
reload();
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
### windowSendMessage(window, cmd, data)
|
|
143
|
-
|
|
144
|
-
`postMessage` to another window/iframe — communication between `f-window`s.
|
|
145
|
-
|
|
146
|
-
| Param | Meaning |
|
|
147
|
-
| -------- | ----------------------------------------------------------------- |
|
|
148
|
-
| `window` | Window object, `'#PARENT'` (parent), or `'#iframeId'` (iframe ID) |
|
|
149
|
-
| `cmd` | Command name |
|
|
150
|
-
| `data` | Payload |
|
|
151
|
-
|
|
152
|
-
```js
|
|
153
|
-
// Gửi lên cửa sổ cha
|
|
154
|
-
windowSendMessage("#PARENT", "refreshData", { id: vueData.selectedId });
|
|
155
|
-
|
|
156
|
-
// Gửi đến iframe có id="iframeChild"
|
|
157
|
-
windowSendMessage("#iframeChild", "loadItem", { itemId: 5 });
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
## AJAX
|
|
163
|
-
|
|
164
|
-
### ajaxCALL(URL, DATA, callBack, errorCallBack, header)
|
|
165
|
-
|
|
166
|
-
AJAX POST. Pass only the path — domain is added via `fixURL`.
|
|
167
|
-
|
|
168
|
-
```js
|
|
169
|
-
ajaxCALL("/SP_GetDonHang", { maKH: vueData.maKH }, function (res) {
|
|
170
|
-
vueData.danhSach = res.data;
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
// Với error handler
|
|
174
|
-
ajaxCALL(
|
|
175
|
-
"/SP_SaveDonHang",
|
|
176
|
-
vueData.form,
|
|
177
|
-
function (res) {
|
|
178
|
-
Vue.$toast.success("Lưu thành công", { position: "top" });
|
|
179
|
-
},
|
|
180
|
-
function (err) {
|
|
181
|
-
showMessage({ title: "Lỗi", message: err.message, type: "red" });
|
|
182
|
-
},
|
|
183
|
-
);
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## File Export
|
|
189
|
-
|
|
190
|
-
### jsonToExcel(Obj)
|
|
191
|
-
|
|
192
|
-
Exports JSON to `.xlsx`. Auto-loads ExcelJS.
|
|
193
|
-
|
|
194
|
-
**Single sheet:**
|
|
195
|
-
|
|
196
|
-
```js
|
|
197
|
-
jsonToExcel({
|
|
198
|
-
data: vueData.danhSach, // Array of objects
|
|
199
|
-
filename: "danh-sach.xlsx",
|
|
200
|
-
worksheet: "DanhSach",
|
|
201
|
-
});
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
**Multi sheet:**
|
|
205
|
-
|
|
206
|
-
```js
|
|
207
|
-
jsonToExcel({
|
|
208
|
-
filename: "bao-cao.xlsx",
|
|
209
|
-
sheets: [
|
|
210
|
-
{ name: "Sheet1", data: vueData.list1 },
|
|
211
|
-
{ name: "Sheet2", data: vueData.list2 },
|
|
212
|
-
],
|
|
213
|
-
});
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
---
|
|
217
|
-
|
|
218
|
-
## Data Utilities
|
|
219
|
-
|
|
220
|
-
### groupBy(arrayObj, groupField, sumArr)
|
|
221
|
-
|
|
222
|
-
Groups objects by a field and sums numeric columns; returns grouped array with `count`.
|
|
223
|
-
|
|
224
|
-
```js
|
|
225
|
-
// groupBy(data, 'Khoa', ['SLNghiHoc', 'SLTotNghiep'])
|
|
226
|
-
var result = groupBy(vueData.data, "phongBan", ["soLuong", "doanhThu"]);
|
|
227
|
-
// result: [{ phongBan: 'A', soLuong: 10, doanhThu: 5000, count: 3 }, ...]
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
> For complex grouping use Lodash `_.groupBy`.
|
|
231
|
-
|
|
232
|
-
---
|
|
233
|
-
|
|
234
|
-
### findInArray(obj)
|
|
235
|
-
|
|
236
|
-
Finds an element by condition.
|
|
237
|
-
|
|
238
|
-
```js
|
|
239
|
-
var item = findInArray({ array: vueData.list, value: { id: 5 } });
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
> Usually prefer the shorter Lodash `_.find(array, condition)`.
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
### fillData(obj)
|
|
247
|
-
|
|
248
|
-
Copies data from a source array into a target object by key and mapping.
|
|
249
|
-
|
|
250
|
-
- **Parameters:** `{ src, des, key, map }` — src: source array, des: target object, key: matching value, map: field mapping
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
### buildHeader(obj, mapCol)
|
|
255
|
-
|
|
256
|
-
Builds `headers` for `f-table` from data. No `mapCol` → headers from the first record's keys (numeric columns get `el: 't-num'`); with `mapCol` → mapped from `{ text, value }`.
|
|
257
|
-
|
|
258
|
-
```js
|
|
259
|
-
// Tự dựng header từ dữ liệu API
|
|
260
|
-
vueData.headers = buildHeader(vueData.dsData);
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
### capacityText(numb)
|
|
264
|
-
|
|
265
|
-
Bytes → size string (`'1.5 Mb'`, `'320 Kb'`) for file sizes.
|
|
266
|
-
|
|
267
|
-
### appCommand(cmdData)
|
|
268
|
-
|
|
269
|
-
Sends a command to the native app (React Native / iOS webkit / Android) when FUI is embedded in a mobile app.
|
|
270
|
-
|
|
271
|
-
---
|
|
272
|
-
|
|
273
|
-
## PDF
|
|
274
|
-
|
|
275
|
-
### printPDF(obj)
|
|
276
|
-
|
|
277
|
-
Builds and prints/downloads a PDF with `pdfMake`. Auto-loads pdfMake.
|
|
278
|
-
|
|
279
|
-
```js
|
|
280
|
-
printPDF({
|
|
281
|
-
data: docDefinition, // pdfMake docDefinition object
|
|
282
|
-
download: true, // true = tải file, false = mở viewer
|
|
283
|
-
callBack: function () {
|
|
284
|
-
console.log("Done");
|
|
285
|
-
},
|
|
286
|
-
});
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
|
|
291
|
-
## Clipboard & String
|
|
292
|
-
|
|
293
|
-
### copyToClipboard(textToCopy)
|
|
294
|
-
|
|
295
|
-
Copies to clipboard; uses `navigator.clipboard` when available (HTTPS), else `execCommand`.
|
|
296
|
-
|
|
297
|
-
```js
|
|
298
|
-
copyToClipboard(vueData.maHoaDon);
|
|
299
|
-
copyToClipboard(JSON.stringify(vueData.data));
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
---
|
|
303
|
-
|
|
304
|
-
### fileNameClear(fname)
|
|
305
|
-
|
|
306
|
-
Strips special characters from a file name (keeps letters, digits, spaces, dashes).
|
|
307
|
-
|
|
308
|
-
```js
|
|
309
|
-
var safeName = fileNameClear(vueData.tenFile); // "report (2025)!" → "report 2025"
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
---
|
|
313
|
-
|
|
314
|
-
### hashCode(s)
|
|
315
|
-
|
|
316
|
-
Integer hash of a string (for unique keys).
|
|
317
|
-
|
|
318
|
-
```js
|
|
319
|
-
var key = hashCode("unique-string-" + Date.now());
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
---
|
|
323
|
-
|
|
324
|
-
### generateID()
|
|
325
|
-
|
|
326
|
-
Random string ID.
|
|
327
|
-
|
|
328
|
-
```js
|
|
329
|
-
var newId = "win_" + generateID();
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
---
|
|
333
|
-
|
|
334
|
-
## Cookie & Auth
|
|
335
|
-
|
|
336
|
-
### getCookie(cname) / setCookie(name, value, days, domain)
|
|
337
|
-
|
|
338
|
-
Read/write browser cookies.
|
|
339
|
-
|
|
340
|
-
```js
|
|
341
|
-
var token = getCookie("awt");
|
|
342
|
-
setCookie("theme", "dark", 30); // hết hạn sau 30 ngày
|
|
343
|
-
setCookie("lang", "vi", 365, ".fui.vn"); // share cookie toàn domain
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
---
|
|
347
|
-
|
|
348
|
-
### logout(cookiesName, domain, url)
|
|
349
|
-
|
|
350
|
-
Clears the cookie and redirects to login.
|
|
351
|
-
|
|
352
|
-
```js
|
|
353
|
-
logout(); // xóa cookie 'awt', redirect về login mặc định
|
|
354
|
-
logout("myToken", ".fui.vn", "/login");
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
---
|
|
358
|
-
|
|
359
|
-
## Permissions
|
|
360
|
-
|
|
361
|
-
### rightTest(rightObject)
|
|
362
|
-
|
|
363
|
-
Checks whether the current user has the required rights, against `vueData.user`.
|
|
364
|
-
|
|
365
|
-
```js
|
|
366
|
-
// Kiểm tra user có role 'admin' hoặc 'manager'
|
|
367
|
-
if (rightTest({ role: ['admin', 'manager'] })) {
|
|
368
|
-
vueData.showDelete = true;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// Kiểm tra nhiều điều kiện cùng lúc (AND)
|
|
372
|
-
if (rightTest({ dept: 'IT', level: [1, 2] })) { ... }
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
---
|
|
376
|
-
|
|
377
|
-
## Color Utilities
|
|
378
|
-
|
|
379
|
-
### colorLib(color)
|
|
380
|
-
|
|
381
|
-
Color utility (hex, rgb, hsl), mostly for charts.
|
|
382
|
-
|
|
383
|
-
```js
|
|
384
|
-
var c = colorLib("#4e73df");
|
|
385
|
-
c.hexString(); // '#4e73df'
|
|
386
|
-
c.rgbString(); // 'rgb(78, 115, 223)'
|
|
387
|
-
c.lighten(0.2); // làm sáng 20%
|
|
388
|
-
c.darken(0.1); // làm tối 10%
|
|
389
|
-
c.alpha(0.5).rgbString(); // 'rgba(78, 115, 223, 0.5)'
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
### transparentize(value, opacity)
|
|
393
|
-
|
|
394
|
-
Shortcut for a transparent color.
|
|
395
|
-
|
|
396
|
-
```js
|
|
397
|
-
transparentize("#4e73df", 0.5); // 'rgba(78, 115, 223, 0.5)'
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
---
|
|
401
|
-
|
|
402
|
-
## Script Loader
|
|
403
|
-
|
|
404
|
-
### loadScripts(scriptsArray, callbackFunc)
|
|
405
|
-
|
|
406
|
-
Loads scripts by URL, then runs the callback — on-demand libraries.
|
|
407
|
-
|
|
408
|
-
```js
|
|
409
|
-
loadScripts(["/include/pdfmake/pdfmake.min.js", "/include/pdfmake/vfs_fonts.js"], function () {
|
|
410
|
-
printPDF({ data: docDef, download: true });
|
|
411
|
-
});
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
---
|
|
415
|
-
|
|
416
|
-
## Device Detection
|
|
417
|
-
|
|
418
|
-
### extractHostname(url) / getDomainWithoutSubdomain(url)
|
|
419
|
-
|
|
420
|
-
Extract hostname/domain from a URL. Internal; rarely used directly.
|
|
421
|
-
|
|
422
|
-
```js
|
|
423
|
-
extractHostname("https://api.fui.vn/fp/test"); // 'api.fui.vn'
|
|
424
|
-
getDomainWithoutSubdomain("https://api.fui.vn"); // 'fui.vn'
|
|
425
|
-
```
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# Design System — App-mode vs Web-mode
|
|
2
|
-
|
|
3
|
-
> Owns: **aesthetic mode decision, `border-radius` limits, the `{projectId}/DESIGN.md` accumulation loop**. Approved class/prop/style: [controls-styling-vocabulary.md](controls-styling-vocabulary.md). Standard dialog/form anatomy: `fui design read fui`.
|
|
4
|
-
|
|
5
|
-
Before writing any `controls`, decide the module's mode. This is the first, **hard** decision — each mode has its own aesthetic rules; never borrow across.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 1. The two modes
|
|
10
|
-
|
|
11
|
-
| | **App-mode** (default) | **Web-mode** |
|
|
12
|
-
| -------------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
13
|
-
| Applies to | Management software: CRUD, lists, forms, internal dashboards, permissions | Landing pages, product intros, public pages (usually `HTMLOnly: true`) |
|
|
14
|
-
| Aesthetic source | **ONLY** `fui design read fui` + `controls-styling-vocabulary.md` | Brand DESIGN.md (`fui design list` → `fui design read <brand>`) |
|
|
15
|
-
| Brand DESIGN.md (nike, linear, bmw...) | **FORBIDDEN** — even "just the colors" | Allowed, pick by tone/industry |
|
|
16
|
-
| Custom style/class | **FORBIDDEN** (per `controls-styling-vocabulary.md`) | Allowed in `header.html` |
|
|
17
|
-
| Component preference | `f-*` / `v-*` per FUI standard | Free HTML/CSS |
|
|
18
|
-
|
|
19
|
-
**Web-mode signals**: `HTMLOnly: true` in `_moduleInfo.json`, or user says "landing page / intro page / public home page". Everything else → App-mode. Unsure → **ask the user**.
|
|
20
|
-
|
|
21
|
-
⚠️ `HTMLOnly: true` is not just an aesthetic signal: the server then embeds **no** V2/V3 JS/CSS library (not Vue, Vuetify, jQuery, lodash, MDI, `projectdefaultstyle.css`) — declare everything needed in the module itself. Read [module-structure.md §HTMLOnly=true: no library is embedded](module-structure.md#htmlonlytrue-no-library-is-embedded) **before** writing the first tag.
|
|
22
|
-
|
|
23
|
-
**Mandatory in App-mode**: before writing/editing layout, dialog or form, load `fui design read fui` (if not loaded this session) for the standard anatomy (f-dialog-style `v-dialog`, floating-label form, color/icon palette), and read `controls-styling-vocabulary.md`. Finish this reading **before sketching or writing controls** — never design while guessing rules from memory.
|
|
24
|
-
|
|
25
|
-
Before designing, confirm the three core UI rule groups from their owner files: icon sizes and styling vocabulary (`controls-styling-vocabulary.md`), dialog anatomy/actions (`fui design read fui` + `ui-dialog-patterns.md`), and vertical alignment of controls in a row (`controls-patterns.md` §Vertical centering). If the task has a dialog, also read `ui-dialog-patterns.md` before sketching it.
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## 2. Per-project override — `{projectId}/DESIGN.md`
|
|
30
|
-
|
|
31
|
-
If `{projectId}/DESIGN.md` exists in the workspace, it **overrides** same-topic rules of the active mode (unmentioned topics follow the common standard). **Always check it before designing.**
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## 3. Design-rule accumulation loop (MANDATORY)
|
|
36
|
-
|
|
37
|
-
When the user critiques a UI detail ("dialog must...", "this button's color...", "don't use..."):
|
|
38
|
-
|
|
39
|
-
1. Fix the module per the feedback.
|
|
40
|
-
2. **Immediately write the rule into `{projectId}/DESIGN.md`** (create it if missing — use the template at the end of `fui design read fui`), phrased as a **general rule + correct/incorrect JSON examples**, not just the specific incident.
|
|
41
|
-
3. If the rule clearly applies to EVERY project → tell the user "this rule should go into the common standard `fui/DESIGN.md`" and propose the content — **only the user decides** to update the common standard.
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## 4. `border-radius` limits
|
|
46
|
-
|
|
47
|
-
Apply to **EVERY brand/style, even when a brand DESIGN.md suggests larger values**:
|
|
48
|
-
|
|
49
|
-
| Frame type | Max `border-radius` |
|
|
50
|
-
| ------------------------------------------------------------------ | ------------------- |
|
|
51
|
-
| Large frames (card container, dialog, section wrapper, main panel) | `12px` |
|
|
52
|
-
| Medium frames (large button, input group, sub-panel, toolbar) | `8px` |
|
|
53
|
-
| Small frames (small button, chip, badge, tag, icon container) | `6px` |
|
|
54
|
-
|
|
55
|
-
If a brand DESIGN.md suggests a larger radius (heavily rounded brands like Airbnb, Notion, Nike...) → **lower it to the allowed max**; never use the original value.
|
|
56
|
-
|
|
57
|
-
**Exception**: fully round elements (avatar, round dot icon button) use `border-radius: 50%` — outside these limits.
|