@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.
Files changed (111) hide show
  1. package/README.md +19 -3
  2. package/dist/fui-bmg5pnmq.js +379 -0
  3. package/dist/fui.js +1 -1
  4. package/package.json +3 -6
  5. package/skills/fui/SKILL.md +9 -41
  6. package/skills/fui-skill/SKILL.md +95 -225
  7. package/skills/fui-skill/assets/projectdefaultstyle-3.0.css +555 -0
  8. package/skills/fui-skill/assets/projectdefaultstyle.css +207 -235
  9. package/skills/fui-skill/references/INDEX.md +105 -137
  10. package/skills/fui-skill/references/advanced-techniques.md +76 -68
  11. package/skills/fui-skill/references/coding-standards.md +56 -56
  12. package/skills/fui-skill/references/component-design.md +166 -173
  13. package/skills/fui-skill/references/component-quickref.md +61 -60
  14. package/skills/fui-skill/references/component-table.md +128 -117
  15. package/skills/fui-skill/references/components-dialog.md +55 -56
  16. package/skills/fui-skill/references/components-display.md +24 -30
  17. package/skills/fui-skill/references/components-echart.md +186 -261
  18. package/skills/fui-skill/references/components-input.md +72 -96
  19. package/skills/fui-skill/references/controls-patterns.md +196 -342
  20. package/skills/fui-skill/references/controls-styling-vocabulary.md +130 -97
  21. package/skills/fui-skill/references/db-table-design.md +24 -28
  22. package/skills/fui-skill/references/db-workflow.md +191 -390
  23. package/skills/fui-skill/references/default-function.md +169 -128
  24. package/skills/fui-skill/references/design-modes.md +35 -63
  25. package/skills/fui-skill/references/echart-templates.md +204 -196
  26. package/skills/fui-skill/references/fastproject.md +62 -60
  27. package/skills/fui-skill/references/fsheet.md +109 -124
  28. package/skills/fui-skill/references/fullstack-workflow.md +90 -128
  29. package/skills/fui-skill/references/module-data-patterns.md +31 -40
  30. package/skills/fui-skill/references/module-json-anatomy.md +47 -52
  31. package/skills/fui-skill/references/module-structure.md +80 -196
  32. package/skills/fui-skill/references/new-session.md +49 -51
  33. package/skills/fui-skill/references/pdfmake.md +17 -17
  34. package/skills/fui-skill/references/permission-system.md +89 -108
  35. package/skills/fui-skill/references/platform-architecture.md +128 -153
  36. package/skills/fui-skill/references/project-config.md +102 -134
  37. package/skills/fui-skill/references/project-provisioning.md +139 -244
  38. package/skills/fui-skill/references/script-map.md +208 -242
  39. package/skills/fui-skill/references/sql-clr-functions.md +98 -97
  40. package/skills/fui-skill/references/system-design.md +63 -88
  41. package/skills/fui-skill/references/tapi-file-api.md +46 -52
  42. package/skills/fui-skill/references/tapi-permission-patterns.md +51 -53
  43. package/skills/fui-skill/references/tapi-reference.md +132 -207
  44. package/skills/fui-skill/references/tools-registry.md +84 -460
  45. package/skills/fui-skill/references/ui-crosswindow-patterns.md +79 -75
  46. package/skills/fui-skill/references/ui-dialog-patterns.md +98 -72
  47. package/skills/fui-skill/references/ui-layout-patterns.md +26 -26
  48. package/skills/fui-skill/references/ui-patterns.md +71 -83
  49. package/skills/fui-skill/references/ui-screenshot-review.md +63 -62
  50. package/skills/fui-skill/references/ui-table-cell-patterns.md +61 -59
  51. package/skills/fui-skill/references/ui-templates.md +16 -23
  52. package/skills/fui-skill/references/verification.md +236 -246
  53. package/skills/fui-skill/references/watcher-patterns.md +30 -63
  54. package/skills/fui-skill/references/websocket-realtime.md +83 -66
  55. package/skills/fui-skill/scripts/component-3.0.js +298 -131
  56. package/skills/fui-skill/scripts/component.js +277 -271
  57. package/skills/fui-skill/scripts/componentTable-3.0.js +182 -53
  58. package/skills/fui-skill/scripts/componentTable.js +171 -49
  59. package/skills/fui-skill/scripts/defaultfunction-3.0.js +88 -3
  60. package/skills/fui-skill/scripts/defaultfunction.js +88 -3
  61. package/skills/fui-skill/scripts/fsheet.js +38 -0
  62. package/dist/fui-y8an39cn.js +0 -420
  63. package/skills/fui-skill/README.md +0 -112
  64. package/skills/fui-skill/metadata.json +0 -75
  65. package/skills/fui-skill-cli/SKILL.md +0 -139
  66. package/skills/fui-skill-cli/references/INDEX.md +0 -110
  67. package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
  68. package/skills/fui-skill-cli/references/coding-standards.md +0 -112
  69. package/skills/fui-skill-cli/references/component-design.md +0 -448
  70. package/skills/fui-skill-cli/references/component-quickref.md +0 -78
  71. package/skills/fui-skill-cli/references/component-table.md +0 -248
  72. package/skills/fui-skill-cli/references/components-dialog.md +0 -191
  73. package/skills/fui-skill-cli/references/components-display.md +0 -141
  74. package/skills/fui-skill-cli/references/components-echart.md +0 -316
  75. package/skills/fui-skill-cli/references/components-input.md +0 -335
  76. package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
  77. package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
  78. package/skills/fui-skill-cli/references/db-table-design.md +0 -73
  79. package/skills/fui-skill-cli/references/db-workflow.md +0 -288
  80. package/skills/fui-skill-cli/references/default-function.md +0 -425
  81. package/skills/fui-skill-cli/references/design-modes.md +0 -57
  82. package/skills/fui-skill-cli/references/echart-templates.md +0 -489
  83. package/skills/fui-skill-cli/references/fastproject.md +0 -99
  84. package/skills/fui-skill-cli/references/fsheet.md +0 -203
  85. package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
  86. package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
  87. package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
  88. package/skills/fui-skill-cli/references/module-structure.md +0 -141
  89. package/skills/fui-skill-cli/references/new-session.md +0 -85
  90. package/skills/fui-skill-cli/references/pdfmake.md +0 -60
  91. package/skills/fui-skill-cli/references/permission-system.md +0 -150
  92. package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
  93. package/skills/fui-skill-cli/references/project-config.md +0 -303
  94. package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
  95. package/skills/fui-skill-cli/references/script-map.md +0 -262
  96. package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
  97. package/skills/fui-skill-cli/references/system-design.md +0 -89
  98. package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
  99. package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
  100. package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
  101. package/skills/fui-skill-cli/references/tools-registry.md +0 -84
  102. package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
  103. package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
  104. package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
  105. package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
  106. package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
  107. package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
  108. package/skills/fui-skill-cli/references/ui-templates.md +0 -22
  109. package/skills/fui-skill-cli/references/verification.md +0 -236
  110. package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
  111. package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
@@ -1,112 +0,0 @@
1
- # FUI Coding Standards
2
-
3
- > Owns: **general code standards: naming, `<style scoped>` in `.vue` (manual scoping), no backticks in `<template>`, reusable APIs**. Detailed component design rules: [component-design.md](component-design.md).
4
-
5
- ## 1. Naming
6
-
7
- ### Components (`components/`)
8
-
9
- - **Prefix** `uc-` (User Component) for custom components, distinct from standard FUI `f-`, `t-`.
10
- - **Kebab-case** file names (e.g. `uc-trangthai-sukien.vue`, `uc-user-profile.vue`).
11
- - **Props**: camelCase in script, kebab-case in templates (`userProfile` -> `:user-profile`).
12
- - **Reusable APIs**: default to generic props, emits and slots so the component works across modules/screens.
13
- - **No overfitted names**: prefer neutral contracts (`items`, `value`, `label`, `loading`, `readonly`, `disabled`, `options`, `config`) unless the domain truly needs a specific name.
14
- - **Push orchestration up**: API calls, route changes and page coordination stay in `module.json` or the parent; the component handles presentation and local interaction.
15
- - **Emit up**: prefer `$emit(...)` for `input`, `change`, `select`, `submit`, `remove` or explicit action events over mutating parent-owned state.
16
-
17
- ### CSS Classes
18
-
19
- - **`<style scoped>` in `.vue` is allowed** (saved server-side as `ComCSS`) but `scoped` has **no real effect** — FUI just concatenates every component's `ComCSS` in the module into one global stylesheet (`ComponentCSSBuild()`): no AST transform, no `data-v-xxxx`. **Scope every selector manually**: give the root template element a unique class matching the component name (kebab-case, e.g. `uc-invoice-list`) and write every rule under it (`.uc-invoice-list__title`, never bare `.title`). Full example: [component-design.md](component-design.md).
20
- - **Placement**: component CSS → `<style scoped>` in the `.vue` (manually scoped). Module-wide CSS → `style.css` (publish with `fui module publish css`). `header.html` still works for CSS but is no longer the only option.
21
- - **Vuetify utilities first** (`ma-2`, `pa-0`, `d-flex`, `primary--text`).
22
- - **Custom classes**: meaningful prefixed names (`ep-hero`, `ep-field-grid`); avoid generic `.box`, `.red`.
23
- - **State classes**: descriptive (`.is-active`, `.has-error`).
24
-
25
- ### Action Keys (`module.json`)
26
-
27
- - **API actions**: prefix `api` (`apiGetDSSuKien`, `apiUpdateUser`).
28
- - **Event handlers**: prefix `handle` (`handleOpenReport`, `handleSubmit`).
29
- - **Dialog actions**: prefix a verb (`openUploadDialog`, `closeSettings`).
30
-
31
- ## 2. Menu (`set.menu`)
32
-
33
- Define the app menu in `module.json`'s `set` object.
34
-
35
- ```json
36
- "menu": [
37
- {
38
- "name": "Main Group",
39
- "icon": "mdi-home", // Material Design Icons
40
- "url": "/dashboard", // Route
41
- "right": { // Permission check
42
- "SystemRight": [1, 2] // Array of allowed Right IDs
43
- }
44
- },
45
- {
46
- "name": "Management",
47
- "icon": "mdi-cog",
48
- "submenu": [ // Nested menu items
49
- {
50
- "name": "Users",
51
- "url": "/users"
52
- },
53
- {
54
- "name": "Settings",
55
- "url": "/settings"
56
- }
57
- ]
58
- }
59
- ]
60
- ```
61
-
62
- ## 3. Project Structure
63
-
64
- - **Canonical layout**: follow [module-structure.md](module-structure.md) in workspace and chat contexts — real local files with workspace access; in chat, mirror the same structure in the response.
65
- - **Required**: `_info.json` and `module.json` at module root.
66
- - **`components/`**: only `.vue` files; no subfolders unless strictly necessary (FUI scans this root).
67
- - **`components/_components.json`**: keep the registry when using `uc-*` components.
68
- - **`header.html`**: still valid for CSS, but prefer manually scoped `<style scoped>` in `.vue` for component CSS and `style.css` for module-wide CSS.
69
- - **`module.json`**: keep clean; move large static lists to the DB or separate JSON files if supported.
70
-
71
- ## 4. Best Practices
72
-
73
- - **Data binding**: no complex logic in JSON attributes; use computed properties in components or simpler `vueData` structures.
74
- - **Events**: use `CALL(vueData.actionName)` for complex interactions; inline JS like `vueData.count++` only for simple toggles.
75
- - **Responsive**: always set `configForm.xs` and `configForm.md` for form widths.
76
-
77
- ## 5. Component Registration (`_components.json`)
78
-
79
- **Upsert pattern:**
80
-
81
- - **New component** (before publish): only `comName`. Do NOT assign `comID`.
82
- ```json
83
- [{ "comName": "hr-employee-profile" }]
84
- ```
85
- - **After publish & sync**: the server assigns `comID`; sync updates the file:
86
- ```json
87
- [{ "comID": 7813, "comName": "hr-employee-profile" }]
88
- ```
89
-
90
- > **Rule**: never create or modify `comID` manually — it is server-generated.
91
-
92
- ## 6. Vue Component Design
93
-
94
- Full `uc-*.vue` rules in [component-design.md](component-design.md), including:
95
-
96
- - No `components: {}` registration
97
- - `<style scoped>` in `.vue` must be manually scoped (see CSS Classes)
98
- - No backticks in `<template>`
99
- - No `v-dialog` — use the `v-overlay` structure
100
- - Required structure for dialog components
101
-
102
- ## 7. Complex Module Architecture
103
-
104
- When `module.json` controls exceed ~200 lines:
105
-
106
- - **Extract to a Vue component**: move UI into a `.vue`; `module.json` keeps data/API plus one component call in `controls`.
107
- - **Props binding**: pass all data from `module.json` via props, kebab-case in templates (`:nhan-vien="nhanVien"`).
108
- - **Design for reuse first**: before naming props/methods, check whether it can be a generic list, card, dialog body, filter panel, summary block or form section reusable elsewhere.
109
- - **Configurable states**: expose loading, empty, disabled, readonly via props or slots, not a hardcoded workflow.
110
- - **Sticky headers**: for multiple sticky elements (e.g. hero + tabs), wrap them in **one parent div** with `position: sticky`, not each element.
111
- - **Tabs vs accordion**: 5+ sections → horizontal `v-tabs` over `v-expansion-panels` (one section at a time, less overload, swipe on mobile).
112
- - **Swipe gestures**: attach `touchstart`/`touchend` on the **outermost wrapper** (not the content area) so swipe works regardless of content height.
@@ -1,448 +0,0 @@
1
- # FUI Vue Component Design Rules
2
-
3
- > Owns: **`uc-*.vue` rules: module/project scope, no `name:`/`components:{}`, props/emits/slots, no `_injectStyle`, manual `<style scoped>` scoping, verification (`fui component preview`, push project components before module render), `{projectId}/COMPONENTS.md`**. Approved classes/props: [controls-styling-vocabulary.md](controls-styling-vocabulary.md).
4
-
5
- Mandatory for every `uc-*.vue`, dialog components included.
6
-
7
- ---
8
-
9
- ## 1. Two scopes: module vs project
10
-
11
- | | Module-scope | Project-scope (global) |
12
- | -------------- | ---------------------------------------------------- | ----------------------------------------- |
13
- | **File** | `{projectId}/modules/{moduleId}/components/uc-*.vue` | `{projectId}/components/uc-*.vue` |
14
- | **Registry** | `modules/{moduleId}/components/_components.json` | `{projectId}/components/_components.json` |
15
- | **Visible in** | That module only | **All modules in the project** |
16
- | **Auto-load** | In its module | Automatic — **nothing to declare** |
17
- | **Use when** | Used by one module | Reused across modules |
18
-
19
- ### Choosing scope
20
-
21
- ```
22
- Component này sẽ dùng ở nhiều module? → project-scope
23
- Component chỉ dùng trong một module? → module-scope
24
- ```
25
-
26
- ### Commands per scope
27
-
28
- | Operation | Module-scope | Project-scope (global) |
29
- | -------------------------- | --------------------------------------------------- | -------------------------------------------------- |
30
- | **Create** (not on server) | `fui component new <name>` — uses session module | `fui component new <name> -p <pid>` — NO module |
31
- | **Update** (on server) | `fui component update <name>` — uses session module | `fui component update <name> -p <pid>` — NO module |
32
- | **Delete** | `fui component delete <name>` — uses session module | `fui component delete <name> -p <pid>` — NO module |
33
- | **Read source** | `fui component get <name> -p <pid> -m <mid>` | `fui component get <name> -p <pid>` — omit module |
34
- | **Sync list** | `fui component list -p <pid> -m <mid>` | `fui component list -p <pid>` — omit module |
35
- | **Workspace file** | `{moduleDir}/components/uc-foo.vue` | `{projectDir}/components/uc-foo.vue` |
36
-
37
- **Single rule:** module given → module-scope · no module, only project → project-scope. Flags: `fui component --help`.
38
-
39
- **Create ≠ update — no implicit upsert.** Both read the **local** `.vue` (must exist on disk) and derive `ComID` from `_components.json` (never pass it):
40
-
41
- - `fui component new` — INSERT only. Refreshes `_components.json` **from the server first**, then checks the name; duplicate = **hard error** (INSERT on a stale cache creates **two same-name records**, unfixable from fui). Re-syncs after to get the real `ComID`.
42
- - `fui component update` — UPDATE only. No `ComID` = **hard error**, never creates: never created (→ `fui component new`) or stale cache (→ `fui component list`, retry).
43
-
44
- `fui component delete` looks up ComID in local `_components.json`; stale → `fui component list` first.
45
-
46
- **`fui module publish html` excludes project-scope components** — push them separately (`fui component new`/`update`).
47
-
48
- ---
49
-
50
- ## 1a. Existing project components — `{projectId}/COMPONENTS.md`
51
-
52
- Before designing a project-scope component, **check `{projectId}/COMPONENTS.md`** (if present): existing project `uc-*.vue` with purpose and main props. Don't rebuild one that exists.
53
-
54
- ```
55
- {FUI_MCP_WORKDIR}/{projectId}/COMPONENTS.md ← kiểm tra TRƯỚC khi tạo component project-scope mới
56
- ```
57
-
58
- **Accumulation:** after creating/updating a reusable project component, append an entry; no file → create with:
59
-
60
- ```markdown
61
- # {projectId} — Danh sách component project-scope
62
-
63
- ## uc-ten-component
64
-
65
- **Mục đích:** mô tả ngắn gọn component dùng để làm gì
66
- **Props:** `propA` (kiểu, mặc định) · `propB` (kiểu, mặc định)
67
- **Events:** `@eventName` — khi nào phát
68
- **Ghi chú:** điều gì cần biết khi dùng (nếu có)
69
- ```
70
-
71
- > Mirrors `{projectId}/DESIGN.md` ([design-modes.md](design-modes.md) §2-3). **Never auto-remove entries** — remove only after `fui component delete` removed it from the server.
72
-
73
- ---
74
-
75
- ## 2. Naming and file layout
76
-
77
- - Prefix `uc-` (User Component; vs `f-*` FUI runtime, `v-*` Vuetify), kebab-case: `uc-trangthai-sukien.vue`, `uc-user-profile.vue`
78
- - Only in `components/` at module or project root; no subfolders
79
- - Registry `components/_components.json`: only `comName`, never set `comID`
80
-
81
- ---
82
-
83
- ## 3. Registration — NO `components: {}`, NO `name:`
84
-
85
- FUI auto-registers every `uc-*.vue` **globally**. Never declare `components: { ... }` (doesn't work in FUI) or `name:` (FUI derives it from the filename; may conflict):
86
-
87
- ```js
88
- // ❌ SAI — không cần và có thể gây xung đột
89
- export default {
90
- name: 'uc-user-card',
91
- props: { ... }
92
- }
93
-
94
- // ✅ ĐÚNG — bỏ name, FUI tự resolve từ tên file
95
- export default {
96
- props: { ... }
97
- }
98
- ```
99
-
100
- ```js
101
- // ❌ SAI — không dùng trong FUI
102
- export default {
103
- components: { "uc-user-card": UcUserCard },
104
- };
105
-
106
- // ✅ ĐÚNG — dùng trực tiếp tag trong template
107
- // <uc-user-card :data="data" />
108
- ```
109
-
110
- ---
111
-
112
- ## 4. Props
113
-
114
- - `script`: camelCase (`userName`, `itemList`); `template`: kebab-case (`:user-name="userName"`)
115
- - Array/Object defaults use `function()`, not arrow functions:
116
-
117
- ```js
118
- // ❌ SAI
119
- props: { items: { default: () => [] } }
120
-
121
- // ✅ ĐÚNG
122
- props: { items: { default: function() { return [] } } }
123
- ```
124
-
125
- - Prefer neutral reusable names (`items`, `value`, `label`, `loading`, `readonly`, `disabled`, `options`, `config`), not screen-specific ones
126
-
127
- ---
128
-
129
- ## 5. Emits
130
-
131
- - Emit to the parent; never mutate parent state
132
- - Standard: `input`, `change`, `select`, `submit`, `remove`, `action`
133
- - Dialog components always close with `('input', false)` — Vue 2 `v-model` compatible
134
-
135
- ---
136
-
137
- ## 6. Template syntax constraints
138
-
139
- ### No backticks in `<template>`
140
-
141
- Breaks in Vue 2 templates; concatenate:
142
-
143
- ```html
144
- <!-- ❌ SAI -->
145
- :label="`Total (${items.length})`"
146
-
147
- <!-- ✅ ĐÚNG -->
148
- :label="'Total (' + items.length + ')'"
149
- ```
150
-
151
- ### No `@` shorthand in JSON
152
-
153
- `module.json`: always `v-on:click`, never `@click`. `.vue` templates: `@click` is fine.
154
-
155
- ### Vue 2 needs a single root element
156
-
157
- ```html
158
- <!-- ✅ ĐÚNG -->
159
- <template>
160
- <div>
161
- <!-- nội dung -->
162
- </div>
163
- </template>
164
- ```
165
-
166
- ---
167
-
168
- ## 7. Style & class — use existing Vuetify classes, DON'T invent
169
-
170
- **Use Vuetify utility classes for ALL spacing/flex/text/color/size. New class only when truly special** (effect/layout Vuetify lacks) — invented classes break consistency.
171
-
172
- ### ❌ NEVER inject CSS via JavaScript
173
-
174
- No `<style>` created in JS and appended to `document.head` (`_injectStyle`) — severe anti-pattern (dodges the no-`<style>` rule, spawns invented classes):
175
-
176
- ```js
177
- // ❌ SAI NGHIÊM TRỌNG — không bao giờ làm thế này trong .vue
178
- methods: {
179
- _injectStyle: function() {
180
- var s = document.createElement('style')
181
- s.textContent = ['.smg-root{...}', '.smg-card{...}', '.smg-badge{...}', ...].join('')
182
- document.head.appendChild(s) // ❌ bơm CSS + hàng loạt class tự chế
183
- }
184
- }
185
- ```
186
-
187
- `<style scoped>` is allowed for custom CSS (rarely needed), but **does not scope**: FUI concatenates every module component's `ComCSS` into ONE stylesheet (`ComponentCSSBuild()`) — no SFC compile, no `data-v-xxxx`. **Scope manually**:
188
-
189
- 1. Template root gets a class = component name (`uc-invoice-list` → `class="uc-invoice-list"`).
190
- 2. EVERY selector starts from that class — **no bare selectors** (`.title`, `.header`...); they leak into every component in the module.
191
-
192
- ```vue
193
- <template>
194
- <div class="uc-invoice-list">
195
- <div class="uc-invoice-list__toolbar">
196
- <span class="uc-invoice-list__title">{{ title }}</span>
197
- </div>
198
- <f-table class="uc-invoice-list__table" :items="rows"></f-table>
199
- </div>
200
- </template>
201
-
202
- <style scoped>
203
- .uc-invoice-list__toolbar {
204
- display: flex;
205
- align-items: center;
206
- justify-content: space-between;
207
- }
208
- .uc-invoice-list__title {
209
- font-weight: 600;
210
- font-size: 14px;
211
- }
212
- .uc-invoice-list__table {
213
- margin-top: 8px;
214
- }
215
- </style>
216
- ```
217
-
218
- ```vue
219
- <!-- ❌ SAI — selector trần, đụng với component khác cùng module có class .title/.toolbar -->
220
- <style scoped>
221
- .title {
222
- font-weight: 600;
223
- }
224
- .toolbar {
225
- display: flex;
226
- }
227
- </style>
228
- ```
229
-
230
- Module-wide CSS → `style.css` (`fui module publish css`); `header.html` still works but isn't the only option.
231
-
232
- ### Before adding a class → check the approved vocabulary
233
-
234
- Allowed Vuetify classes/props (spacing, flex, text, color, radius, elevation, breakpoint, size), priority, when a custom class is allowed → [controls-styling-vocabulary.md](controls-styling-vocabulary.md) §3. Applies unchanged in `.vue`, **except** no FUI grid `w`/`col` (`module.json` syntax translated by the runtime) — write the Vuetify grid directly.
235
-
236
- **Grid syntax DIFFERS by framework** — FUI V2 = Vuetify 1.5, FUI V3 = Vuetify 3 (canonical: [controls-patterns.md](controls-patterns.md) §Vuetify version):
237
-
238
- | | V2 (Vuetify 1.5) | V3 (Vuetify 3) |
239
- | ------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
240
- | Columns | `v-layout` > `v-flex xs8` | `v-row` > `v-col cols="8"` |
241
- | `v-flex` | ✅ | ❌ **does not exist** — renders as an inert HTML element: no error, no `[Vue warn]`, just **layout gone** |
242
- | `v-layout` | ✅ grid row | ⚠️ **exists with a different meaning**: app layout wrapper (with `v-main`, as `fastproject-3.0.js` uses), NOT a grid row. Using it instead of `v-row` gives a flex container without grid gutter/breakpoints |
243
- | bare prop `shrink` | ✅ (`v-flex` prop) | ❌ no such prop → inert DOM attribute. Use `class="shrink"` |
244
-
245
- §8 is **V3** (`v-row`/`v-col`); V2 projects use `v-layout`/`v-flex`. Silent breakage both ways: `v-flex` in V3 **shows content with wrong layout**, nothing reports it. Fixing an old component → `fui component preview` on **the project's framework** before pushing.
246
-
247
- Component-specific CSS → its own `<style scoped>`, manually scoped — not `header.html` unless shared by several components/the module.
248
-
249
- ---
250
-
251
- ## 8. Standard dialog in `uc-*.vue` — STANDARD TEMPLATE
252
-
253
- EVERY form dialog: `v-dialog` + `v-card` with these **fixed conventions**. Vuetify utility classes only — no invented classes, no `style`.
254
-
255
- ```html
256
- <v-dialog v-model="editDialog" max-width="600">
257
- <v-card>
258
- <!-- Tiêu đề: px-3 pt-2 pb-3, subtitle-1 font-weight-bold, nút X bên phải -->
259
- <v-card-title class="d-flex align-center px-3 pt-2 pb-3 subtitle-1 font-weight-bold">
260
- {{ editItem.RoundID ? 'Chỉnh sửa vòng thi' : 'Thêm vòng thi mới' }}
261
- <v-spacer></v-spacer>
262
- <v-btn icon @click="editDialog = false"><v-icon>mdi-close</v-icon></v-btn>
263
- </v-card-title>
264
-
265
- <!-- Nội dung: px-3 py-1; field dùng outlined dense hide-details, chia cột bằng v-row/v-col -->
266
- <v-card-text class="px-3 py-1">
267
- <v-row>
268
- <v-col cols="8">
269
- <v-text-field v-model="editItem.RoundName" label="Tên vòng thi" hide-details outlined dense></v-text-field>
270
- </v-col>
271
- <v-col cols="4">
272
- <v-text-field
273
- v-model.number="editItem.RoundOrder"
274
- label="Thứ tự"
275
- type="number"
276
- hide-details
277
- outlined
278
- dense
279
- ></v-text-field>
280
- </v-col>
281
- </v-row>
282
- </v-card-text>
283
-
284
- <!-- Hàng cuối: action căn phải, button rộng tự nhiên; action phụ text, action chính primary -->
285
- <v-card-actions class="pa-3">
286
- <v-spacer></v-spacer>
287
- <v-btn text @click="resetForm">Đặt lại</v-btn>
288
- <v-btn color="primary" elevation="0" :loading="saving" @click="saveRound">Lưu</v-btn>
289
- </v-card-actions>
290
- </v-card>
291
- </v-dialog>
292
- ```
293
-
294
- ### Mandatory conventions (don't change arbitrarily)
295
-
296
- | Part | Class/prop | Note |
297
- | ---------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
298
- | `v-dialog` | `max-width="600"` | 600 normal form; 400 small; 800–900 wide form |
299
- | `v-card-title` | `d-flex align-center px-3 pt-2 pb-3 subtitle-1 font-weight-bold` | Compact title + X button (`v-btn icon` → `mdi-close`) on the right via `v-spacer` |
300
- | `v-card-text` | `px-3 py-1` | Consistent content padding |
301
- | Input fields | `outlined dense hide-details` | Compact, equal height; columns via `v-row` + `v-col cols="N"` |
302
- | `v-card-actions` | **Last row**; `pa-3` + `v-spacer` before buttons | All actions right-aligned |
303
- | Button width | No `block`, `width`, grow class or stretched column wrapper | Natural width from label |
304
- | Primary button | At most one with `color="primary" elevation="0"` + `:loading="saving"` | Filled to show priority; `:loading` during API call |
305
- | Secondary button | `text`, no background `color` | Minor actions; understated |
306
-
307
- - Mode-dependent title: `{{ editItem.ID ? 'Chỉnh sửa' : 'Thêm mới' }}`.
308
- - Numbers: `v-model.number` + `type="number"`.
309
- - Close: `@click="dialogVar = false"`; also set `false` in the callback after a successful save.
310
- - Keep default icon size; never add `small`/`:small` to `v-icon` or icon buttons.
311
-
312
- ### Variants
313
-
314
- - **Toolbar header** (color/icon emphasis): replace `v-card-title` with `v-toolbar dense flat` + `v-toolbar-title`.
315
- - **Fullscreen** (large/multi-area form): `<v-dialog v-model="..." fullscreen>` + `v-toolbar` header, content in `v-container class="grid-list-md"`.
316
-
317
- ---
318
-
319
- ## 9. Design for reuse
320
-
321
- - Shape as list, card, dialog body, filter panel, summary block or form section where possible
322
- - Expose loading/empty/disabled/readonly via props/slots, don't hardcode a workflow
323
- - API calls, routing, permissions stay in `module.json` or parent — component = presentation
324
- - module.json `controls` > ~200 lines → extract UI to a Vue component; module.json keeps data/API
325
-
326
- ---
327
-
328
- ## 10. No `f-dialog` inside a component template
329
-
330
- `f-dialog` works only directly in the module's `controls` JSON. In `uc-*.vue` use the §8 v-dialog.
331
-
332
- ---
333
-
334
- ## 11. `<script>` syntax limits
335
-
336
- ### No `async / await / finally`
337
-
338
- Unsupported by the FUI `.vue` parser; use callbacks:
339
-
340
- ```js
341
- // ❌ SAI
342
- async mounted() {
343
- const res = await fetch(url)
344
- }
345
-
346
- // ✅ ĐÚNG
347
- mounted() {
348
- ajaxCALL(url, {}, function(res) { ... })
349
- }
350
- ```
351
-
352
- ### No template literals (backticks) in `<script>`
353
-
354
- Only work in standalone `script.js`:
355
-
356
- ```js
357
- // ❌ SAI — trong .vue <script>
358
- var url = `/api/Student/${this.studentID}`;
359
-
360
- // ✅ ĐÚNG
361
- var url = "/api/Student/" + this.studentID;
362
- ```
363
-
364
- ---
365
-
366
- ## 12. Reuse `defaultfunction.js` — DON'T rewrite
367
-
368
- **Before writing logic (API call, confirm, notify, format, group, copy...) → check [default-function.md](default-function.md).** Write your own only if nothing fits.
369
-
370
- ### API calls — `ajaxCALL` (NOT hand-rolled `fetch`/`axios`/`$.ajax`)
371
-
372
- `fetch` fails cross-domain (CORS/credentials). `ajaxCALL` handles credentials, Bearer token and base domain (`v_Set.apiDomain`) — don't prepend it.
373
-
374
- ```js
375
- // ❌ SAI
376
- fetch(url, { method: 'POST', body: JSON.stringify(data) })
377
- .then(r => r.json()).then(res => { ... })
378
-
379
- // ✅ ĐÚNG — ajaxCALL(URL, DATA, successCb, errorCb, header)
380
- ajaxCALL('spAPI_RoundList', { ContestID: this.contestID }, function(res) {
381
- // res đã parse JSON (json_data tự parse)
382
- }, function(err) {
383
- // tuỳ chọn — mặc định ajaxCALL đã showMessage lỗi
384
- })
385
- ```
386
-
387
- ### Confirm — `confirm` (NOT `window.confirm`)
388
-
389
- ```js
390
- confirm({
391
- title: 'Xác nhận xoá',
392
- message: 'Bạn có chắc muốn xoá vòng thi này?',
393
- action: function() { ajaxCALL('spAPI_RoundDelete', { RoundID: id }, function(){ ... }); }
394
- });
395
- ```
396
-
397
- ### Notify — `showMessage` or `Vue.$toast`
398
-
399
- ```js
400
- showMessage({ title: "Đã lưu thành công" }); // hộp thoại
401
- showMessage({ title: "Lỗi", message: "...", type: "red" });
402
- Vue.$toast.success("Đã lưu", { position: "top" }); // toast góc màn hình
403
- ```
404
-
405
- ### Other common helpers (don't rewrite)
406
-
407
- `groupBy` · `findInArray` · `jsonToExcel` (Excel export) · `printPDF` · `copyToClipboard` · `openWindow` · `pushRouter` · `rightTest` (permission check) · `generateID` · `capacityText` · `buildHeader` (auto f-table headers). Details: [default-function.md](default-function.md).
408
-
409
- > Globals — never add a CDN for them: `_` (Lodash: `_.groupBy`, `_.sumBy`, `_.cloneDeep`...), `moment` (dates), `numeral` (numbers).
410
-
411
- ---
412
-
413
- ## 13. Verify with `fui component preview` BEFORE assembling into the module
414
-
415
- Seen only after assembly, component bugs and assembly bugs mix. `fui component preview` renders **one component** on its own page from the **local** `.vue` (no push needed) with sample data passed directly.
416
-
417
- ```
418
- fui component preview uc-invoice-list -p <pid> --cases '[
419
- { "name": "danh sách rỗng", "props": { "items": [] } },
420
- { "name": "có dữ liệu", "props": { "items": [ {...}, {...} ], "title": "Hoá đơn" } },
421
- { "name": "click chọn dòng", "props": { "items": [...] },
422
- "scenario": [ { "click": "Xem" }, { "assert": "vueData.selected != null" } ] }
423
- ]'
424
- # -p only → project-scope; add -m <mid> → module-scope (same inference as fui component new/update)
425
- # devices default: desktop + mobile
426
- ```
427
-
428
- - **Props**: arrays/objects as **real values** (pushed into `data[]`, bound `:prop`). Strings → static attrs; keys starting `:`/`v-` kept verbatim (use `v-on:`/`v-slot:`, **not** `@`/`#`).
429
- - **`cases × devices` ≤ 8** (each render = real browser session).
430
- - Also accepted: `slot` (`innerHTML` content), `vueData`, mocks, `user` (test permission gates), `viewport` (force low height to expose self-measuring components). Flags: `fui component preview --help`.
431
- - `scenario` uses **the exact `--render` grammar on the real DOM**: `set`/`click`/`call`/`exe`/`assert`; pick rows with `nth` (no `item`/`index`).
432
- - **Module `style.css` NOT loaded** — component must stand on its own `<style>` + project theme.
433
- - Returns: screenshots (max 4 inline, rest as paths) + JS errors + `[Vue warn]` + DOM audit. **Read the images and fix** before pushing.
434
-
435
- ### Project components: MUST push before rendering a module that uses them
436
-
437
- `fui module simulate --render` builds the project layer from the **server** bundle; unpushed local edits **don't appear** (screenshot lies). So `--render` **hard-blocks** (no override) when a local project component differs from the server bundle.
438
-
439
- ```
440
- sửa uc-*.vue cấp project
441
- → fui component preview (kiểm chứng bản local, chưa push)
442
- → fui component new (lần đầu) hoặc fui component update (các lần sau) — push lên server
443
- → fui module simulate --render ← chỉ chạy được sau khi đã push
444
- ```
445
-
446
- Blocked and **server is newer** (edited in web IDE) → `fui project sync`; **don't push over it** (erases their work).
447
-
448
- **Module-level** components are exempt: the module layer renders from local files.
@@ -1,78 +0,0 @@
1
- # FUI Component Quick Reference
2
-
3
- > Owns: **FUI component catalog, components needing JS/CSS imports, add/remove import workflow**. Per-component details: file in the right column.
4
-
5
- Prefer `f-*`; use `v-*` only when no FUI equivalent exists.
6
-
7
- | Component | Use for | Reference |
8
- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
9
- | `f-table` | **Any datatable** — CRUD via dialog form or view-only (readonly = omit `:update-api`); auto-builds headers when `:headers` omitted; totals row via `sum-format` | [component-table.md](component-table.md) |
10
- | `f-dialog` | Modal with form, watch, buttons | [components-dialog.md](components-dialog.md) |
11
- | `f-window` | Dialog opening a URL in an iframe | [components-dialog.md](components-dialog.md) |
12
- | `f-button` | Button with action, hotkey, form validation | [components-input.md](components-input.md) |
13
- | `f-date` | Date input with picker + typed mask | [components-input.md](components-input.md) |
14
- | `f-time` | Time input with picker + typed mask | [components-input.md](components-input.md) |
15
- | `f-time-counter` | Countdown / clock | [components-input.md](components-input.md) |
16
- | `f-search` | API-backed autocomplete | [components-input.md](components-input.md) |
17
- | `f-menu` | Dropdown button menu with icon/action/link | [components-input.md](components-input.md) |
18
- | `f-radiobox` | Radio group from items array | [components-input.md](components-input.md) |
19
- | `f-file-upload` | File upload (Plupload, progress dialog) | [components-input.md](components-input.md) |
20
- | `f-image-update` | Image upload + crop | [components-input.md](components-input.md) |
21
- | `f-excel-reader` | Excel/CSV → JSON (pick sheet, skip first N rows, name columns) | [components-input.md](components-input.md) |
22
- | `f-qrcode` | Render QR code | [components-input.md](components-input.md) |
23
- | `f-qrcode-reader` | Read QR via camera | [components-input.md](components-input.md) |
24
- | `f-editor` | Rich text editor (CKEditor 5) | [components-dialog.md](components-dialog.md) |
25
- | `f-editor-dialog` | Rich text editor in a modal | [components-dialog.md](components-dialog.md) |
26
- | `f-echart` | **Charts** — ECharts V5: bar, line, pie, scatter, gauge, radar, heatmap, sankey, tree, map, graph... | [components-echart.md](components-echart.md) · [echart-templates.md](echart-templates.md) |
27
- | `f-sheet` | **Excel-like in-grid editing** — edit cells in place, paste from Excel, no dialog (AG Grid) — **needs import** | [fsheet.md](fsheet.md) |
28
- | `f-pdfmake` | Render PDF in iframe | [components-display.md](components-display.md) · [pdfmake.md](pdfmake.md) |
29
- | `f-label` | Chip/badge for tags, status | [components-display.md](components-display.md) |
30
- | `f-box` | Display/edit key-value rows | [components-display.md](components-display.md) |
31
- | `f-header` | Large heading (display-1, primary color) | [components-display.md](components-display.md) |
32
- | `f-title` | Small heading (title, primary color) | [components-display.md](components-display.md) |
33
- | `f-slider` | Image carousel | [components-display.md](components-display.md) |
34
- | `fp-profile` | User info/profile block | [components-display.md](components-display.md) |
35
-
36
- ### Table-cell components (`t-*`) — used in f-table `headers`
37
-
38
- `t-html` · `t-label` · `t-num` · `t-time` · `t-boolean` · `t-check` (toggle) · `t-text` · `t-select` · `t-combobox` · `t-menu` (context menu) · `t-link` · `t-button` — details: [ui-table-cell-patterns.md](ui-table-cell-patterns.md).
39
-
40
- > `header-bar` and `f-window` are internal, runtime-built (header menu, `openWindow` window) — never place them directly in `controls`.
41
-
42
- ## Components needing JS/CSS imports
43
-
44
- **When adding or removing one of these, run `fui import list` and add/remove the matching imports.**
45
-
46
- | Component | Required imports |
47
- | ----------------- | -------------------------------------------------------------------------------------------------------- |
48
- | `f-pdfmake` | `/include/pdfmake/pdfmake.min.js` · `/include/pdfmake/print.min.js` · `/include/pdfmake/vfs_fonts.js` |
49
- | `f-file-upload` | `/include/plupload-2.3.7/plupload.full.min.js` |
50
- | `f-image-update` | `/include/vue-advanced-cropper/index.umd.js` · `/include/vue-advanced-cropper/style.css` |
51
- | `f-qrcode` | `/include/qrcode/qrcode.min.js` |
52
- | `f-qrcode-reader` | `/include/qrcode/qrcode-reader.min.js` |
53
- | `f-echart` | `/include/chart/echarts.min.js` · `/include/chart/fechart.js` (**in this order**) — Apache ECharts |
54
- | `f-sheet` | `/include/ag-grid/ag-grid-community.min.js` · `/include/ag-grid/fsheet.js` (**in this order**) — AG Grid |
55
- | `f-editor` | `/include/ckeditor5/build/ckeditor.js` |
56
- | `f-editor-dialog` | `/include/ckeditor5/build/ckeditor.js` |
57
-
58
- > **Bundled, NO import needed:** `v-*` (Vuetify) · `f-table` · `f-dialog` · `f-button` ·
59
- > `f-date` · `f-time` · `f-search` · `f-menu` · `f-radiobox` · `f-box` · `f-label` · `f-header` ·
60
- > `f-title` · `f-slider` · `f-excel-reader` — and any component not in the table above.
61
-
62
- **Workflow when adding a component with imports** (see `fui import --help`):
63
-
64
- 1. `fui import list` (project + module) — check existing imports
65
- 2. Missing → `fui import new` for each file
66
- 3. Removing a component → check whether the import is still used elsewhere; if not → `fui import delete`
67
-
68
- ---
69
-
70
- ## Quick selection rules
71
-
72
- - `f-button` over `v-btn` when you need FUI actions (CALL, hotkey, form validation)
73
- - `f-date` / `f-time` over `v-text-field` + manual date parsing
74
- - `f-search` over `v-autocomplete` for API search
75
- - `f-menu` over `v-menu + v-btn` for dropdown actions
76
- - `f-table` over `v-data-table` for EVERY table — CRUD and view-only (readonly = omit `:update-api`)
77
- - `f-echart` for every chart type (bar, line, pie, gauge, scatter, radar, sankey, tree, map...)
78
- - Dialogs: `f-table` `ctrl-update` for inline CRUD; standalone dialog → hand-build `v-dialog` per the standard anatomy (`fui design read fui` §4 + `ui-dialog-patterns.md`); `f-dialog` only for very small forms