vue3-components-plus 3.0.10 → 3.0.12

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 (65) hide show
  1. package/README.md +15 -2
  2. package/dist/ComponentDemo/ImageDemo.vue +2 -2
  3. package/dist/ComponentDemo/NsTableDemo/index.vue +516 -0
  4. package/dist/ComponentDemo/NsTableDemo/mockData.js +639 -0
  5. package/dist/cdn/ezuikit/ezuikit.js +27 -0
  6. package/dist/cdn/ezuikit/ezuikit_static/PlayCtrlWasm/playCtrl1/HasSIMD/Decoder.js +168 -0
  7. package/dist/cdn/ezuikit/ezuikit_static/PlayCtrlWasm/playCtrl1/NoSIMD/Decoder.js +168 -0
  8. package/dist/cdn/ezuikit/ezuikit_static/PlayCtrlWasm/playCtrl3/hasWorker/HasSIMD/Decoder.js +21 -0
  9. package/dist/cdn/ezuikit/ezuikit_static/PlayCtrlWasm/playCtrl3/hasWorker/HasSIMD/Decoder.wasm +0 -0
  10. package/dist/cdn/ezuikit/ezuikit_static/PlayCtrlWasm/playCtrl3/hasWorker/HasSIMD/Decoder.worker.js +1 -0
  11. package/dist/cdn/ezuikit/ezuikit_static/PlayCtrlWasm/playCtrl3/hasWorker/NoSIMD/Decoder.js +21 -0
  12. package/dist/cdn/ezuikit/ezuikit_static/PlayCtrlWasm/playCtrl3/hasWorker/NoSIMD/Decoder.wasm +0 -0
  13. package/dist/cdn/ezuikit/ezuikit_static/PlayCtrlWasm/playCtrl3/hasWorker/NoSIMD/Decoder.worker.js +1 -0
  14. package/dist/cdn/ezuikit/ezuikit_static/PlayCtrlWasm/playCtrl3/noWorker/Decoder.js +21 -0
  15. package/dist/cdn/ezuikit/ezuikit_static/PlayCtrlWasm/playCtrl3/noWorker/Decoder.wasm +0 -0
  16. package/dist/cdn/ezuikit/ezuikit_static/css/component.css +1257 -0
  17. package/dist/cdn/ezuikit/ezuikit_static/css/inspectTheme.css +354 -0
  18. package/dist/cdn/ezuikit/ezuikit_static/css/theme copy.css +126 -0
  19. package/dist/cdn/ezuikit/ezuikit_static/css/theme.css +140 -0
  20. package/dist/cdn/ezuikit/ezuikit_static/imgs/bg.png +0 -0
  21. package/dist/cdn/ezuikit/ezuikit_static/imgs/bg.svg +33 -0
  22. package/dist/cdn/ezuikit/ezuikit_static/imgs/empty.png +0 -0
  23. package/dist/cdn/ezuikit/ezuikit_static/imgs/end.png +0 -0
  24. package/dist/cdn/ezuikit/ezuikit_static/imgs/fallback.svg +52 -0
  25. package/dist/cdn/ezuikit/ezuikit_static/imgs/start.png +0 -0
  26. package/dist/cdn/ezuikit/ezuikit_static/rec/datepicker.js +1522 -0
  27. package/dist/cdn/ezuikit/ezuikit_static/rec/datepicker.min.css +36 -0
  28. package/dist/cdn/ezuikit/ezuikit_static/rec/datepicker.zh-CN.js +19 -0
  29. package/dist/cdn/ezuikit/ezuikit_static/rec/jquery.min.js +2 -0
  30. package/dist/cdn/ezuikit/ezuikit_static/speed/speed.css +145 -0
  31. package/dist/cdn/ezuikit/ezuikit_static/talk/adapeter.js +5497 -0
  32. package/dist/cdn/ezuikit/ezuikit_static/talk/janus.js +3507 -0
  33. package/dist/cdn/ezuikit/ezuikit_static/talk/tts-v4.js +343 -0
  34. package/dist/cdn/ezuikit.js +27 -0
  35. package/dist/cdn/h5player/h5player.min.js +313 -0
  36. package/dist/cdn/h5player/playctrl1/DecodeWorker.js +642 -0
  37. package/dist/cdn/h5player/playctrl1/Decoder.js +1 -0
  38. package/dist/cdn/h5player/playctrl1simd/DecodeWorker.js +642 -0
  39. package/dist/cdn/h5player/playctrl1simd/Decoder.js +1 -0
  40. package/dist/cdn/h5player/playctrl2/Decoder.js +21 -0
  41. package/dist/cdn/h5player/playctrl2/Decoder.wasm +0 -0
  42. package/dist/cdn/h5player/playctrl2/Decoder.worker.js +1 -0
  43. package/dist/cdn/h5player/playctrl3/Decoder.js +21 -0
  44. package/dist/cdn/h5player/playctrl3/Decoder.wasm +0 -0
  45. package/dist/cdn/h5player/playctrl3/Decoder.worker.js +1 -0
  46. package/dist/cdn/h5player/talk/AudioInterCom.js +21 -0
  47. package/dist/cdn/h5player/talk/AudioInterCom.wasm +0 -0
  48. package/dist/cdn/h5player/talkW/AudioInterCom.js +21 -0
  49. package/dist/cdn/h5player/talkW/AudioInterCom.wasm +0 -0
  50. package/dist/cdn/h5player/talkW/AudioInterCom.worker.js +1 -0
  51. package/dist/cdn/h5player/transform/libSystemTransform.js +6525 -0
  52. package/dist/cdn/h5player/transform/libSystemTransform.wasm +0 -0
  53. package/dist/cdn/h5player/transform/systemTransform-worker.js +120 -0
  54. package/dist/cdn/md5.js +254 -0
  55. package/dist/js/EasyPlayer-decode.js +1 -0
  56. package/dist/js/EasyPlayer-lib.js +1 -0
  57. package/dist/js/EasyPlayer-pro.js +1 -0
  58. package/dist/js/EasyPlayer-pro.wasm +0 -0
  59. package/dist/js/EasyPlayer-snap.wasm +0 -0
  60. package/dist/vue3-components-plus.css +1 -1
  61. package/dist/vue3-components-plus.js +8362 -6927
  62. package/dist/vue3-components-plus.umd.cjs +1 -1
  63. package/package.json +1 -2
  64. package/dist/cdn.zip +0 -0
  65. package/dist/js.zip +0 -0
package/README.md CHANGED
@@ -1013,10 +1013,23 @@ autoScaleInit(document.querySelector('body'), {
1013
1013
 
1014
1014
  ## 更新日志
1015
1015
 
1016
+ ```text
1017
+ version: 3.0.12
1018
+ 日期: 2026-03-13
1019
+ 更新内容:
1020
+ 1. 添加NsTableContainer带搜索条件的表格
1021
+ ```
1022
+
1023
+ ```text
1024
+ version: 3.0.11
1025
+ 日期: 2026-03-09
1026
+ 更新内容:
1027
+ 1. 修复bug
1028
+ ```
1029
+
1016
1030
  ```text
1017
1031
  version: 3.0.10
1018
1032
  日期: 2026-01-23
1019
1033
  更新内容:
1020
1034
  1. 修改NsSaturationLine文字字体
1021
- ```
1022
-
1035
+ ```
@@ -10,8 +10,8 @@
10
10
 
11
11
  <script setup lang="ts">
12
12
  import { reactive, ref } from 'vue';
13
- import src from '@/assets/b.jpg'
14
- import errorSrc from '@/assets/a.png'
13
+ import src from '@/assets/a.jpg'
14
+ import errorSrc from '@/assets/b.jpg'
15
15
  const hasPreview = ref(true)
16
16
  const apiUrl = reactive( {
17
17
  type: Object,
@@ -0,0 +1,516 @@
1
+ <template>
2
+ <div class="demo-page">
3
+ <!-- 使用 NsTableContainer 组件 -->
4
+ <NsTableContainer
5
+ ref="containerRef"
6
+ :search-items="searchItems"
7
+ :external-search-params="externalSearchParams"
8
+ :search-props="{
9
+ labelWidth: '100px',
10
+ }"
11
+ :table-data="tableData"
12
+ :columns="columns"
13
+ :total="total"
14
+ :table-props="{
15
+ showSelection: true,
16
+ showIndex: true,
17
+ loading: loading,
18
+ rowKey: 'id',
19
+ showPagination: true,
20
+ }"
21
+ :load-data="loadData"
22
+ @search="handleSearch"
23
+ @reset="handleReset"
24
+ @add="handleAdd"
25
+ @selection-change="handleSelectionChange"
26
+ >
27
+ <!-- 自定义状态列 -->
28
+ <template #status="{ row }">
29
+ <el-tag :type="getStatusType(row.status)">
30
+ {{ getStatusText(row.status) }}
31
+ </el-tag>
32
+ </template>
33
+
34
+ <!-- 自定义性别列 -->
35
+ <template #gender="{ row }">
36
+ <el-tag :type="row.gender === 1 ? 'primary' : 'danger'" size="small">
37
+ {{ row.gender === 1 ? '男' : '女' }}
38
+ </el-tag>
39
+ </template>
40
+
41
+ <!-- 自定义部门列 -->
42
+ <template #department="{ row }">
43
+ <el-tag effect="plain">{{ getDepartmentText(row.department) }}</el-tag>
44
+ </template>
45
+ </NsTableContainer>
46
+ <!-- 选择操作区域 -->
47
+ <div class="selection-actions">
48
+ <el-button @click="getSelectedRows">获取选中行</el-button>
49
+ <el-button @click="getSelectedKeys">获取选中ID</el-button>
50
+ <el-button @click="selectRows([1, 3, 5])">选中ID为1,3,5的行</el-button>
51
+ <el-button @click="clearSelection">清空选择</el-button>
52
+ <el-button @click="selectAll">全选</el-button>
53
+ <el-button @click="checkSelection">检查选择状态</el-button>
54
+ </div>
55
+ </div>
56
+ </template>
57
+
58
+ <script setup lang="ts">
59
+ import { Delete, Edit, View } from '@element-plus/icons-vue'
60
+ import { ElDatePicker, ElInput, ElMessage, ElMessageBox, ElSelect, ElSwitch } from 'element-plus'
61
+ import { onMounted, ref } from 'vue'
62
+ import { fetchDepartmentOptions, fetchStatusOptions, filterUsers, mockUsers } from './mockData.js'
63
+
64
+ // ==================== 组件引用 ====================
65
+ const containerRef = ref(null)
66
+
67
+ // ==================== 搜索配置 ====================
68
+ // 当前搜索参数(从 PageSearch 获取)
69
+ const searchParams = ref({})
70
+
71
+ // 外部注入的搜索参数(用于特殊情况传参)
72
+ const externalSearchParams = ref({ test: 'aaa' })
73
+
74
+ // ==================== 数据状态 ====================
75
+ const loading = ref(false)
76
+ const tableData = ref([])
77
+ const total = ref(0)
78
+
79
+ const searchItems = ref([
80
+ {
81
+ prop: 'username',
82
+ label: '用户名',
83
+ span: 6,
84
+ component: ElInput,
85
+ attrs: {
86
+ placeholder: '请输入用户名',
87
+ clearable: true,
88
+ maxlength: 20,
89
+ },
90
+ events: {
91
+ keyup: (e) => {
92
+ if (e.key === 'Enter') {
93
+ handleSearch()
94
+ }
95
+ },
96
+ },
97
+ },
98
+ {
99
+ prop: 'realName',
100
+ label: '真实姓名',
101
+ span: 6,
102
+ component: ElInput,
103
+ attrs: {
104
+ placeholder: '请输入真实姓名',
105
+ clearable: true,
106
+ },
107
+ },
108
+ {
109
+ prop: 'status',
110
+ label: '状态',
111
+ span: 6,
112
+ component: ElSelect,
113
+ attrs: {
114
+ placeholder: '请选择状态',
115
+ clearable: true,
116
+ },
117
+ children: [],
118
+ events: {
119
+ change: (_) => {
120
+ ElMessage.success('下拉选择变化')
121
+ },
122
+ },
123
+ },
124
+ {
125
+ prop: 'department',
126
+ label: '部门',
127
+ span: 6,
128
+ component: ElSelect,
129
+ attrs: {
130
+ placeholder: '请选择部门',
131
+ clearable: true,
132
+ filterable: true,
133
+ },
134
+ children: [],
135
+ },
136
+ {
137
+ prop: 'gender',
138
+ label: '性别',
139
+ span: 6,
140
+ component: ElSelect,
141
+ attrs: {
142
+ placeholder: '请选择性别',
143
+ clearable: true,
144
+ },
145
+ children: [
146
+ { label: '全部', value: '' },
147
+ { label: '男', value: 1 },
148
+ { label: '女', value: 2 },
149
+ ],
150
+ },
151
+ {
152
+ prop: 'createTime',
153
+ label: '创建时间',
154
+ span: 6,
155
+ component: ElDatePicker,
156
+ attrs: {
157
+ type: 'daterange',
158
+ rangeSeparator: '至',
159
+ startPlaceholder: '开始日期',
160
+ endPlaceholder: '结束日期',
161
+ clearable: true,
162
+ format: 'YYYY-MM-DD',
163
+ valueFormat: 'YYYY-MM-DD',
164
+ },
165
+ },
166
+ {
167
+ prop: 'phone',
168
+ label: '手机号',
169
+ span: 6,
170
+ component: ElInput,
171
+ attrs: {
172
+ placeholder: '请输入手机号',
173
+ clearable: true,
174
+ maxlength: 11,
175
+ },
176
+ },
177
+ {
178
+ prop: 'active',
179
+ label: '是否激活',
180
+ span: 6,
181
+ component: ElSwitch,
182
+ attrs: {
183
+ activeText: '是',
184
+ inactiveText: '否',
185
+ },
186
+ defaultValue: true,
187
+ },
188
+ ])
189
+
190
+ // ==================== 表格配置 ====================
191
+ const columns = ref([
192
+ {
193
+ prop: 'id',
194
+ label: 'ID',
195
+ width: 80,
196
+ sortable: true,
197
+ // el-table-column 属性透传示例
198
+ 'class-name': 'id-column', // 自定义列样式类名
199
+ resizable: false, // 禁止拖拽调整宽度
200
+ },
201
+ { prop: 'avatar', label: '头像', slot: 'avatar', width: 80 },
202
+ {
203
+ prop: 'username',
204
+ label: '用户名',
205
+ width: 120,
206
+ // 透传属性
207
+ 'show-overflow-tooltip': true, // 内容过长时显示 tooltip
208
+ formatter: (row, column, cellValue) => {
209
+ return cellValue ? `@${cellValue}` : '-'
210
+ },
211
+ },
212
+ {
213
+ prop: 'realName',
214
+ label: '真实姓名',
215
+ width: 120,
216
+ 'min-width': 100, // 最小宽度
217
+ },
218
+ { prop: 'gender', label: '性别', slot: 'gender', width: 80 },
219
+ { prop: 'department', label: '部门', slot: 'department', width: 120 },
220
+ { prop: 'status', label: '状态', slot: 'status', width: 100 },
221
+ {
222
+ prop: 'phone',
223
+ label: '手机号',
224
+ width: 130,
225
+ 'show-overflow-tooltip': true,
226
+ },
227
+ {
228
+ prop: 'email',
229
+ label: '邮箱',
230
+ minWidth: 180,
231
+ 'show-overflow-tooltip': true,
232
+ filters: [
233
+ // 筛选配置
234
+ { text: 'Gmail', value: '@gmail.com' },
235
+ { text: 'QQ邮箱', value: '@qq.com' },
236
+ ],
237
+ 'filter-method': (value, row) => {
238
+ return row.email.includes(value)
239
+ },
240
+ },
241
+ {
242
+ prop: 'createTime',
243
+ label: '创建时间',
244
+ width: 180,
245
+ sortable: true,
246
+ 'sort-orders': ['descending', 'ascending'], // 排序顺序
247
+ },
248
+ // 操作列
249
+ {
250
+ type: 'action',
251
+ label: '操作',
252
+ width: 300,
253
+ fixed: 'right',
254
+ align: 'center',
255
+ headerAlign: 'center',
256
+ buttons: [
257
+ {
258
+ label: '查看',
259
+ type: 'primary',
260
+ link: true,
261
+ icon: View,
262
+ handler: (row) => handleView(row),
263
+ },
264
+ {
265
+ label: '编辑',
266
+ type: 'warning',
267
+ link: true,
268
+ icon: Edit,
269
+ handler: (row) => handleEdit(row),
270
+ },
271
+ {
272
+ label: '删除',
273
+ type: 'danger',
274
+ link: true,
275
+ icon: Delete,
276
+ show: true,
277
+ disabled: (row) => row.status === 0, // 业务时不展示
278
+ handler: (row) => handleDelete(row),
279
+ },
280
+ ],
281
+ },
282
+ ])
283
+
284
+ // ==================== 工具方法 ====================
285
+ const getStatusType = (status) => {
286
+ return status === 1 ? 'success' : 'danger'
287
+ }
288
+
289
+ const getStatusText = (status) => {
290
+ return status === 1 ? '启用' : '禁用'
291
+ }
292
+
293
+ const getDepartmentText = (department) => {
294
+ const departmentOptions = [
295
+ { label: '技术部', value: 'tech' },
296
+ { label: '产品部', value: 'product' },
297
+ { label: '运营部', value: 'operation' },
298
+ { label: '人力资源部', value: 'hr' },
299
+ { label: '财务部', value: 'finance' },
300
+ ]
301
+ const dept = departmentOptions.find((d) => d.value === department)
302
+ return dept ? dept.label : department
303
+ }
304
+
305
+ // ==================== 数据加载 ====================
306
+ const loadData = async () => {
307
+ loading.value = true
308
+ try {
309
+ // 模拟网络延迟
310
+ await new Promise((resolve) => setTimeout(resolve, 500))
311
+
312
+ // 从组件获取分页信息
313
+ const pagination = containerRef.value?.getPagination() || {
314
+ currentPage: 1,
315
+ pageSize: 10,
316
+ }
317
+
318
+ // 使用 filterUsers 进行过滤和分页
319
+ const result = filterUsers(mockUsers, searchParams.value, {
320
+ currentPage: pagination.currentPage,
321
+ pageSize: pagination.pageSize,
322
+ })
323
+
324
+ // 更新数据
325
+ tableData.value = result.list
326
+ total.value = result.total
327
+ } catch (error) {
328
+ console.error('加载数据失败:', error)
329
+ ElMessage.error('加载数据失败')
330
+ } finally {
331
+ loading.value = false
332
+ }
333
+ }
334
+
335
+ // ==================== 事件处理 ====================
336
+ // 搜索
337
+ const handleSearch = (params) => {
338
+ // 更新搜索参数
339
+ searchParams.value = { ...params }
340
+ loadData()
341
+ }
342
+
343
+ // 重置
344
+ const handleReset = () => {
345
+ // 重置搜索参数
346
+ // searchParams.value = {};
347
+ console.log('表单已重置,数据已刷新')
348
+ }
349
+
350
+ // 选择变化
351
+ const handleSelectionChange = (selection) => {
352
+ console.log('选中的数据:', selection)
353
+ }
354
+
355
+ // ==================== 选择列操作方法 ====================
356
+ const getSelectedRows = () => {
357
+ if (!containerRef.value) return
358
+ const selectedRows = containerRef.value.getSelectionRows()
359
+ ElMessage.success(
360
+ `选中了 ${selectedRows.length} 行数据:${selectedRows.map((r) => r.username).join(', ')}`,
361
+ )
362
+ console.log('选中的行数据:', selectedRows)
363
+ }
364
+
365
+ const getSelectedKeys = () => {
366
+ if (!containerRef.value) return
367
+ const selectedKeys = containerRef.value.getSelectionKeys()
368
+ ElMessage.success(`选中了 ${selectedKeys.length} 个ID:${selectedKeys.join(', ')}`)
369
+ console.log('选中的ID:', selectedKeys)
370
+ }
371
+
372
+ const selectRows = (ids) => {
373
+ if (!containerRef.value) return
374
+
375
+ try {
376
+ // 设置选择
377
+ containerRef.value.setSelectionKeys(ids)
378
+
379
+ // 延迟检查选择结果
380
+ setTimeout(() => {
381
+ const selectedRows = containerRef.value.getSelectionRows()
382
+ const selectedKeys = containerRef.value.getSelectionKeys()
383
+
384
+ if (selectedRows.length > 0) {
385
+ ElMessage.success(`已选中ID为 ${ids.join(', ')} 的行,实际选中:${selectedKeys.join(', ')}`)
386
+ } else {
387
+ ElMessage.warning(`未选中任何行,请检查数据是否正确`)
388
+ }
389
+ }, 100)
390
+ } catch (error) {
391
+ console.error('选择出错:', error)
392
+ ElMessage.error(`选择失败:${error.message}`)
393
+ }
394
+ }
395
+
396
+ const clearSelection = () => {
397
+ if (!containerRef.value) return
398
+ containerRef.value.clearAllSelection()
399
+ ElMessage.success('已清空所有选择')
400
+ }
401
+
402
+ const selectAll = () => {
403
+ if (!containerRef.value) return
404
+ containerRef.value.selectAll()
405
+ ElMessage.success('已全选所有行')
406
+ }
407
+
408
+ const checkSelection = () => {
409
+ if (!containerRef.value) return
410
+
411
+ // 检查特定行是否被选中
412
+ const isRow1Selected = containerRef.value.isRowSelected(tableData.value[0])
413
+ const isKey3Selected = containerRef.value.isKeySelected(3)
414
+
415
+ ElMessage.info(
416
+ `第一行是否选中:${isRow1Selected ? '是' : '否'},ID为3是否选中:${
417
+ isKey3Selected ? '是' : '否'
418
+ }`,
419
+ )
420
+ }
421
+
422
+ // 新增
423
+ const handleAdd = () => {
424
+ ElMessage.success('新增')
425
+ }
426
+
427
+ // 查看
428
+ const handleView = (row) => {
429
+ ElMessage.success(`查看:${row.username}`)
430
+ }
431
+
432
+ // 编辑
433
+ const handleEdit = (row) => {
434
+ ElMessage.success(`编辑:${row.username}`)
435
+ }
436
+
437
+ // 删除
438
+ const handleDelete = (row) => {
439
+ ElMessageBox.confirm(`确定要删除用户 "${row.username}" 吗?`, '删除确认', {
440
+ confirmButtonText: '确定',
441
+ cancelButtonText: '取消',
442
+ type: 'warning',
443
+ }).then(() => {
444
+ // 模拟删除
445
+ ElMessage.success('删除成功')
446
+ loadData()
447
+ })
448
+ }
449
+
450
+ // ==================== 生命周期 ====================
451
+ onMounted(async () => {
452
+ // 异步获取状态选项(模拟接口请求,延迟2秒)
453
+ const options = await fetchStatusOptions()
454
+ searchItems.value[2].children = options
455
+
456
+ // 异步获取部门选项(模拟接口请求,延迟2秒)
457
+ const departmentOptions = await fetchDepartmentOptions()
458
+ searchItems.value[3].children = departmentOptions
459
+
460
+ // 搜索条件准备好后,调用 initSearchAndLoad 初始化搜索参数并加载数据
461
+ // 这会自动获取 PageSearch 的初始表单数据(包含默认值和外部参数)
462
+ containerRef.value?.initSearchAndLoad()
463
+ })
464
+ </script>
465
+
466
+ <style scoped>
467
+ .demo-page {
468
+ height: 100%;
469
+ padding: 20px;
470
+ background: #f5f7fa;
471
+ display: flex;
472
+ flex-direction: column;
473
+ }
474
+
475
+ :deep(.el-dialog__body) {
476
+ padding: 20px;
477
+ }
478
+
479
+ .selection-actions {
480
+ margin-top: 20px;
481
+ padding: 20px;
482
+ background: #f5f7fa;
483
+ border-radius: 4px;
484
+ display: flex;
485
+ gap: 10px;
486
+ flex-wrap: wrap;
487
+ }
488
+
489
+ .debug-content {
490
+ padding: 0 20px;
491
+ }
492
+
493
+ .debug-item {
494
+ margin-bottom: 24px;
495
+ }
496
+
497
+ .debug-label {
498
+ display: block;
499
+ font-weight: 600;
500
+ color: #303133;
501
+ margin-bottom: 8px;
502
+ font-size: 14px;
503
+ }
504
+
505
+ .debug-value {
506
+ background: #f5f7fa;
507
+ padding: 12px;
508
+ border-radius: 4px;
509
+ font-size: 13px;
510
+ color: #606266;
511
+ margin: 0;
512
+ white-space: pre-wrap;
513
+ word-wrap: break-word;
514
+ border: 1px solid #e4e7ed;
515
+ }
516
+ </style>