matrix_components 2.0.440 → 2.0.443
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +671 -183
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,25 +1,10 @@
|
|
|
1
|
-
#
|
|
2
|
-
组件使用示例参考dist/ComponentDemo
|
|
1
|
+
# Matrix Components 组件库
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
## 简介
|
|
5
4
|
|
|
6
|
-

|
|
5
|
+
Matrix Components 是一个功能丰富的 Vue 3 企业级组件库,提供办公文档预览、动态表单、视频播放、权限控制等完整解决方案。
|
|
7
6
|
|
|
8
|
-

|
|
9
|
-
|
|
10
|
-

|
|
11
|
-
|
|
12
|
-

|
|
13
|
-
|
|
14
|
-

|
|
15
|
-
|
|
16
|
-

|
|
17
|
-
|
|
18
|
-

|
|
19
|
-
|
|
20
|
-

|
|
21
|
-
|
|
22
|
-

|
|
7
|
+
组件使用示例参考 `dist/ComponentDemo`
|
|
23
8
|
|
|
24
9
|
```
|
|
25
10
|
version:2.0.440
|
|
@@ -172,7 +157,6 @@ version:2.0.308
|
|
|
172
157
|
1.增加Demo示例目录:组件使用示例在dist/ComponentDemo
|
|
173
158
|
```
|
|
174
159
|
|
|
175
|
-
|
|
176
160
|
```
|
|
177
161
|
version:2.0.305
|
|
178
162
|
2025年10月21日15:05:11
|
|
@@ -260,6 +244,40 @@ version:2.0.292
|
|
|
260
244
|
1.NsPdf预览组件支持搜索功能
|
|
261
245
|
```
|
|
262
246
|
|
|
247
|
+
|
|
248
|
+
## 📊 功能特性总结
|
|
249
|
+
|
|
250
|
+
### 组件功能
|
|
251
|
+
|
|
252
|
+
- ✅ **NsOffice**: 办公文档统一预览(Excel/PDF/Word)
|
|
253
|
+
- ✅ **NsForm**: 动态表单生成和管理
|
|
254
|
+
- ✅ **NsVideo**: 专业视频播放器
|
|
255
|
+
- ✅ **NsDialog**: 灵活弹窗对话框
|
|
256
|
+
- ✅ **NsPdf**: PDF文档预览和搜索
|
|
257
|
+
- ✅ **NsExcel**: Excel预览和编辑
|
|
258
|
+
- ✅ **NsWord**: Word文档预览
|
|
259
|
+
- ✅ **NsImage**: 图片预览
|
|
260
|
+
- ✅ **NsMD**: Markdown编辑器
|
|
261
|
+
- ✅ **NsSaturationline**: 浸润线
|
|
262
|
+
- ✅ **NsAutoScreen**: 自适应屏幕工具
|
|
263
|
+
|
|
264
|
+
### 指令功能
|
|
265
|
+
|
|
266
|
+
- ✅ **v-permission**: 按钮权限控制
|
|
267
|
+
- ✅ **v-length**: 输入长度和格式限制
|
|
268
|
+
- ✅ **v-sline**: 单行文本省略
|
|
269
|
+
- ✅ **v-event-unuse/use**: 事件穿透控制
|
|
270
|
+
|
|
271
|
+
### 工具函数
|
|
272
|
+
|
|
273
|
+
- ✅ **HTTP请求**: 完整的RESTful API封装
|
|
274
|
+
- ✅ **资源加载**: 动态JS/CSS资源管理
|
|
275
|
+
- ✅ **表格排序**: 表格排序功能
|
|
276
|
+
- ✅ **SM2加密**: 国密算法加密
|
|
277
|
+
- ✅ **CSS变量**: 主题样式管理
|
|
278
|
+
- ✅ **通用工具**: 常用工具函数
|
|
279
|
+
|
|
280
|
+
|
|
263
281
|
## 创建公共组件库步骤
|
|
264
282
|
|
|
265
283
|
- npm create vue@latest
|
|
@@ -284,7 +302,6 @@ version:2.0.292
|
|
|
284
302
|
// 全局导入
|
|
285
303
|
export default NsComponents
|
|
286
304
|
```
|
|
287
|
-
|
|
288
305
|
- 子目录:NsXX目录,创建独立导出index.ts
|
|
289
306
|
|
|
290
307
|
```
|
|
@@ -297,7 +314,6 @@ version:2.0.292
|
|
|
297
314
|
// 导出子组件
|
|
298
315
|
export default NsXX
|
|
299
316
|
```
|
|
300
|
-
|
|
301
317
|
- 配置package.json
|
|
302
318
|
|
|
303
319
|
```
|
|
@@ -325,7 +341,6 @@ version:2.0.292
|
|
|
325
341
|
...
|
|
326
342
|
}
|
|
327
343
|
```
|
|
328
|
-
|
|
329
344
|
- 配置vite.config.ts
|
|
330
345
|
|
|
331
346
|
```
|
|
@@ -364,13 +379,11 @@ version:2.0.292
|
|
|
364
379
|
},
|
|
365
380
|
}
|
|
366
381
|
```
|
|
367
|
-
|
|
368
382
|
- 打包
|
|
369
383
|
|
|
370
384
|
```
|
|
371
385
|
npm run build
|
|
372
386
|
```
|
|
373
|
-
|
|
374
387
|
- 当前项目main.ts使用
|
|
375
388
|
|
|
376
389
|
```
|
|
@@ -383,7 +396,6 @@ version:2.0.292
|
|
|
383
396
|
// app.use(NsXX)
|
|
384
397
|
|
|
385
398
|
```
|
|
386
|
-
|
|
387
399
|
- 当前项目Test.vue使用
|
|
388
400
|
|
|
389
401
|
```
|
|
@@ -419,217 +431,693 @@ version:2.0.292
|
|
|
419
431
|
|
|
420
432
|
```
|
|
421
433
|
|
|
422
|
-
|
|
434
|
+
## 📋 组件列表
|
|
435
|
+
|
|
436
|
+
### 1. NsOffice - 办公文档统一预览组件
|
|
437
|
+
|
|
438
|
+
支持格式:Excel(.xlsx/.xls)、PDF(.pdf)、Word(.docx/.doc)
|
|
439
|
+
|
|
440
|
+
```vue
|
|
441
|
+
<template>
|
|
442
|
+
<!-- 基础使用 -->
|
|
443
|
+
<NsOffice :url="fileUrl" />
|
|
444
|
+
|
|
445
|
+
<!-- Excel编辑模式 -->
|
|
446
|
+
<NsOffice :url="excelUrl" :isEdit="true" />
|
|
447
|
+
|
|
448
|
+
<!-- 获取组件引用 -->
|
|
449
|
+
<NsOffice ref="officeRef" :url="fileUrl" />
|
|
450
|
+
</template>
|
|
451
|
+
|
|
452
|
+
<script setup>
|
|
453
|
+
import { ref } from 'vue'
|
|
454
|
+
import { NsOffice } from 'matrix_components'
|
|
455
|
+
|
|
456
|
+
const officeRef = ref()
|
|
457
|
+
|
|
458
|
+
// 获取文件类型
|
|
459
|
+
const fileType = officeRef.value?.getFileType() // 'excel' | 'pdf' | 'word' | 'unsupported'
|
|
460
|
+
|
|
461
|
+
// 获取当前激活的组件实例
|
|
462
|
+
const activeComponent = officeRef.value?.getActiveComponent()
|
|
463
|
+
|
|
464
|
+
// 刷新组件
|
|
465
|
+
officeRef.value?.refresh()
|
|
466
|
+
</script>
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### 2. NsForm - 动态表单组件
|
|
470
|
+
|
|
471
|
+
```vue
|
|
472
|
+
<template>
|
|
473
|
+
<NsForm :rows="formConfig" ref="formRef" />
|
|
474
|
+
</template>
|
|
475
|
+
|
|
476
|
+
<script setup>
|
|
477
|
+
import { ref } from 'vue'
|
|
478
|
+
import { NsForm } from 'matrix_components'
|
|
479
|
+
|
|
480
|
+
const formRef = ref()
|
|
481
|
+
const formConfig = [
|
|
482
|
+
{
|
|
483
|
+
key: 'name',
|
|
484
|
+
label: '姓名',
|
|
485
|
+
component: 'el-input',
|
|
486
|
+
props: { placeholder: '请输入姓名' }
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
key: 'age',
|
|
490
|
+
label: '年龄',
|
|
491
|
+
component: 'el-input-number',
|
|
492
|
+
props: { min: 0, max: 100 }
|
|
493
|
+
}
|
|
494
|
+
]
|
|
495
|
+
|
|
496
|
+
// 获取表单数据
|
|
497
|
+
const formData = formRef.value?.getFormData()
|
|
498
|
+
|
|
499
|
+
// 重置表单
|
|
500
|
+
formRef.value?.resetForm()
|
|
501
|
+
|
|
502
|
+
// 验证表单
|
|
503
|
+
const isValid = formRef.value?.validate()
|
|
504
|
+
</script>
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### 3. NsVideo - 视频播放组件
|
|
508
|
+
|
|
509
|
+
```vue
|
|
510
|
+
<template>
|
|
511
|
+
<NsVideo
|
|
512
|
+
ref="nsVideoRef"
|
|
513
|
+
v-bind="videoData"
|
|
514
|
+
v-on="videoEvent"
|
|
515
|
+
@changeSplit='changeSplitHandler'
|
|
516
|
+
>
|
|
517
|
+
<!-- 自定义插槽 -->
|
|
518
|
+
<template #video-tree><span>左侧树-自定义插槽</span></template>
|
|
519
|
+
<template #video-player-head><span>播放区域头部-自定义插槽</span></template>
|
|
520
|
+
<template #video-player-view><span>播放区域主体-自定义插槽</span></template>
|
|
521
|
+
<template #video-player-foot><span>播放区域底部控制按钮-自定义插槽</span></template>
|
|
522
|
+
<template #video-player-cover><span>播放器canvas画布区域(除head+foot+tree区域)</span></template>
|
|
523
|
+
</NsVideo>
|
|
524
|
+
</template>
|
|
525
|
+
|
|
526
|
+
<script setup>
|
|
527
|
+
import { ref } from 'vue'
|
|
528
|
+
import { NsVideo } from 'matrix_components'
|
|
529
|
+
|
|
530
|
+
const nsVideoRef = ref()
|
|
531
|
+
|
|
532
|
+
// 视频配置数据
|
|
533
|
+
const videoData = {
|
|
534
|
+
// 显示视频关闭按钮
|
|
535
|
+
showClose: true,
|
|
536
|
+
// 是否支持全屏
|
|
537
|
+
hasFullScreen: true,
|
|
538
|
+
// 显示树
|
|
539
|
+
showTree: true,
|
|
540
|
+
// 树数据
|
|
541
|
+
treeData: [
|
|
542
|
+
{
|
|
543
|
+
id: '1',
|
|
544
|
+
label: '分组1',
|
|
545
|
+
children: [
|
|
546
|
+
{
|
|
547
|
+
videoModel: 'easyplayer',
|
|
548
|
+
id: '111',
|
|
549
|
+
label: '视频A',
|
|
550
|
+
url: 'ws://example.com/rtp/video.live.flv',
|
|
551
|
+
deviceId: 'a1',
|
|
552
|
+
channelId: 'a11',
|
|
553
|
+
icontype: 'on',
|
|
554
|
+
}
|
|
555
|
+
]
|
|
556
|
+
}
|
|
557
|
+
],
|
|
558
|
+
// 树节点对应的key
|
|
559
|
+
treeNodeKey: 'id',
|
|
560
|
+
// 树节点展开的key
|
|
561
|
+
treeExpandedKeys: ['11'],
|
|
562
|
+
// 树节点属性
|
|
563
|
+
treeOptions: {
|
|
564
|
+
icontype: 'icontype',
|
|
565
|
+
background: 'background',
|
|
566
|
+
videoUrlKey: 'url',
|
|
567
|
+
children: 'children',
|
|
568
|
+
label: 'label',
|
|
569
|
+
},
|
|
570
|
+
// 获取、设置打开的播放视频信息
|
|
571
|
+
videoInfos: [
|
|
572
|
+
{
|
|
573
|
+
index: 0,
|
|
574
|
+
url: 'https://example.com/video.flv',
|
|
575
|
+
info: {
|
|
576
|
+
videoModel: 'easyplayer',
|
|
577
|
+
id: 'video1',
|
|
578
|
+
url: 'https://example.com/video.flv',
|
|
579
|
+
deviceId: 'c1',
|
|
580
|
+
channelId: 'c11',
|
|
581
|
+
},
|
|
582
|
+
}
|
|
583
|
+
],
|
|
584
|
+
// 单点播放
|
|
585
|
+
videoSingleUrl: false,
|
|
586
|
+
// 已经在播放的是否关闭后再点击打开
|
|
587
|
+
videoSingleClose: false,
|
|
588
|
+
// 播放模式: 1: 单击,2: 双击
|
|
589
|
+
videoPlayModel: 1,
|
|
590
|
+
// 分屏模式: 1: 单屏, 2: 四屏, 3: 九屏
|
|
591
|
+
videoSplitType: 1,
|
|
592
|
+
// 显示分屏按钮
|
|
593
|
+
showVideoSplit: true,
|
|
594
|
+
// 显示方向控制按钮
|
|
595
|
+
showVideoCtrls: false,
|
|
596
|
+
// 禁止控制按钮默认请求行为
|
|
597
|
+
stopVideoCtrlMethods: true,
|
|
598
|
+
// 单个视频错误最大次数
|
|
599
|
+
videoErrorMaxCount: 3,
|
|
600
|
+
// easyplayer配置
|
|
601
|
+
videoConfig: {
|
|
602
|
+
MSE: true,
|
|
603
|
+
WCS: true,
|
|
604
|
+
WASM: true,
|
|
605
|
+
WASMSIMD: true,
|
|
606
|
+
isLive: true,
|
|
607
|
+
hasAudio: false,
|
|
608
|
+
stretch: false
|
|
609
|
+
},
|
|
610
|
+
// 事件回调
|
|
611
|
+
treeClick: () => { console.log('点击树节点') },
|
|
612
|
+
treeDBClick: () => { console.log('双击树节点') },
|
|
613
|
+
treeRightMenu: () => { console.log('右键树菜单') },
|
|
614
|
+
treeExpand: () => { console.log('展开树节点') },
|
|
615
|
+
videoError: () => { console.log('视频错误') },
|
|
616
|
+
}
|
|
423
617
|
|
|
618
|
+
// 视频操作事件
|
|
619
|
+
const videoEvent = {
|
|
620
|
+
videoOriginalInfo: (info) => { console.log('视频原始信息:', info) },
|
|
621
|
+
up: () => { console.log('向上移动') },
|
|
622
|
+
down: () => { console.log('向下移动') },
|
|
623
|
+
left: () => { console.log('向左移动') },
|
|
624
|
+
right: () => { console.log('向右移动') },
|
|
625
|
+
zoomin: () => { console.log('放大') },
|
|
626
|
+
zoomout: () => { console.log('缩小') },
|
|
627
|
+
stop: () => { console.log('停止') },
|
|
628
|
+
speed: () => { console.log('设置速度') },
|
|
629
|
+
speak: () => { console.log('开始说话') },
|
|
630
|
+
scan: () => { console.log('扫描') },
|
|
631
|
+
cruise: () => { console.log('巡航') },
|
|
632
|
+
call: () => { console.log('调用') },
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// 获取原始视频信息
|
|
636
|
+
const videoInfo = nsVideoRef.value?.getOriginalInfo()
|
|
637
|
+
|
|
638
|
+
// 设置视频URL
|
|
639
|
+
nsVideoRef.value?.setVideoUrl('ws://example.com/rtp/video.live.flv', false, 1, {
|
|
640
|
+
videoModel: 'easyplayer'
|
|
641
|
+
})
|
|
642
|
+
|
|
643
|
+
// 移除视频
|
|
644
|
+
nsVideoRef.value?.removeVideo(1, true)
|
|
645
|
+
|
|
646
|
+
// 分屏变化回调
|
|
647
|
+
function changeSplitHandler(num) {
|
|
648
|
+
console.log('分屏模式:', num)
|
|
649
|
+
}
|
|
650
|
+
</script>
|
|
424
651
|
```
|
|
425
|
-
// 1. 复制播放器资源
|
|
426
|
-
js文件夹 到 public/目录中
|
|
427
|
-
cdn文件夹 到 public/目录中
|
|
428
652
|
|
|
429
|
-
|
|
653
|
+
**前置准备:**
|
|
654
|
+
|
|
655
|
+
1. 复制播放器资源:`js文件夹` 到 `public/` 目录中
|
|
656
|
+
2. 复制播放器资源:`cdn文件夹` 到 `public/` 目录中
|
|
657
|
+
3. 在 `index.html` 中引入:
|
|
658
|
+
|
|
659
|
+
```html
|
|
430
660
|
<script src="./js/EasyPlayer-pro.js"></script>
|
|
431
661
|
<script src="./cdn/h5player/h5player.min.js"></script>
|
|
662
|
+
```
|
|
432
663
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
import 'matrix_components
|
|
437
|
-
|
|
664
|
+
### 4. NsDialog - 弹出框组件
|
|
665
|
+
|
|
666
|
+
```javascript
|
|
667
|
+
import { NsDialog, closeAllNsDialog } from 'matrix_components'
|
|
668
|
+
|
|
669
|
+
// 打开对话框
|
|
670
|
+
NsDialog({
|
|
671
|
+
title: '测试',
|
|
672
|
+
// 任何组件添加 $emit('close') 时,会触发关闭弹出框事件
|
|
673
|
+
dom: VideoDemo, // 也可以通过异步方式:import("@/views/VideoDemo.vue") 和 () => import("@/views/VideoDemo.vue")
|
|
674
|
+
option: {
|
|
675
|
+
// dom对应的自定义组件props属性
|
|
676
|
+
...data,
|
|
677
|
+
},
|
|
678
|
+
events: {
|
|
679
|
+
// dom组件内部自定义事件emit('btnClick', xxx)
|
|
680
|
+
btnClick: () => {
|
|
681
|
+
console.log("点击中间区域内容");
|
|
682
|
+
},
|
|
683
|
+
},
|
|
684
|
+
modalColor: 'rgb(0 21 115 / 20%)', // 遮罩层颜色
|
|
685
|
+
width: '800px', // 宽度, 整个弹出框的高度,非内容高度
|
|
686
|
+
height: '450px', // 高度, 不配置则默认为内容高度
|
|
687
|
+
dialogPadding: [10, 20], // 弹窗内padding
|
|
688
|
+
showFooter: true, // 默认显示底部按钮
|
|
689
|
+
immediately: false, // true立即取消弹出框, false异步请求后取消弹出框,默认false
|
|
690
|
+
draggable: true, // 是否可拖拽,默认false
|
|
691
|
+
|
|
692
|
+
confirm: async (closeFn, componentRef, footerLoading) => { // 底部确认按钮回调事件
|
|
693
|
+
// componentRef可以调用内部函数,前提需要defineExpose
|
|
694
|
+
try{
|
|
695
|
+
const selectRows = componentRef?.value?.getSelectedRows();
|
|
696
|
+
console.log("点击确认,选择数据:", selectRows);
|
|
697
|
+
} catch(e) {
|
|
698
|
+
console.log(e)
|
|
699
|
+
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
700
|
+
}
|
|
701
|
+
// footerLoading可以控制底部loading状态
|
|
702
|
+
if(footerLoading) {
|
|
703
|
+
footerLoading.value = false
|
|
704
|
+
}
|
|
705
|
+
// 请求数据,再关闭
|
|
706
|
+
if(closeFn) {
|
|
707
|
+
closeFn()
|
|
708
|
+
}
|
|
709
|
+
},
|
|
710
|
+
close: () => { // 关闭弹出时立即出发
|
|
711
|
+
console.log("点击关闭");
|
|
712
|
+
},
|
|
713
|
+
closed: () => { // 弹窗销毁时触发
|
|
714
|
+
console.log("完成关闭");
|
|
715
|
+
},
|
|
716
|
+
// 头部+底部自定义配置
|
|
717
|
+
headerDom: xxx,
|
|
718
|
+
headerOption: {},
|
|
719
|
+
headerEvents: {},
|
|
720
|
+
footerDom: yyy,
|
|
721
|
+
footerOption: {},
|
|
722
|
+
footerEvents: {},
|
|
723
|
+
// 底部按钮名称
|
|
724
|
+
footerTitle: {
|
|
725
|
+
close: "取消",
|
|
726
|
+
confirm: "确定",
|
|
727
|
+
},
|
|
728
|
+
}, true, '#app') // true为是否遮罩(非必填), '#app'为挂载点(非必填)
|
|
729
|
+
|
|
730
|
+
// 关闭所有对话框
|
|
731
|
+
closeAllNsDialog()
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
### 5. NsPdf - PDF预览组件
|
|
735
|
+
|
|
736
|
+
```vue
|
|
737
|
+
<template>
|
|
738
|
+
<NsPdf ref="pdfRef" :url="pdfUrl"></NsPdf>
|
|
739
|
+
</template>
|
|
740
|
+
|
|
741
|
+
<script setup>
|
|
742
|
+
import { ref } from 'vue'
|
|
743
|
+
import { NsPdf } from 'matrix_components'
|
|
438
744
|
|
|
439
|
-
|
|
745
|
+
const pdfRef = ref()
|
|
746
|
+
|
|
747
|
+
// 搜索关键词
|
|
748
|
+
function searchKeyword() {
|
|
749
|
+
pdfRef.value?.search('关键词')
|
|
750
|
+
}
|
|
751
|
+
</script>
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
### 6. NsExcel - Excel预览/编辑组件
|
|
755
|
+
|
|
756
|
+
```vue
|
|
440
757
|
<template>
|
|
441
|
-
|
|
442
|
-
<!-- 自定义插槽
|
|
443
|
-
<template #video-tree><span>左侧树-自定义插槽</span></template>
|
|
444
|
-
<template #video-player-head><span>播放区域头部-自定义插槽</span></template>
|
|
445
|
-
<template #video-player-view><span>播放区域主体-自定义插槽</span></template>
|
|
446
|
-
<template #video-player-foot><span>播放区域底部控制按钮-自定义插槽</span></template>
|
|
447
|
-
-->
|
|
448
|
-
</NsVideo>
|
|
758
|
+
<NsExcel :url="excelUrl" :isEdit="true" />
|
|
449
759
|
</template>
|
|
450
760
|
```
|
|
451
761
|
|
|
452
|
-
###
|
|
762
|
+
### 7. NsWord - Word预览组件
|
|
453
763
|
|
|
764
|
+
```vue
|
|
765
|
+
<template>
|
|
766
|
+
<NsWord :url="wordUrl" />
|
|
767
|
+
</template>
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
### 8. NsImage - 图片预览组件
|
|
771
|
+
|
|
772
|
+
```vue
|
|
773
|
+
<template>
|
|
774
|
+
<NsImage :src="imageUrl" :defaultImg="defaultImage" />
|
|
775
|
+
</template>
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
### 9. NsMD - Markdown编辑器组件
|
|
779
|
+
|
|
780
|
+
```vue
|
|
781
|
+
<template>
|
|
782
|
+
<NsMD v-model="markdownContent" />
|
|
783
|
+
</template>
|
|
454
784
|
```
|
|
455
|
-
// 1. 安装公共组件库 (安装过则无需安装)
|
|
456
|
-
//@ts-ignore
|
|
457
|
-
import NsComponents, { autoScaleInit } from 'matrix_components'
|
|
458
|
-
import 'matrix_components/dist/matrix_components.css'
|
|
459
|
-
app.use(NsComponents)
|
|
460
785
|
|
|
461
|
-
|
|
786
|
+
### 10. NsSaturationline - 饱和度线组件
|
|
787
|
+
|
|
788
|
+
```vue
|
|
789
|
+
<template>
|
|
790
|
+
<NsSaturationline :data="saturationData" />
|
|
791
|
+
</template>
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
### 11. NsAutoScreen - 自适应屏幕工具
|
|
795
|
+
|
|
796
|
+
```javascript
|
|
797
|
+
import { autoScaleInit, sacle_x, sacle_y } from 'matrix_components'
|
|
798
|
+
|
|
799
|
+
// 初始化自适应
|
|
462
800
|
autoScaleInit(document.querySelector('body'), {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
801
|
+
designWidth: 1920,
|
|
802
|
+
designHeight: 920,
|
|
803
|
+
mode: 'stretch', // 可选 horizontal/vertical/stretch
|
|
466
804
|
});
|
|
467
805
|
|
|
806
|
+
// 获取缩放比例
|
|
807
|
+
const scaleX = sacle_x()
|
|
808
|
+
const scaleY = sacle_y()
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
## 🔧 自定义指令
|
|
814
|
+
|
|
815
|
+
### 1. v-permission - 按钮权限控制
|
|
816
|
+
|
|
817
|
+
```vue
|
|
818
|
+
<template>
|
|
819
|
+
<!-- 使用class控制权限,无权限时隐藏 -->
|
|
820
|
+
<el-button v-permission.class.display>查看</el-button>
|
|
821
|
+
|
|
822
|
+
<!-- 使用id控制权限,无权限时隐藏 -->
|
|
823
|
+
<el-button v-permission.id>编辑</el-button>
|
|
824
|
+
|
|
825
|
+
<!-- 默认使用id控制权限 -->
|
|
826
|
+
<el-button id="zuhu_list_add" v-permission>新增</el-button>
|
|
827
|
+
</template>
|
|
828
|
+
|
|
829
|
+
<script setup>
|
|
830
|
+
// 权限配置(需要在引入组件库之前设置)
|
|
831
|
+
import { createApp } from 'vue'
|
|
832
|
+
|
|
833
|
+
const app = createApp(App)
|
|
834
|
+
const btnsPermission = {
|
|
835
|
+
'zuhu_list_add': true, // 有权限
|
|
836
|
+
'zuhu_list_edit': false // 无权限
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
app.provide('btnsPermission', btnsPermission)
|
|
840
|
+
app.use(NsComponents) // 引入组件库
|
|
841
|
+
</script>
|
|
468
842
|
```
|
|
469
843
|
|
|
470
|
-
###
|
|
844
|
+
### 2. v-length - 输入长度限制
|
|
845
|
+
|
|
846
|
+
```vue
|
|
847
|
+
<template>
|
|
848
|
+
<!-- 限制最大长度50(默认) -->
|
|
849
|
+
<el-input v-length placeholder="请输入用户名" />
|
|
850
|
+
|
|
851
|
+
<!-- 自定义长度限制 -->
|
|
852
|
+
<el-input v-length="100" placeholder="最多100字符" />
|
|
853
|
+
|
|
854
|
+
<!-- 仅允许输入数字 -->
|
|
855
|
+
<el-input v-length.number="11" placeholder="请输入手机号" />
|
|
856
|
+
|
|
857
|
+
<!-- 自定义正则表达式 -->
|
|
858
|
+
<el-input v-length.regex="{ maxLength: 10, pattern: /^[a-zA-Z]*$/ }" placeholder="仅允许字母" />
|
|
859
|
+
|
|
860
|
+
<!-- 数字范围限制 -->
|
|
861
|
+
<el-input v-length.range="{ min: 0, max: 100, int: true, maxLength: 10 }" placeholder="0-100整数" />
|
|
862
|
+
</template>
|
|
471
863
|
```
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
...data,
|
|
480
|
-
},
|
|
481
|
-
events: {
|
|
482
|
-
// dom组件内部自定义事件emit('btnClick', xxx)
|
|
483
|
-
btnClick: () => {
|
|
484
|
-
console.log("点击中间区域内容");
|
|
485
|
-
},
|
|
486
|
-
},
|
|
487
|
-
modalColor: 'rgb(0 21 115 / 20%)', // 遮罩层颜色
|
|
488
|
-
width: '800px', // 宽度, 整个弹出框的高度,非内容高度
|
|
489
|
-
height: '450px', // 高度, 不配置则默认为内容高度
|
|
490
|
-
dialogPadding: [10, 20], // 弹窗内padding
|
|
491
|
-
showFooter: true, // 默认显示底部按钮
|
|
492
|
-
immediately: false, // true立即取消弹出框, false异步请求后取消弹出框,默认false
|
|
493
|
-
draggable: true, // 是否可拖拽,默认false
|
|
494
|
-
|
|
495
|
-
confirm: async (closeFn: any, componentRef: any, footerLoading: any) => { // 底部确认按钮回调事件
|
|
496
|
-
// 2.componentRef可以调用内部函数,前提需要defineExpose
|
|
497
|
-
try{
|
|
498
|
-
const selectRows = componentRef?.value?.getSelectedRows();
|
|
499
|
-
console.log("点击确认,选择数据:", selectRows);
|
|
500
|
-
} catch(e) {
|
|
501
|
-
console.log(e)
|
|
502
|
-
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
503
|
-
}
|
|
504
|
-
// 3.footerLoading可以控制底部loading状态
|
|
505
|
-
if(footerLoading) {
|
|
506
|
-
footerLoading.value = false
|
|
507
|
-
}
|
|
508
|
-
// 1.请求数据,再关闭
|
|
509
|
-
if(closeFn) {
|
|
510
|
-
closeFn()
|
|
511
|
-
}
|
|
512
|
-
},
|
|
513
|
-
close: () => { // 关闭弹出时立即出发
|
|
514
|
-
console.log("点击关闭");
|
|
515
|
-
},
|
|
516
|
-
closed: () => { // 弹窗销毁时触发
|
|
517
|
-
console.log("完成关闭");
|
|
518
|
-
},
|
|
519
|
-
// 头部+底部自定义配置
|
|
520
|
-
// 任何组件添加 $emit('close') 时,会触发关闭弹出框事件
|
|
521
|
-
headerDom: xxx,
|
|
522
|
-
headerOption: {},
|
|
523
|
-
headerEvents: {},
|
|
524
|
-
// 任何组件添加 $emit('close') 时,会触发关闭弹出框事件
|
|
525
|
-
footerDom: yyy,
|
|
526
|
-
footerOption: {},
|
|
527
|
-
footerEvents: {},
|
|
528
|
-
// 底部按钮名称
|
|
529
|
-
footerTitle: {
|
|
530
|
-
close: "取消",
|
|
531
|
-
confirm: "确定",
|
|
532
|
-
},
|
|
533
|
-
}, true, '#app') // true为是否遮罩(非必填), '#app'为挂载点(非必填)
|
|
864
|
+
|
|
865
|
+
### 3. v-sline - 单行文本省略
|
|
866
|
+
|
|
867
|
+
```vue
|
|
868
|
+
<template>
|
|
869
|
+
<span v-sline>这是一段很长的文本内容,超出部分会自动显示省略号...</span>
|
|
870
|
+
</template>
|
|
534
871
|
```
|
|
535
872
|
|
|
536
|
-
### 4.
|
|
873
|
+
### 4. v-event-unuse / v-event-use - 事件穿透控制
|
|
874
|
+
|
|
875
|
+
```vue
|
|
876
|
+
<template>
|
|
877
|
+
<!-- 阻止事件穿透 -->
|
|
878
|
+
<div v-event-use>
|
|
879
|
+
<button>这个按钮可以点击</button>
|
|
880
|
+
</div>
|
|
881
|
+
|
|
882
|
+
<!-- 允许事件穿透 -->
|
|
883
|
+
<div v-event-unuse>
|
|
884
|
+
<div>这个区域的事件会穿透到下层</div>
|
|
885
|
+
</div>
|
|
886
|
+
</template>
|
|
537
887
|
```
|
|
538
|
-
// 使用方法
|
|
539
|
-
// 1. 按钮权限 v-permission.class.display / v-permission.id.display / v-permission.class / v-permission.id(默认)
|
|
540
|
-
<button id="zuhu_list_add" v-permission>新增</button>
|
|
541
888
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
889
|
+
## 🔧 工具函数
|
|
890
|
+
|
|
891
|
+
### 1. 通用工具函数
|
|
892
|
+
|
|
893
|
+
```javascript
|
|
894
|
+
import { isNotNull } from 'matrix_components'
|
|
895
|
+
|
|
896
|
+
// 检查值是否非空
|
|
897
|
+
const result = isNotNull(value) // 返回布尔值
|
|
898
|
+
```
|
|
546
899
|
|
|
547
|
-
|
|
548
|
-
// .number 修饰符会限制只能输入数字(通过输入事件过滤非数字字符)
|
|
549
|
-
<el-input placeholder="请输入手机号" v-length.number="11"/>
|
|
550
|
-
<el-input placeholder="请输入用户名" v-length />
|
|
900
|
+
### 2. 动态资源加载
|
|
551
901
|
|
|
552
|
-
|
|
553
|
-
|
|
902
|
+
```javascript
|
|
903
|
+
import { loadAccess, removeDynamicAccess } from 'matrix_components'
|
|
554
904
|
|
|
555
|
-
//
|
|
556
|
-
|
|
557
|
-
<div>无法点击到</div>
|
|
905
|
+
// 加载JS/CSS资源
|
|
906
|
+
await loadAccess('https://example.com/script.js', 'script-tag', false)
|
|
558
907
|
|
|
559
|
-
|
|
560
|
-
|
|
908
|
+
// 移除动态加载的资源
|
|
909
|
+
removeDynamicAccess('script-tag')
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
### 3. CSS变量管理
|
|
561
913
|
|
|
914
|
+
```javascript
|
|
915
|
+
import { loadCssVars } from 'matrix_components'
|
|
916
|
+
|
|
917
|
+
// 获取所有CSS变量
|
|
918
|
+
const cssVars = loadCssVars()
|
|
919
|
+
console.log(cssVars['--matrix-primary-color'])
|
|
562
920
|
```
|
|
563
921
|
|
|
922
|
+
### 4. 表格排序工具
|
|
923
|
+
|
|
924
|
+
```javascript
|
|
925
|
+
import { handleSortChange, headerClick, handleHeaderCellClass } from 'matrix_components'
|
|
564
926
|
|
|
565
|
-
|
|
927
|
+
// 在表格组件中使用
|
|
928
|
+
<el-table
|
|
929
|
+
@sort-change="(sort) => handleSortChange(sort, searchForm, getList)"
|
|
930
|
+
@header-click="headerClick"
|
|
931
|
+
:header-cell-class-name="(params) => handleHeaderCellClass(params, searchForm)"
|
|
932
|
+
>
|
|
933
|
+
<!-- 表格内容 -->
|
|
934
|
+
</el-table>
|
|
566
935
|
```
|
|
567
|
-
// 使用方法
|
|
568
|
-
import NsComponents, { getEncryptSm2 } from 'matrix_components'
|
|
569
|
-
app.use(NsComponents)
|
|
570
|
-
const encrypArrs = getEncryptSm2(publicKey, ["xxx", "yyy"], isAdd04=false, cipherMode=1)
|
|
571
936
|
|
|
937
|
+
### 5. SM2加密工具
|
|
938
|
+
|
|
939
|
+
```javascript
|
|
940
|
+
import { getEncryptSm2 } from 'matrix_components'
|
|
941
|
+
|
|
942
|
+
// 使用SM2加密
|
|
943
|
+
const encrypted = getEncryptSm2(publicKey, ["xxx", "yyy"], isAdd04=false, cipherMode=1)
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
### 6. 动态表单工具函数
|
|
947
|
+
|
|
948
|
+
```javascript
|
|
949
|
+
import {
|
|
950
|
+
useFileUpload,
|
|
951
|
+
getAllFormNodeByKey,
|
|
952
|
+
getAllFormKvData,
|
|
953
|
+
getAllFormNodeRefByKey
|
|
954
|
+
} from 'matrix_components'
|
|
955
|
+
|
|
956
|
+
// 表单文件上传hook
|
|
957
|
+
const { uploadFile, deleteFile } = useFileUpload()
|
|
958
|
+
|
|
959
|
+
// 根据key获取表单节点信息
|
|
960
|
+
const formNode = getAllFormNodeByKey(formRows, 'username')
|
|
961
|
+
|
|
962
|
+
// 获取表单所有键值对数据
|
|
963
|
+
const formData = getAllFormKvData(formRows)
|
|
964
|
+
|
|
965
|
+
// 根据key获取表单节点引用
|
|
966
|
+
const nodeRef = getAllFormNodeRefByKey(formRows, 'username')
|
|
967
|
+
```
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
### 7. 屏幕自适应函数
|
|
972
|
+
|
|
973
|
+
```javascript
|
|
974
|
+
import { sacle_x, sacle_y, autoScaleInit } from 'matrix_components'
|
|
975
|
+
|
|
976
|
+
// 初始化自适应
|
|
977
|
+
autoScaleInit(document.querySelector('body'), {
|
|
978
|
+
designWidth: 1920,
|
|
979
|
+
designHeight: 920,
|
|
980
|
+
mode: 'stretch' // 可选 horizontal/vertical/stretch
|
|
981
|
+
})
|
|
982
|
+
|
|
983
|
+
// 获取当前缩放比例
|
|
984
|
+
const scaleX = sacle_x()
|
|
985
|
+
const scaleY = sacle_y()
|
|
572
986
|
```
|
|
573
987
|
|
|
574
|
-
|
|
988
|
+
## 🌐 HTTP请求函数
|
|
989
|
+
|
|
990
|
+
### 1. 基础HTTP请求方法
|
|
991
|
+
|
|
992
|
+
```javascript
|
|
993
|
+
import { get, post, put, del, download, downLoadLocalFile, getTokenInfo } from 'matrix_components'
|
|
994
|
+
|
|
995
|
+
// GET请求
|
|
996
|
+
const result = await get('/api/users', { page: 1, size: 10 })
|
|
997
|
+
|
|
998
|
+
// POST请求
|
|
999
|
+
const result = await post('/api/users', { name: '张三', age: 25 })
|
|
1000
|
+
|
|
1001
|
+
// PUT请求
|
|
1002
|
+
const result = await put('/api/users/1', { name: '李四', age: 30 })
|
|
1003
|
+
|
|
1004
|
+
// DELETE请求
|
|
1005
|
+
const result = await del('/api/users/1')
|
|
1006
|
+
|
|
1007
|
+
// 文件下载
|
|
1008
|
+
await download('/api/export', 'report.xlsx', 'get', { type: 'excel' })
|
|
1009
|
+
|
|
1010
|
+
// 下载本地文件
|
|
1011
|
+
downLoadLocalFile('/public/', 'template.xlsx', 'template.xlsx')
|
|
1012
|
+
|
|
1013
|
+
// 获取token信息
|
|
1014
|
+
const tokenInfo = getTokenInfo()
|
|
575
1015
|
```
|
|
576
|
-
|
|
577
|
-
|
|
1016
|
+
|
|
1017
|
+
### 2. 初始化配置
|
|
1018
|
+
|
|
1019
|
+
```javascript
|
|
1020
|
+
// main.ts中配置
|
|
1021
|
+
import { createApp } from 'vue'
|
|
578
1022
|
import NsComponents from 'matrix_components'
|
|
579
1023
|
|
|
1024
|
+
const app = createApp(App)
|
|
1025
|
+
|
|
580
1026
|
// 请求地址的baseUrl,建议在app.use(NsComponents)之前设置
|
|
581
|
-
app.config.globalProperties.$BaseUrl = 'http
|
|
1027
|
+
app.config.globalProperties.$BaseUrl = 'http://api.example.com/'
|
|
1028
|
+
|
|
582
1029
|
// 图片、文件请求地址的ImageBaseUrl,建议在app.use(NsComponents)之前设置
|
|
583
|
-
app.config.globalProperties.$ImageBaseUrl = 'http
|
|
584
|
-
app.use(NsComponents)
|
|
1030
|
+
app.config.globalProperties.$ImageBaseUrl = 'http://api.example.com/'
|
|
585
1031
|
|
|
586
1032
|
// 【可选】401无权显示回调
|
|
587
|
-
app.config.globalProperties.$LogoutCallback = logoutHandler
|
|
588
|
-
// 【可选】请求添加的token头的key,默认为satoken。token的key和value需要在外部项目中自己设置
|
|
589
|
-
sessionStorage.setItem('tokenName', 'xxx')
|
|
590
|
-
sessionStorage.setItem('tokenValue', 'yyy')
|
|
1033
|
+
app.config.globalProperties.$LogoutCallback = logoutHandler
|
|
591
1034
|
|
|
592
|
-
//
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
```
|
|
1035
|
+
// 【可选】请求添加的token头的key,默认为satoken
|
|
1036
|
+
sessionStorage.setItem('tokenName', 'Authorization')
|
|
1037
|
+
sessionStorage.setItem('tokenValue', 'Bearer your-token-here')
|
|
596
1038
|
|
|
597
|
-
|
|
1039
|
+
app.use(NsComponents)
|
|
598
1040
|
```
|
|
599
|
-
// 使用方法
|
|
600
|
-
import { NsPdf } from 'matrix_components'
|
|
601
|
-
<NsPdf ref="pdfRef" :url="pdfUrl"></NsPdf>
|
|
602
|
-
const pdfRef = ref()
|
|
603
1041
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
1042
|
+
### 3. 实际使用示例
|
|
1043
|
+
|
|
1044
|
+
```javascript
|
|
1045
|
+
// api/user.js
|
|
1046
|
+
import { get, post } from 'matrix_components'
|
|
1047
|
+
|
|
1048
|
+
export const getUserList = (params) => get('/api/users', params)
|
|
1049
|
+
|
|
1050
|
+
export const createUser = (data) => post('/api/users', data)
|
|
1051
|
+
|
|
1052
|
+
export const updateUser = (id, data) => put(`/api/users/${id}`, data)
|
|
1053
|
+
|
|
1054
|
+
export const deleteUser = (id) => del(`/api/users/${id}`)
|
|
1055
|
+
|
|
1056
|
+
export const exportUsers = () => download('/api/users/export', 'users.xlsx')
|
|
607
1057
|
```
|
|
608
1058
|
|
|
609
|
-
|
|
1059
|
+
## 🚀 完整安装和使用
|
|
1060
|
+
|
|
1061
|
+
### 1. 安装依赖
|
|
1062
|
+
|
|
1063
|
+
```bash
|
|
1064
|
+
# 安装Element Plus
|
|
1065
|
+
pnpm i element-plus
|
|
1066
|
+
|
|
1067
|
+
# 安装组件库
|
|
1068
|
+
pnpm i matrix_components -S --registry=http://199.10.9.178:8081/repository/npm-group/
|
|
1069
|
+
|
|
1070
|
+
# 如果安装失败,使用备用地址
|
|
1071
|
+
pnpm i matrix_components --registry=http://199.10.9.178:8081/repository/npm-hosted/
|
|
610
1072
|
```
|
|
611
|
-
// 统一的办公文档预览组件,根据文件URL自动选择合适的组件
|
|
612
|
-
// 支持格式:Excel(.xlsx/.xls)、PDF(.pdf)、Word(.docx/.doc)
|
|
613
1073
|
|
|
614
|
-
|
|
615
|
-
import { NsOffice } from 'matrix_components'
|
|
1074
|
+
### 2. 全局引入
|
|
616
1075
|
|
|
617
|
-
|
|
618
|
-
|
|
1076
|
+
```javascript
|
|
1077
|
+
// main.ts
|
|
1078
|
+
import { createApp } from 'vue'
|
|
1079
|
+
import App from './App.vue'
|
|
619
1080
|
|
|
620
|
-
//
|
|
621
|
-
|
|
1081
|
+
// 安装 Element-Plus
|
|
1082
|
+
import 'element-plus/dist/index.css'
|
|
1083
|
+
import ElementPlus from 'element-plus'
|
|
1084
|
+
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
|
622
1085
|
|
|
623
|
-
//
|
|
624
|
-
|
|
625
|
-
|
|
1086
|
+
// 安装组件库
|
|
1087
|
+
// @ts-ignore
|
|
1088
|
+
import NsComponents from 'matrix_components'
|
|
1089
|
+
import 'matrix_components/dist/matrix_components.css'
|
|
626
1090
|
|
|
627
|
-
|
|
628
|
-
|
|
1091
|
+
const app = createApp(App)
|
|
1092
|
+
|
|
1093
|
+
// 配置请求地址
|
|
1094
|
+
app.config.globalProperties.$BaseUrl = 'http://your-api-server/'
|
|
1095
|
+
app.config.globalProperties.$ImageBaseUrl = 'http://your-api-server/'
|
|
1096
|
+
|
|
1097
|
+
app.use(ElementPlus, {
|
|
1098
|
+
locale: zhCn,
|
|
1099
|
+
})
|
|
1100
|
+
app.use(NsComponents)
|
|
1101
|
+
|
|
1102
|
+
app.mount('#app')
|
|
1103
|
+
```
|
|
1104
|
+
|
|
1105
|
+
### 3. 按需引入
|
|
1106
|
+
|
|
1107
|
+
```javascript
|
|
1108
|
+
// 按需引入组件和函数
|
|
1109
|
+
import { NsForm, NsVideo, get, post, autoScaleInit } from 'matrix_components'
|
|
1110
|
+
|
|
1111
|
+
// 在组件中使用
|
|
1112
|
+
const app = createApp(App)
|
|
1113
|
+
app.use(NsForm)
|
|
1114
|
+
app.use(NsVideo)
|
|
1115
|
+
|
|
1116
|
+
autoScaleInit(document.querySelector('body'), {
|
|
1117
|
+
designWidth: 1920,
|
|
1118
|
+
designHeight: 920,
|
|
1119
|
+
mode: 'stretch'
|
|
1120
|
+
})
|
|
1121
|
+
```
|
|
629
1122
|
|
|
630
|
-
// 获取当前激活的组件实例
|
|
631
|
-
const activeComponent = officeRef.value?.getActiveComponent()
|
|
632
1123
|
|
|
633
|
-
// 刷新组件
|
|
634
|
-
officeRef.value?.refresh()
|
|
635
|
-
```
|