@fui-org/fui-cli 1.3.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +19 -3
  2. package/dist/fui-bmg5pnmq.js +379 -0
  3. package/dist/fui.js +1 -1
  4. package/package.json +7 -6
  5. package/skills/fui/SKILL.md +9 -41
  6. package/skills/fui-skill/SKILL.md +95 -225
  7. package/skills/fui-skill/assets/projectdefaultstyle-3.0.css +555 -0
  8. package/skills/fui-skill/assets/projectdefaultstyle.css +207 -235
  9. package/skills/fui-skill/references/INDEX.md +105 -137
  10. package/skills/fui-skill/references/advanced-techniques.md +76 -68
  11. package/skills/fui-skill/references/coding-standards.md +56 -56
  12. package/skills/fui-skill/references/component-design.md +166 -173
  13. package/skills/fui-skill/references/component-quickref.md +61 -60
  14. package/skills/fui-skill/references/component-table.md +128 -117
  15. package/skills/fui-skill/references/components-dialog.md +55 -56
  16. package/skills/fui-skill/references/components-display.md +24 -30
  17. package/skills/fui-skill/references/components-echart.md +186 -261
  18. package/skills/fui-skill/references/components-input.md +72 -96
  19. package/skills/fui-skill/references/controls-patterns.md +196 -342
  20. package/skills/fui-skill/references/controls-styling-vocabulary.md +130 -97
  21. package/skills/fui-skill/references/db-table-design.md +24 -28
  22. package/skills/fui-skill/references/db-workflow.md +191 -390
  23. package/skills/fui-skill/references/default-function.md +169 -128
  24. package/skills/fui-skill/references/design-modes.md +35 -63
  25. package/skills/fui-skill/references/echart-templates.md +204 -196
  26. package/skills/fui-skill/references/fastproject.md +62 -60
  27. package/skills/fui-skill/references/fsheet.md +109 -124
  28. package/skills/fui-skill/references/fullstack-workflow.md +90 -128
  29. package/skills/fui-skill/references/module-data-patterns.md +31 -40
  30. package/skills/fui-skill/references/module-json-anatomy.md +47 -52
  31. package/skills/fui-skill/references/module-structure.md +80 -196
  32. package/skills/fui-skill/references/new-session.md +49 -51
  33. package/skills/fui-skill/references/pdfmake.md +17 -17
  34. package/skills/fui-skill/references/permission-system.md +89 -108
  35. package/skills/fui-skill/references/platform-architecture.md +128 -153
  36. package/skills/fui-skill/references/project-config.md +102 -134
  37. package/skills/fui-skill/references/project-provisioning.md +139 -244
  38. package/skills/fui-skill/references/script-map.md +208 -242
  39. package/skills/fui-skill/references/sql-clr-functions.md +98 -97
  40. package/skills/fui-skill/references/system-design.md +63 -88
  41. package/skills/fui-skill/references/tapi-file-api.md +46 -52
  42. package/skills/fui-skill/references/tapi-permission-patterns.md +51 -53
  43. package/skills/fui-skill/references/tapi-reference.md +132 -207
  44. package/skills/fui-skill/references/tools-registry.md +84 -460
  45. package/skills/fui-skill/references/ui-crosswindow-patterns.md +79 -75
  46. package/skills/fui-skill/references/ui-dialog-patterns.md +98 -72
  47. package/skills/fui-skill/references/ui-layout-patterns.md +26 -26
  48. package/skills/fui-skill/references/ui-patterns.md +71 -83
  49. package/skills/fui-skill/references/ui-screenshot-review.md +63 -62
  50. package/skills/fui-skill/references/ui-table-cell-patterns.md +61 -59
  51. package/skills/fui-skill/references/ui-templates.md +16 -23
  52. package/skills/fui-skill/references/verification.md +236 -246
  53. package/skills/fui-skill/references/watcher-patterns.md +30 -63
  54. package/skills/fui-skill/references/websocket-realtime.md +83 -66
  55. package/skills/fui-skill/scripts/component-3.0.js +298 -131
  56. package/skills/fui-skill/scripts/component.js +277 -271
  57. package/skills/fui-skill/scripts/componentTable-3.0.js +182 -53
  58. package/skills/fui-skill/scripts/componentTable.js +171 -49
  59. package/skills/fui-skill/scripts/defaultfunction-3.0.js +88 -3
  60. package/skills/fui-skill/scripts/defaultfunction.js +88 -3
  61. package/skills/fui-skill/scripts/fsheet.js +38 -0
  62. package/dist/fui-x7kph78r.js +0 -420
  63. package/skills/fui-skill/README.md +0 -112
  64. package/skills/fui-skill/metadata.json +0 -75
  65. package/skills/fui-skill-cli/SKILL.md +0 -139
  66. package/skills/fui-skill-cli/references/INDEX.md +0 -110
  67. package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
  68. package/skills/fui-skill-cli/references/coding-standards.md +0 -112
  69. package/skills/fui-skill-cli/references/component-design.md +0 -448
  70. package/skills/fui-skill-cli/references/component-quickref.md +0 -78
  71. package/skills/fui-skill-cli/references/component-table.md +0 -248
  72. package/skills/fui-skill-cli/references/components-dialog.md +0 -191
  73. package/skills/fui-skill-cli/references/components-display.md +0 -141
  74. package/skills/fui-skill-cli/references/components-echart.md +0 -316
  75. package/skills/fui-skill-cli/references/components-input.md +0 -335
  76. package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
  77. package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
  78. package/skills/fui-skill-cli/references/db-table-design.md +0 -73
  79. package/skills/fui-skill-cli/references/db-workflow.md +0 -288
  80. package/skills/fui-skill-cli/references/default-function.md +0 -425
  81. package/skills/fui-skill-cli/references/design-modes.md +0 -57
  82. package/skills/fui-skill-cli/references/echart-templates.md +0 -489
  83. package/skills/fui-skill-cli/references/fastproject.md +0 -99
  84. package/skills/fui-skill-cli/references/fsheet.md +0 -203
  85. package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
  86. package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
  87. package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
  88. package/skills/fui-skill-cli/references/module-structure.md +0 -141
  89. package/skills/fui-skill-cli/references/new-session.md +0 -85
  90. package/skills/fui-skill-cli/references/pdfmake.md +0 -60
  91. package/skills/fui-skill-cli/references/permission-system.md +0 -150
  92. package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
  93. package/skills/fui-skill-cli/references/project-config.md +0 -303
  94. package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
  95. package/skills/fui-skill-cli/references/script-map.md +0 -262
  96. package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
  97. package/skills/fui-skill-cli/references/system-design.md +0 -89
  98. package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
  99. package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
  100. package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
  101. package/skills/fui-skill-cli/references/tools-registry.md +0 -84
  102. package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
  103. package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
  104. package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
  105. package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
  106. package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
  107. package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
  108. package/skills/fui-skill-cli/references/ui-templates.md +0 -22
  109. package/skills/fui-skill-cli/references/verification.md +0 -236
  110. package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
  111. package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
@@ -1,14 +1,13 @@
1
1
  # FUI Input & Interaction Components
2
2
 
3
- > File này sở hữu: **component nhập liệu: `f-date`, `f-time`, `f-search`, `f-radiobox`, `f-button`, `f-menu`, upload**.
3
+ > Owns: **input components: `f-date`, `f-time`, `f-search`, `f-radiobox`, `f-button`, `f-menu`, upload**.
4
4
 
5
- Components dùng để nhận input hoặc tương tác với người dùng. Xem prefix/binding rules tại [components-display.md](components-display.md).
5
+ Components for input and user interaction. Prefix/binding rules: [components-display.md](components-display.md).
6
6
 
7
7
  ## f-radiobox
8
8
 
9
9
  - Props (source): `label`, `items`, `itemValue`, `itemText`
10
10
  - Emit: `input` on change
11
- - Example:
12
11
 
13
12
  ```json
14
13
  {
@@ -27,13 +26,11 @@ Components dùng để nhận input hoặc tương tác với người dùng. Xe
27
26
  ## f-menu
28
27
 
29
28
  - Props (source): `items`, `label`, `iconText`, `menuAttr`
30
- - Behavior: dropdown button với danh sách menu items
31
- - Nếu `label` rỗng hoặc undefined → hiển thị icon-only button
32
- - `items` format: mảng `{ text, visible, color, "icon-text", action, href, target }`
33
- - `action`: FUI action object — chạy qua `runAction`
34
- - `href` + `target`: điều hướng như thẻ `<a>`
35
- - `visible`: ẩn/hiện item (default `true`)
36
- - Example:
29
+ - Dropdown button with menu items; `label` empty/undefined → icon-only button
30
+ - `items`: array of `{ text, visible, color, "icon-text", action, href, target }`
31
+ - `action`: FUI action object, run via `runAction`
32
+ - `href` + `target`: navigate like `<a>`
33
+ - `visible`: show/hide item (default `true`)
37
34
 
38
35
  ```json
39
36
  {
@@ -55,8 +52,7 @@ Components dùng để nhận input hoặc tương tác với người dùng. Xe
55
52
 
56
53
  - Props (source): `api`, `apiData`, `items`
57
54
  - Emit: `input` when selection changes
58
- - Behavior: debounced API search (500ms), bỏ qua keyword < 2 ký tự
59
- - Example:
55
+ - Debounced API search (500ms); keywords < 2 chars ignored
60
56
 
61
57
  ```json
62
58
  {
@@ -75,11 +71,8 @@ Components dùng để nhận input hoặc tương tác với người dùng. Xe
75
71
  ## f-button
76
72
 
77
73
  - Props (source): `label`, `checkvalid`, `ctrlhotkey`, `iconText`, `action`, `includeData`
78
- - Behavior:
79
- - debounced click (500ms, leading)
80
- - validates form khi `checkvalid=true`
81
- - nếu `$attrs.target == 'dialog'`, mở window theo attrs (`wid`, `title`, `url`, `onclose`)
82
- - Example:
74
+ - Debounced click (500ms, leading); validates form when `checkvalid=true`
75
+ - `$attrs.target == 'dialog'` → opens a window from attrs (`wid`, `title`, `url`, `onclose`)
83
76
 
84
77
  ```json
85
78
  {
@@ -96,12 +89,8 @@ Components dùng để nhận input hoặc tương tác với người dùng. Xe
96
89
  ## f-date
97
90
 
98
91
  - Props (source): `value`, `label`, `dateAdd`, `required`
99
- - Emit: `input` with normalized date (hoặc `null`)
100
- - Behavior:
101
- - hỗ trợ typed mask và picker
102
- - chấp nhận nhiều định dạng input khi khởi tạo
103
- - `dateAdd` tự set ngày tương đối so với hôm nay
104
- - Example:
92
+ - Emit: `input` with normalized date (or `null`)
93
+ - Typed mask + picker; accepts many input formats on init; `dateAdd` sets a date relative to today
105
94
 
106
95
  ```json
107
96
  {
@@ -119,9 +108,8 @@ Components dùng để nhận input hoặc tương tác với người dùng. Xe
119
108
  ## f-time
120
109
 
121
110
  - Props (source): `value`, `label`, `timeAdd`, `required`
122
- - Emit: `input` with `HH:mm` (hoặc `null`)
123
- - Behavior: typed mask + time picker
124
- - Example:
111
+ - Emit: `input` with `HH:mm` (or `null`)
112
+ - Typed mask + time picker
125
113
 
126
114
  ```json
127
115
  {
@@ -139,16 +127,10 @@ Components dùng để nhận input hoặc tương tác với người dùng. Xe
139
127
  ## f-time-counter
140
128
 
141
129
  - Props (source): `value`, `type`, `labelFormat`, `format`
142
- - `value`: số giây (Number) hoặc datetime string (`"yyyy-MM-dd HH:mm:ss"`)
143
- - `type`:
144
- - `0` — đếm ngược, hiển thị ngày/giờ/phút/giây đầy đủ
145
- - `1` — đếm ngược, chỉ hiển thị tổng số giây còn lại
146
- - `2` — đồng hồ thời gian thực (hiển thị giờ hiện tại)
147
- - `format`: `{ label, day, hour, minute, second }` — nhãn đơn vị
148
- - Emit:
149
- - `input` (số giây còn lại) khi đếm từ seconds (value là Number)
150
- - `time-end` khi timer về 0
151
- - Example:
130
+ - `value`: seconds (Number) or datetime string (`"yyyy-MM-dd HH:mm:ss"`)
131
+ - `type`: `0` countdown with full days/hours/minutes/seconds · `1` countdown showing total remaining seconds only · `2` real-time clock (current time)
132
+ - `format`: `{ label, day, hour, minute, second }` — unit labels
133
+ - Emit: `input` (remaining seconds) when counting from seconds (Number value); `time-end` when timer hits 0
152
134
 
153
135
  ```json
154
136
  {
@@ -165,8 +147,7 @@ Components dùng để nhận input hoặc tương tác với người dùng. Xe
165
147
  ## f-qrcode
166
148
 
167
149
  - Props (source): `value`, `logo`, `color`, `size`
168
- - Behavior: render QR image từ value
169
- - Example:
150
+ - Renders a QR image from value
170
151
 
171
152
  ```json
172
153
  {
@@ -183,8 +164,7 @@ Components dùng để nhận input hoặc tương tác với người dùng. Xe
183
164
  ## f-qrcode-reader
184
165
 
185
166
  - Props (source): `value`, `label`, `width`
186
- - Emit: `input` (đóng dialog), `update` (decoded content)
187
- - Example:
167
+ - Emit: `input` (closes dialog), `update` (decoded content)
188
168
 
189
169
  ```json
190
170
  {
@@ -201,8 +181,7 @@ Components dùng để nhận input hoặc tương tác với người dùng. Xe
201
181
  ## f-image-update
202
182
 
203
183
  - Props (source): `value`, `label`, `title`, `apiUpload`, `iconText`, `imageType`, `size`, `quality`, `dialogWidth`, `dialogHeight`, `imageBoxAttr`, `imageAttr`, `buttonAttr`, `croperAttr`
204
- - Emit: `update` sau khi upload thành công (`{ returnData, imageData }`)
205
- - Example:
184
+ - Emit: `update` after successful upload (`{ returnData, imageData }`)
206
185
 
207
186
  ```json
208
187
  {
@@ -222,11 +201,7 @@ Components dùng để nhận input hoặc tương tác với người dùng. Xe
222
201
 
223
202
  - Props (source): `label`, `url`, `autoclose`, `iconText`, `filters`, `resize`, `onclose`
224
203
  - Emit: `input` on upload complete
225
- - Behavior:
226
- - dùng Plupload
227
- - tự upload khi chọn file
228
- - chạy `onclose` action khi dialog đóng
229
- - Example:
204
+ - Uses Plupload; uploads on file select; runs `onclose` action when the dialog closes
230
205
 
231
206
  ```json
232
207
  {
@@ -246,71 +221,72 @@ Components dùng để nhận input hoặc tương tác với người dùng. Xe
246
221
 
247
222
  ## f-excel-reader
248
223
 
249
- Nút upload đọc file Excel/CSV → đẩy dữ liệu đã parse vào `v-model` (mảng object, hoặc mảng lồng mảng tuỳ `:header`). Thư viện XLSX lazy-load khi người dùng chọn file lần đầu, **không cần khai import** trong module.json.
224
+ Button: reads Excel/CSV → `v-model` (array of objects, or of arrays per `:header`). XLSX lazy-loads on first pick; **no import** in module.json.
250
225
 
251
- **Đầu ra:**
252
- - `v-model` — mảng dữ liệu đã parse
253
- - `load` — object metadata: `{ rows, rowCount, headers, sheetName, sheetNames, fileName }`
254
- - `error` — `{ message, fileName }` khi file quá lớn, đọc thất bại, hoặc XLSX load timeout
255
- - `action-error` — `{ message, fileName }` khi action callback ném lỗi (dữ liệu Excel vẫn hợp lệ)
226
+ **Outputs:**
256
227
 
257
- **Props — Hiển thị:**
228
+ - `v-model` — parsed data array
229
+ - `load` — metadata `{ rows, rowCount, headers, sheetName, sheetNames, fileName }`
230
+ - `error` — `{ message, fileName }` when file too large, read fails, or XLSX load times out
231
+ - `action-error` — `{ message, fileName }` when the action callback throws (Excel data still valid)
258
232
 
259
- | Prop | Default | Mô tả |
260
- |---|---|---|
261
- | `label` | `'Load Excel'` | Nhãn nút |
262
- | `icon-text` | `'mdi-grid'` | Icon Vuetify MDI; `null`/`''` để ẩn icon |
263
- | `accept` | `.xlsx,.xlsb,.xlsm,.xls,.csv,.txt,.ods,.dbf,.prn,.html,.htm` | Loại file chấp nhận |
233
+ **Props — display:**
264
234
 
265
- **Props — Đọc dữ liệu:**
235
+ | Prop | Default | Description |
236
+ | ----------- | ------------------------------------------------------------ | ------------------------------ |
237
+ | `label` | `'Load Excel'` | Button label |
238
+ | `icon-text` | `'mdi-grid'` | MDI icon; `null`/`''` hides it |
239
+ | `accept` | `.xlsx,.xlsb,.xlsm,.xls,.csv,.txt,.ods,.dbf,.prn,.html,.htm` | Accepted file types |
266
240
 
267
- | Prop | Default | Mô tả |
268
- |---|---|---|
269
- | `:header` | `null` | Quyết định key của mỗi object trong mảng kết quả (xem bảng bên dưới) |
270
- | `:raw` | `false` | `false` = parse số và ngày; `true` = giữ nguyên raw string |
271
- | `date-format` | `'dd/mm/yyyy'` | Format ngày khi `:raw="false"` |
272
- | `:defval` | `''` | Giá trị thay thế cho ô trống |
273
- | `:sheet` | `0` | Sheet cần đọc — số (index 0-based) hoặc tên sheet (string) |
274
- | `:skip-rows` | `0` | Bỏ qua N dòng đầu trước khi đọc header/data |
241
+ **Props — reading:**
275
242
 
276
- **Giá trị của `:header`:**
243
+ | Prop | Default | Description |
244
+ | ------------- | -------------- | ------------------------------------------------------------- |
245
+ | `:header` | `null` | Decides the object keys in the result (table below) |
246
+ | `:raw` | `false` | `false` = parse numbers and dates; `true` = keep raw strings |
247
+ | `date-format` | `'dd/mm/yyyy'` | Date format when `:raw="false"` |
248
+ | `:defval` | `''` | Value for empty cells |
249
+ | `:sheet` | `0` | Sheet to read — number (0-based index) or sheet name (string) |
250
+ | `:skip-rows` | `0` | Skip N leading rows before header/data |
277
251
 
278
- | Giá trị | Kết quả |
279
- |---|---|
280
- | `null` _(mặc định)_ | Dùng dòng đầu tiên của sheet làm tên key: `[{MSSV:"1234", HoTen:"An"}]` |
281
- | `1` | Trả mảng lồng mảng, không có key: `[["MSSV","HoTen"],["1234","An"]]` |
282
- | `"A"` | Dùng chữ cái cột Excel làm key: `[{A:"MSSV", B:"HoTen"}]` |
283
- | `["ma","ten"]` | Tự đặt tên key theo thứ tự cột (không dùng dòng header trong file) |
252
+ **`:header` values:**
284
253
 
285
- ⚠️ **Bẫy `:sheet` — sai tên thì KHÔNG báo lỗi.** Hai kiểu giá trị hỏng khác hẳn nhau:
254
+ | Value | Result |
255
+ | ------------------ | ------------------------------------------------------------- |
256
+ | `null` _(default)_ | First sheet row as keys: `[{MSSV:"1234", HoTen:"An"}]` |
257
+ | `1` | Array of arrays, no keys: `[["MSSV","HoTen"],["1234","An"]]` |
258
+ | `"A"` | Excel column letters as keys: `[{A:"MSSV", B:"HoTen"}]` |
259
+ | `["ma","ten"]` | Your own key names by column order (file header row not used) |
286
260
 
287
- - `:sheet` là **tên** không tồn tại → **im lặng đọc sheet đầu tiên**. Vẫn ra dữ liệu, chỉ là dữ liệu của sheet khác — gõ sai tên sheet không có dấu hiệu nào.
288
- - `:sheet` là **số** vượt quá số sheet → ném lỗi `Không tìm thấy sheet: N` qua event `error`.
261
+ ⚠️ **`:sheet` trap — wrong name does NOT error:**
289
262
 
290
- Dùng tên sheet thì đối chiếu `sheetName` trong event `load` với tên mình mong đợi.
263
+ - Nonexistent **name** → **silently reads the first sheet** (wrong data, no sign).
264
+ - **Number** beyond sheet count → `Không tìm thấy sheet: N` via `error`.
291
265
 
292
- **Props — Giới hạn & timeout:**
266
+ With a name, compare `load`.`sheetName` to the expected name.
293
267
 
294
- | Prop | Default | Mô tả |
295
- |---|---|---|
296
- | `:max-size` | `20` | Giới hạn kích thước file, **đơn vị MB** (tên prop không mang chữ "MB"); `0` = bỏ giới hạn |
297
- | `:load-timeout` | `15000` | Timeout nạp thư viện XLSX (ms) |
268
+ **Props — limits & timeout:**
298
269
 
299
- Giá trị `:max-size` không parse được thành số thì **quay về 20 MB**, không phải bỏ giới hạn — muốn bỏ giới hạn phải truyền đúng số `0`.
270
+ | Prop | Default | Description |
271
+ | --------------- | ------- | ------------------------------------------------------------- |
272
+ | `:max-size` | `20` | File size limit, **in MB** (name has no "MB"); `0` = no limit |
273
+ | `:load-timeout` | `15000` | XLSX library load timeout (ms) |
300
274
 
301
- **Prop — Callback:**
275
+ Unparseable `:max-size` → **20 MB**, not unlimited; no limit = exactly number `0`.
302
276
 
303
- | Prop | Mô tả |
304
- |---|---|
305
- | `:action` | Action object chạy sau khi parse xong và `v-model` đã nhận dữ liệu — thường dùng `{ "CALL": "tenAction" }` |
277
+ **Prop — callback:**
306
278
 
307
- **Ranh giới lỗi — đọc Excel và chạy action là hai giai đoạn tách hẳn:**
279
+ | Prop | Description |
280
+ | --------- | ------------------------------------------------------------------------------------------------ |
281
+ | `:action` | Action object run after parsing, once `v-model` has the data — usually `{ "CALL": "tenAction" }` |
308
282
 
309
- - `action` chỉ chạy sau khi `v-model` đã nhận dữ liệu mới (qua `$nextTick`), nên trong action cứ đọc thẳng `vueData.excelRows`.
310
- - Một khi Excel đã đọc xong, **không lỗi nào còn biến thành event `error` được nữa** — lỗi của action đi ra `action-error`, và dữ liệu đã parse vẫn nguyên vẹn, không rollback. Nghĩa là nhận được `error` ⇒ chắc chắn hỏng ở khâu đọc file; nhận được `action-error` ⇒ file đọc tốt, hỏng ở xử lý phía sau.
311
- - Bấm nút lần nữa khi đang parse thì bị bỏ qua; nếu chọn file mới trước khi file cũ parse xong thì kết quả của lượt cũ bị vứt, không ghi đè lượt mới.
283
+ **Error boundary — reading and action are separate stages:**
312
284
 
313
- **Ví dụ cơ bản — header từ dòng đầu (mặc định):**
285
+ - `action` runs after `v-model` has the data (`$nextTick`); read `vueData.excelRows` directly.
286
+ - After reading, **nothing becomes `error`** — action errors → `action-error`, parsed data kept, no rollback. `error` ⇒ reading failed; `action-error` ⇒ processing failed.
287
+ - Clicks while parsing are ignored; a new file picked before the old finishes discards the old result (never overwrites the new).
288
+
289
+ **Basic — header from first row (default):**
314
290
 
315
291
  ```json
316
292
  {
@@ -325,7 +301,7 @@ Giá trị `:max-size` không parse được thành số thì **quay về 20 MB*
325
301
  }
326
302
  ```
327
303
 
328
- **Ví dụ — đọc sheet theo tên, bỏ 2 dòng đầu, giữ raw string:**
304
+ **Sheet by name, skip 2 rows, keep raw strings:**
329
305
 
330
306
  ```json
331
307
  {
@@ -342,7 +318,7 @@ Giá trị `:max-size` không parse được thành số thì **quay về 20 MB*
342
318
  }
343
319
  ```
344
320
 
345
- **Ví dụ — tự đặt tên cột, giới hạn 5 MB:**
321
+ **Custom column names, 5 MB limit:**
346
322
 
347
323
  ```json
348
324
  {