jianghu-ui 1.0.5 → 1.0.7

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 (48) hide show
  1. package/dist/jianghu-ui.css +186 -115
  2. package/dist/jianghu-ui.js +1 -1
  3. package/package.json +1 -1
  4. package/src/components/JhAddressSelect/JhAddressSelect.vue +6 -6
  5. package/src/components/JhDrawer/JhDrawer.stories.js +6 -6
  6. package/src/components/JhDrawerForm/JhDrawerForm.vue +1 -1
  7. package/src/components/JhForm/JhForm.stories.js +114 -95
  8. package/src/components/JhForm/JhForm.vue +148 -21
  9. package/src/components/JhFormFields/JhFormFields.vue +33 -14
  10. package/src/components/JhModal/JhModal.stories.js +6 -6
  11. package/src/components/JhModal/JhModal.vue +1 -1
  12. package/src/components/JhModalForm/JhModalForm.vue +1 -1
  13. package/src/components/JhTable/JhTable.stories.js +192 -154
  14. package/src/components/JhTable/JhTable.vue +122 -26
  15. package/src/style/globalCSSVuetifyV4.css +1 -2
  16. package/src/components/JhAddressSelect/JhAddressSelect.md +0 -267
  17. package/src/components/JhCard/JhCard.md +0 -246
  18. package/src/components/JhCheckCard/JhCheckCard.md +0 -245
  19. package/src/components/JhConfirmDialog/JhConfirmDialog.md +0 -70
  20. package/src/components/JhDateRangePicker/JhDateRangePicker.md +0 -56
  21. package/src/components/JhDescriptions/JhDescriptions.md +0 -724
  22. package/src/components/JhDraggable/JhDraggable.md +0 -66
  23. package/src/components/JhDrawer/JhDrawer.md +0 -68
  24. package/src/components/JhDrawerForm/JhDrawerForm.md +0 -69
  25. package/src/components/JhEditableTable/JhEditableTable.md +0 -507
  26. package/src/components/JhFileInput/JhFileInput.md +0 -56
  27. package/src/components/JhForm/JhForm.md +0 -676
  28. package/src/components/JhFormFields/JhFormFields.md +0 -647
  29. package/src/components/JhFormList/JhFormList.md +0 -303
  30. package/src/components/JhJsonEditor/JhJsonEditor.md +0 -54
  31. package/src/components/JhLayout/JhLayout.md +0 -580
  32. package/src/components/JhList/JhList.md +0 -441
  33. package/src/components/JhMarkdownEditor/JhMarkdownEditor.md +0 -56
  34. package/src/components/JhMask/JhMask.md +0 -62
  35. package/src/components/JhMenu/JhMenu.md +0 -85
  36. package/src/components/JhModal/JhModal.md +0 -68
  37. package/src/components/JhModalForm/JhModalForm.md +0 -69
  38. package/src/components/JhPageContainer/JhPageContainer.md +0 -409
  39. package/src/components/JhQueryFilter/JhQueryFilter.md +0 -77
  40. package/src/components/JhScene/JhScene.md +0 -64
  41. package/src/components/JhStatisticCard/JhStatisticCard.md +0 -363
  42. package/src/components/JhStepsForm/JhStepsForm.md +0 -666
  43. package/src/components/JhTable/JhTable.md +0 -730
  44. package/src/components/JhTableAttachment/JhTableAttachment.md +0 -70
  45. package/src/components/JhToast/JhToast.md +0 -67
  46. package/src/components/JhTreeSelect/JhTreeSelect.md +0 -82
  47. package/src/components/JhWaterMark/JhWaterMark.md +0 -190
  48. package/src/components/README.md +0 -52
@@ -8,7 +8,7 @@
8
8
  >
9
9
  <v-card>
10
10
  <!-- 标题栏 -->
11
- <v-card-title class="d-flex align-center justify-space-between pa-4">
11
+ <v-card-title class="d-flex align-center justify-space-between pa-4 sticky top-0 z-10 bg-white darken-1">
12
12
  <span class="text-h6">{{ title }}</span>
13
13
  <v-btn
14
14
  v-if="closable"
@@ -101,6 +101,14 @@ export default {
101
101
  control: 'boolean',
102
102
  description: '是否显示选择框',
103
103
  },
104
+ rowKey: {
105
+ control: 'text',
106
+ description: '行唯一标识字段,默认为 "id"',
107
+ },
108
+ itemKey: {
109
+ control: 'text',
110
+ description: 'rowKey 的别名,与 v-data-table API 保持一致',
111
+ },
104
112
  size: {
105
113
  control: 'select',
106
114
  options: ['default', 'medium', 'compact'],
@@ -144,97 +152,51 @@ export default {
144
152
  description: {
145
153
  component: `
146
154
 
147
- 增强版数据表格组件,参考 Ant Design Pro ProTable 设计,提供丰富的功能。
148
-
149
- ## 新增功能特性(Pro 版)
150
-
151
- ### 1. 工具栏功能
152
- - **搜索框**:全局快速搜索
153
- - **刷新按钮**:重新加载数据
154
- - **列设置**:显示/隐藏列,实时生效
155
- - **密度切换**:默认/中等/紧凑三种密度
156
- - **全屏切换**:全屏显示表格(可选)
157
-
158
- ### 2. 列增强功能
159
- - **copyable**:显示复制按钮,一键复制单元格内容
160
- - **ellipsis**:超长文本自动省略,鼠标悬停显示完整内容
161
- - **tooltip**:鼠标悬停提示
162
- - **自定义插槽**:完全自定义列渲染
163
-
164
- ### 3. 操作列配置化
165
- \`\`\`javascript
166
- actionColumn: {
167
- title: '操作',
168
- width: 180,
169
- fixed: 'right',
170
- buttons: [
171
- {
172
- text: '编辑',
173
- type: 'link', // link / icon / button
174
- icon: 'mdi-pencil',
175
- color: 'primary',
176
- tooltip: '编辑记录',
177
- onClick: (row) => { console.log('编辑', row) },
178
- visible: (row) => row.status !== '禁用',
179
- confirm: '确认编辑?'
180
- },
181
- {
182
- text: '删除',
183
- type: 'link',
184
- icon: 'mdi-delete',
185
- color: 'error',
186
- onClick: (row) => { console.log('删除', row) },
187
- confirm: '确认删除?'
188
- }
189
- ]
190
- }
191
- \`\`\`
192
-
193
- ### 4. 服务端分页
194
- 通过 \`request\` prop 支持服务端分页:
195
- \`\`\`javascript
196
- async fetchData(params) {
197
- // params: { page, pageSize, search, sorter, filters }
198
- const response = await fetch('/api/users', {
199
- method: 'POST',
200
- body: JSON.stringify(params),
201
- });
202
- return {
203
- data: response.list,
204
- total: response.total,
205
- success: true,
206
- };
207
- }
208
- \`\`\`
155
+ 增强版数据表格组件,深度继承 Vuetify 2v-data-table,并提供 Pro 级功能。
156
+
157
+ ## 核心特性
209
158
 
210
- ### 5. 行选择增强
211
- - 支持单选/多选
212
- - \`selection-change\` 事件返回 \`{ selectedRowKeys, selectedRows }\`
213
- - 提供 \`getSelectedRows()\` 和 \`clearSelection()\` 方法
159
+ ### 1. 深度继承
160
+ - **API 兼容**:支持 v-data-table 的所有 Props(如 \`show-expand\`、\`group-by\`、\`item-class\` 等)。
161
+ - **插槽透传**:支持所有原生插槽(如 \`top\`、\`footer\`、\`expanded-item\` 等)以及自定义列插槽 \`item.<value>\`。
162
+ - **事件透传**:支持所有原生事件(如 \`click:row\`、\`current-items\` 等)。
163
+ - **实例访问**:通过 \`getVDataTable()\` 获取底层 v-data-table 实例。
214
164
 
215
- ### 6. 响应式密度
216
- 三种密度自动适配:
217
- - **default**: 48px 行高
218
- - **medium**: 40px 行高
219
- - **compact**: 32px 行高
165
+ ### 2. 工具栏与高级筛选
166
+ - **集成搜索**:工具栏内置全局搜索。
167
+ - **列设置**:支持运行时列显示/隐藏切换。
168
+ - **密度切换**:支持 default/medium/compact 三种视觉密度。
169
+ - **高级筛选**:可集成 JhQueryFilter 实现复杂的组合查询。
170
+
171
+ ### 3. 列与单元格增强
172
+ - **Schema 渲染**:支持 \`valueType\` (status, progress, money, date, json 等) 自动化渲染。
173
+ - **交互功能**:支持 \`copyable\` (一键复制) 和 \`ellipsis\` (超长省略)。
174
+ - **操作列配置**:支持配置化的按钮列表,内置权限控制和二次确认。
175
+
176
+ ### 4. 数据流控制
177
+ - **服务端分页**:通过 \`request\` 自动处理请求、分页、排序。
178
+ - **状态持久化**:支持列显示状态持久化。
220
179
 
221
180
  ## 方法
222
181
 
182
+ - \`getVDataTable()\`: 获取底层 v-data-table 实例
223
183
  - \`reload()\`: 重新加载数据(服务端分页)
224
184
  - \`reset()\`: 重置到第一页
225
185
  - \`clearSelection()\`: 清空选择
226
186
  - \`getSelectedRows()\`: 获取选中的行
227
187
 
228
- ## 事件
188
+ ## 事件 (除 v-data-table 原生事件外)
229
189
 
230
190
  - \`create-click\`: 点击新增按钮
231
- - \`update-click\`: 点击详情按钮(item)
232
- - \`delete-click\`: 点击删除按钮(item)
233
- - \`row-click\`: 点击行(item, event)
191
+ - \`update-click\`: 点击详情按钮(针对 actionColumn 默认按钮)
192
+ - \`delete-click\`: 点击删除按钮(针对 actionColumn 默认按钮)
234
193
  - \`selection-change\`: 选择改变 ({ selectedRowKeys, selectedRows })
235
- - \`refresh\`: 点击刷新按钮
236
- - \`copy-success\`: 复制成功(text)
237
- - \`request-error\`: 请求失败(error)
194
+ - \`columns-state-change\`: 列状态改变 (snapshot)
195
+ - \`filter-search\`: 高级筛选查询
196
+ - \`filter-reset\`: 高级筛选重置
197
+ - \`sort-change\`: 排序改变
198
+ - \`copy-success\`: 复制成功 (text)
199
+ - \`request-error\`: 请求失败 (error)
238
200
  `,
239
201
  },
240
202
  },
@@ -253,7 +215,7 @@ export const 基础示例 = {
253
215
  showUpdateAction: true,
254
216
  showDeleteAction: true,
255
217
  showSelect: false,
256
- size: 'default',
218
+ size: 'medium',
257
219
  },
258
220
  render: (args) => ({
259
221
  components: { JhTable },
@@ -857,16 +819,20 @@ export const 自定义列渲染 = {
857
819
  <div>
858
820
  <jh-table v-bind="args">
859
821
  <!-- 自定义状态列 -->
860
- <template v-slot:item.status="{ item }">
822
+ <template v-slot:item.status="{ item, index }">
861
823
  <v-chip
862
824
  :color="item.status === '启用' ? 'success' : 'error'"
863
825
  small
864
826
  label
865
827
  >
866
- <v-icon left x-small>
867
- {{ item.status === '启用' ? 'mdi-check-circle' : 'mdi-close-circle' }}
868
- </v-icon>
869
- {{ item.status }}
828
+ <v-badge
829
+ v-if="index === 0"
830
+ dot
831
+ inline
832
+ color="red"
833
+ class="mr-1"
834
+ ></v-badge>
835
+ {{ item.status }} (索引: {{ index }})
870
836
  </v-chip>
871
837
  </template>
872
838
  </jh-table>
@@ -1360,85 +1326,157 @@ export const 完整CRUD示例 = {
1360
1326
  };
1361
1327
 
1362
1328
 
1363
- export const SelectionAlertRender = {
1329
+ // 受控服务端分页 (完全由父组件控制)
1330
+ export const 受控服务端分页 = {
1364
1331
  render: () => ({
1365
1332
  components: { JhTable },
1366
1333
  data() {
1367
1334
  return {
1368
- headers: [
1369
- { text: '????', value: 'name' },
1370
- { text: '????', value: 'containers' },
1371
- { text: '????', value: 'calls' },
1372
- { text: '???', value: 'owner' },
1373
- { text: '????', value: 'createdAt' }
1374
- ],
1375
- items: [
1376
- { id: 1, name: 'AppName-0', containers: 8, calls: 1276, owner: '???', createdAt: '2025-11-23' },
1377
- { id: 2, name: 'AppName-1', containers: 12, calls: 938, owner: '???', createdAt: '2025-11-23' },
1378
- { id: 3, name: 'AppName-2', containers: 1, calls: 820, owner: '???', createdAt: '2025-11-23' },
1379
- { id: 4, name: 'AppName-3', containers: 5, calls: 1291, owner: '???', createdAt: '2025-11-23' },
1380
- { id: 5, name: 'AppName-4', containers: 17, calls: 1796, owner: '???', createdAt: '2025-11-23' }
1381
- ]
1335
+ headers: sampleHeaders,
1336
+ items: [],
1337
+ loading: false,
1338
+ page: 1,
1339
+ itemsPerPage: 10,
1340
+ serverItemsLength: 0,
1382
1341
  };
1383
1342
  },
1384
- methods: {
1385
- renderAlert(h, { selectedRows, onCleanSelected }) {
1386
- const totalContainers = selectedRows.reduce((sum, row) => sum + row.containers, 0);
1387
- const totalCalls = selectedRows.reduce((sum, row) => sum + row.calls, 0);
1388
- return h(
1389
- 'div',
1390
- { class: 'd-flex align-center flex-wrap', style: { gap: '12px' } },
1391
- [
1392
- h('span', { class: 'font-weight-medium' }, `?? ${selectedRows.length} ?`),
1393
- h(
1394
- 'v-btn',
1395
- {
1396
- props: { text: true, xSmall: true, color: 'primary' },
1397
- on: { click: onCleanSelected }
1398
- },
1399
- '????'
1400
- ),
1401
- h('span', { class: 'grey--text text--darken-1' }, `?????${totalContainers} ?`),
1402
- h('span', { class: 'grey--text text--darken-1' }, `????${totalCalls} ?`)
1403
- ]
1404
- );
1343
+ mounted() {
1344
+ this.loadData();
1345
+ },
1346
+ watch: {
1347
+ page() {
1348
+ console.log('Page changed to:', this.page);
1349
+ this.loadData();
1405
1350
  },
1406
- renderAlertActions(h, { selectedRows }) {
1407
- return h('div', { class: 'd-flex align-center', style: { gap: '8px' } }, [
1408
- h(
1409
- 'v-btn',
1410
- {
1411
- props: { small: true, color: 'error' },
1412
- on: { click: () => this.handleBatchDelete(selectedRows) }
1413
- },
1414
- '????'
1415
- ),
1416
- h(
1417
- 'v-btn',
1418
- {
1419
- props: { small: true, outlined: true, color: 'primary' },
1420
- on: { click: () => this.handleExport(selectedRows) }
1421
- },
1422
- '????'
1423
- )
1424
- ]);
1351
+ itemsPerPage() {
1352
+ console.log('Items per page changed to:', this.itemsPerPage);
1353
+ // 通常改变每页大小时建议重置到第一页,但这里取决于业务逻辑
1354
+ // 注意:v-data-table 可能会自动触发 update:page 为 1
1355
+ this.loadData();
1425
1356
  },
1426
- handleBatchDelete(rows) {
1427
- alert(`???? ${rows.length} ?`);
1357
+ },
1358
+ methods: {
1359
+ async loadData() {
1360
+ this.loading = true;
1361
+ console.log(`Loading data: page=${this.page}, size=${this.itemsPerPage}`);
1362
+
1363
+ // 模拟 API 延迟
1364
+ await new Promise(resolve => setTimeout(resolve, 300));
1365
+
1366
+ const total = allMockData.length;
1367
+ const start = (this.page - 1) * this.itemsPerPage;
1368
+ const end = start + this.itemsPerPage;
1369
+
1370
+ this.items = allMockData.slice(start, end);
1371
+ this.serverItemsLength = total;
1372
+ this.loading = false;
1428
1373
  },
1429
- handleExport(rows) {
1430
- alert(`?? ${rows.length} ?`);
1431
- }
1432
1374
  },
1433
1375
  template: `
1434
- <jh-table
1435
- :headers="headers"
1436
- :items="items"
1437
- show-select
1438
- :toolbar="false"
1439
- :table-alert-render="renderAlert"
1440
- :table-alert-option-render="renderAlertActions"
1441
- />
1442
- `
1443
- })
1376
+ <div>
1377
+ <div class="mb-4 pa-4 orange lighten-5 rounded">
1378
+ <strong>受控服务端分页示例 (无 request 函数)</strong>
1379
+ <p class="mb-0 mt-2">完全由父组件控制 page 和 itemsPerPage,模拟传统的 v-data-table 服务端分页用法。</p>
1380
+ <div class="mt-2">
1381
+ Page: {{ page }} | ItemsPerPage: {{ itemsPerPage }} | Total: {{ serverItemsLength }}
1382
+ </div>
1383
+ </div>
1384
+ <jh-table
1385
+ :headers="headers"
1386
+ :items="items"
1387
+ :loading="loading"
1388
+ :page.sync="page"
1389
+ :items-per-page.sync="itemsPerPage"
1390
+ :server-items-length="serverItemsLength"
1391
+ :footer-props="{
1392
+ 'items-per-page-options': [5, 10, 20]
1393
+ }"
1394
+ />
1395
+ </div>
1396
+ `,
1397
+ }),
1398
+ };
1399
+
1400
+ // 原生插槽透传
1401
+ export const 原生插槽透传 = {
1402
+ render: () => ({
1403
+ components: { JhTable },
1404
+ data() {
1405
+ return {
1406
+ headers: sampleHeaders,
1407
+ items: sampleItems.slice(0, 5),
1408
+ };
1409
+ },
1410
+ template: `
1411
+ <jh-table :headers="headers" :items="items" header-title="原生插槽透传示例">
1412
+ <!-- 顶部插槽 -->
1413
+ <template v-slot:top>
1414
+ <v-toolbar flat color="blue lighten-4">
1415
+ <v-toolbar-title>这是 v-data-table 的 top 插槽</v-toolbar-title>
1416
+ <v-divider class="mx-4" inset vertical></v-divider>
1417
+ <v-spacer></v-spacer>
1418
+ <v-btn color="primary" dark class="mb-2">自定义按钮</v-btn>
1419
+ </v-toolbar>
1420
+ </template>
1421
+
1422
+ <!-- 底部插槽 -->
1423
+ <template v-slot:footer>
1424
+ <div class="pa-4 text-center grey lighten-3">
1425
+ 这是 v-data-table 的 footer 插槽,可以放置汇总信息等
1426
+ </div>
1427
+ </template>
1428
+
1429
+ <!-- 自定义表头插槽 (原生方式) -->
1430
+ <template v-slot:header.username="{ header }">
1431
+ <span class="orange--text font-weight-bold italic">{{ header.text }} (自定义)</span>
1432
+ </template>
1433
+ </jh-table>
1434
+ `,
1435
+ }),
1436
+ };
1437
+
1438
+ // 原生实例访问
1439
+ export const 原生实例访问 = {
1440
+ render: () => ({
1441
+ components: { JhTable },
1442
+ data() {
1443
+ return {
1444
+ headers: sampleHeaders,
1445
+ items: sampleItems,
1446
+ };
1447
+ },
1448
+ template: `
1449
+ <div>
1450
+ <div class="mb-4">
1451
+ <v-btn @click="callNativeSelectAll" color="primary">通过 Ref 调用原生全选 (selectAll)</v-btn>
1452
+ <v-btn @click="checkNativeInstance" color="secondary" class="ml-2">检查原生实例</v-btn>
1453
+ </div>
1454
+ <jh-table
1455
+ ref="jhTableRef"
1456
+ :headers="headers"
1457
+ :items="items"
1458
+ show-select
1459
+ header-title="原生实例访问示例"
1460
+ />
1461
+ </div>
1462
+ `,
1463
+ methods: {
1464
+ callNativeSelectAll() {
1465
+ const vDataTable = this.$refs.jhTableRef.getVDataTable();
1466
+ if (vDataTable) {
1467
+ // 注意:Vuetify 2.x 的 selectAll 可能需要特定参数或通过内部 toggle 实现
1468
+ // 这里演示获取实例并操作
1469
+ vDataTable.toggleSelectAll(true);
1470
+ alert('已通过 getVDataTable().toggleSelectAll(true) 触发全选');
1471
+ }
1472
+ },
1473
+ checkNativeInstance() {
1474
+ const vDataTable = this.$refs.jhTableRef.getVDataTable();
1475
+ console.log('原生 v-data-table 实例:', vDataTable);
1476
+ alert('实例已打印到控制台,构造函数名:' + vDataTable.$options.name);
1477
+ }
1478
+ }
1479
+ }),
1444
1480
  };
1481
+
1482
+