matrix_components 2.0.305 → 2.0.307

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 CHANGED
@@ -1,4 +1,12 @@
1
1
  # **组件库2.0**
2
+ 组件使用示例参考dist/ComponentDemo
3
+ ```
4
+ version:2.0.307
5
+ 2025年10月23日11:21:46
6
+ 更新日志:
7
+ 1.增加Demo示例目录:组件使用示例在dist/ComponentDemo
8
+ ```
9
+
2
10
 
3
11
  ```
4
12
  version:2.0.305
@@ -1,79 +1,347 @@
1
1
  <template>
2
2
  <div style="padding: 20px;">
3
- <h2>测试 el-autocomplete 和 el-input 的 v-length 指令</h2>
4
-
5
- <div style="margin-bottom: 20px;">
6
- <h3>el-autocomplete (限制2个字符)</h3>
7
- <el-autocomplete
8
- ref="autocompleteRef"
9
- v-model="userName"
10
- v-length="2"
11
- :fetch-suggestions="querySearch"
12
- placeholder="请输入用户名"
13
- style="width: 300px;"
14
- />
15
- <p>当前值: "{{ userName }}" (长度: {{ userName.length }})</p>
16
- <button @click="checkDOM">检查 DOM 结构</button>
3
+ <h1>自定义指令演示 Demo</h1>
4
+
5
+ <!-- v-sline 指令演示 -->
6
+ <div class="demo-section">
7
+ <h2>1. v-sline 指令 - 单行文本溢出省略</h2>
8
+ <div style="width: 200px; border: 1px solid #ccc; padding: 10px;">
9
+ <p v-sline>这是一段很长很长很长很长很长很长的文本,用来测试单行省略效果</p>
10
+ </div>
11
+ <div style="width: 200px; border: 1px solid #ccc; padding: 10px; margin-top: 10px;">
12
+ <span v-sline>{{ longText }}</span>
13
+ </div>
14
+ </div>
15
+
16
+ <!-- v-length 指令演示 -->
17
+ <div class="demo-section">
18
+ <h2>2. v-length 指令 - 输入长度限制</h2>
19
+
20
+ <h3>基础用法 - 限制字符长度</h3>
21
+ <div class="input-group">
22
+ <label>限制5个字符:</label>
23
+ <el-input v-model="basicInput" v-length="5" placeholder="最多输入5个字符" style="width: 300px;" />
24
+ <span>当前: "{{ basicInput }}" ({{ basicInput.length }}/5)</span>
25
+ </div>
26
+
27
+ <h3>数字模式 - v-length.number</h3>
28
+ <div class="input-group">
29
+ <label>仅数字,限制8位:</label>
30
+ <el-input v-model="numberInput" v-length.number="8" placeholder="仅能输入数字,最多8位" style="width: 300px;" />
31
+ <span>当前: "{{ numberInput }}" ({{ numberInput.length }}/8)</span>
32
+ </div>
33
+
34
+ <h3>正则模式 - v-length.regex</h3>
35
+ <div class="input-group">
36
+ <label>字母数字,限制6位:</label>
37
+ <el-input
38
+ v-model="regexInput"
39
+ v-length.regex="{ maxLength: 6, pattern: /^[a-zA-Z0-9]*$/ }"
40
+ placeholder="仅字母数字,最多6位"
41
+ style="width: 300px;"
42
+ />
43
+ <span>当前: "{{ regexInput }}" ({{ regexInput.length }}/6)</span>
44
+ </div>
17
45
  </div>
18
-
19
- <div style="margin-bottom: 20px;">
20
- <h3>el-input (限制2个字符)</h3>
21
- <el-input
22
- v-model="xxx"
23
- v-length="2"
24
- placeholder="请输入内容"
25
- style="width: 300px;"
26
- />
27
- <p>当前值: "{{ xxx }}" (长度: {{ xxx.length }})</p>
46
+
47
+ <!-- v-permission 指令演示 -->
48
+ <div class="demo-section">
49
+ <h2>3. v-permission 指令 - 按钮权限控制</h2>
50
+ <p>当前权限列表: {{ btnsPermission.join(', ') }}</p>
51
+
52
+ <h3>ID 权限控制 (默认模式)</h3>
53
+ <div class="button-group">
54
+ <el-button id="add_btn" v-permission type="primary">添加按钮 (有权限)</el-button>
55
+ <el-button id="edit_btn" v-permission type="success">编辑按钮 (有权限)</el-button>
56
+ <el-button id="delete_btn" v-permission type="danger">删除按钮 (无权限-隐藏)</el-button>
57
+ <el-button id="view_btn" v-permission type="info">查看按钮 (无权限-隐藏)</el-button>
58
+ </div>
59
+
60
+ <h3>ID 权限控制 (display模式)</h3>
61
+ <div class="button-group">
62
+ <el-button id="export_btn" v-permission.id.display type="warning">导出按钮 (无权限-display:none)</el-button>
63
+ <el-button id="import_btn" v-permission.id.display type="primary">导入按钮 (无权限-display:none)</el-button>
64
+ </div>
65
+
66
+ <h3>Class 权限控制</h3>
67
+ <div class="button-group">
68
+ <el-button class="admin-btn" v-permission.class type="primary">管理员按钮 (有权限)</el-button>
69
+ <el-button class="super-admin" v-permission.class type="danger">超级管理员 (无权限)</el-button>
70
+ </div>
71
+
72
+ <div style="margin-top: 10px;">
73
+ <el-button @click="togglePermission" type="primary">切换权限</el-button>
74
+ </div>
75
+ </div>
76
+
77
+ <!-- v-event-unuse 和 v-event-use 指令演示 -->
78
+ <div class="demo-section">
79
+ <h2>4. v-event-unuse / v-event-use 指令 - 事件穿透控制</h2>
80
+
81
+ <div class="event-demo-container" v-event-unuse @click="parentClick">
82
+ <p>父容器 (v-event-unuse) - 点击事件被禁用</p>
83
+ <div class="child-container" v-event-use @click="childClick">
84
+ <p>子容器 (v-event-use) - 点击事件可用</p>
85
+ <el-button type="primary">可点击的按钮</el-button>
86
+ </div>
87
+ <el-button type="danger">不可点击的按钮</el-button>
88
+ </div>
89
+
90
+ <p>点击结果: {{ eventResult }}</p>
28
91
  </div>
29
-
30
- <div style="margin-bottom: 20px;">
31
- <h3>原生 input (限制2个字符)</h3>
32
- <input
33
- v-model="nativeInput"
34
- v-length="2"
35
- placeholder="请输入内容"
36
- style="width: 300px; padding: 8px; border: 1px solid #dcdfe6; border-radius: 4px;"
37
- />
38
- <p>当前值: "{{ nativeInput }}" (长度: {{ nativeInput.length }})</p>
92
+
93
+ <!-- 综合演示 -->
94
+ <div class="demo-section">
95
+ <h2>5. 综合演示</h2>
96
+ <div class="comprehensive-demo">
97
+ <div class="form-item">
98
+ <label>用户名 (字母数字,最多8位):</label>
99
+ <el-input
100
+ v-model="username"
101
+ v-length.regex="{ maxLength: 8, pattern: /^[a-zA-Z0-9]*$/ }"
102
+ placeholder="用户名"
103
+ style="width: 200px;"
104
+ />
105
+ </div>
106
+
107
+ <div class="form-item">
108
+ <label>年龄 (数字,最多3位):</label>
109
+ <el-input
110
+ v-model="age"
111
+ v-length.number="3"
112
+ placeholder="年龄"
113
+ style="width: 200px;"
114
+ />
115
+ </div>
116
+
117
+ <div class="form-item">
118
+ <label>描述 (最多50字符):</label>
119
+ <el-input
120
+ v-model="description"
121
+ v-length="50"
122
+ type="textarea"
123
+ placeholder="个人描述"
124
+ style="width: 300px;"
125
+ />
126
+ </div>
127
+
128
+ <div class="form-item">
129
+ <label>长文本展示:</label>
130
+ <div style="width: 200px; border: 1px solid #ddd; padding: 8px;">
131
+ <span v-sline>{{ description || '这里会显示你输入的描述,如果太长会自动省略...' }}</span>
132
+ </div>
133
+ </div>
134
+
135
+ <div class="form-item">
136
+ <el-button id="save_btn" v-permission type="primary">保存 (需要权限)</el-button>
137
+ <el-button @click="clearForm" type="default">清空</el-button>
138
+ </div>
139
+ </div>
39
140
  </div>
40
-
41
- <div id="dom-info" style="margin-top: 20px; padding: 10px; background: #f5f5f5;"></div>
42
141
  </div>
43
142
  </template>
44
143
  <script setup lang="ts">
45
- import { ref } from 'vue'
144
+ import { ref, provide } from 'vue'
145
+
146
+ // v-sline 演示数据
147
+ const longText = ref('这是一个非常非常非常长的文本内容,用来演示v-sline指令的单行省略效果,当文本超出容器宽度时会自动显示省略号')
46
148
 
47
- const userName = ref('')
48
- const xxx = ref('')
149
+ // v-length 演示数据
150
+ const basicInput = ref('')
49
151
  const nativeInput = ref('')
50
- const autocompleteRef = ref(null)
152
+ const numberInput = ref('')
153
+ const regexInput = ref('')
154
+ const chineseInput = ref('')
155
+ const autocompleteInput = ref('')
51
156
 
52
- function querySearch(queryString, cb) {
157
+ // v-permission 演示数据
158
+ const btnsPermission = ref(JSON.parse(sessionStorage.getItem('btnsPermission')) || ['add_btn', 'edit_btn', 'admin-btn'])
159
+ sessionStorage.setItem('btnsPermission', JSON.stringify(btnsPermission.value))
160
+ // v-event 演示数据
161
+ const eventResult = ref('暂无点击')
162
+
163
+ // 综合演示数据
164
+ const username = ref('')
165
+ const age = ref('')
166
+ const description = ref('')
167
+ // 自动完成搜索函数
168
+ function querySearch(queryString: string, cb: (results: Array<{ value: string }>) => void) {
53
169
  const results = queryString
54
- ? [{ value: '测试1' }, { value: '测试2' }, { value: '测试3' }, { value: '测试4' }, { value: '测试5' }].filter(item => item.value.includes(queryString))
170
+ ? [
171
+ { value: '测试用户1' },
172
+ { value: '测试用户2' },
173
+ { value: '管理员' },
174
+ { value: '普通用户' },
175
+ { value: '访客' }
176
+ ].filter(item => item.value.includes(queryString))
55
177
  : []
56
178
  cb(results)
57
179
  }
58
180
 
59
- function checkDOM() {
60
- const autocompleteElement = autocompleteRef.value.$el;
61
- const domInfo = document.getElementById('dom-info');
62
-
63
- // 显示 el-autocomplete 的 DOM 结构
64
- let html = '<h4>el-autocomplete DOM 结构:</h4>';
65
- html += '<pre>' + autocompleteElement.outerHTML.replace(/</g, '&lt;').replace(/>/g, '&gt;') + '</pre>';
66
-
67
- // 查找所有 input 元素
68
- const inputs = autocompleteElement.querySelectorAll('input');
69
- html += '<h4>找到的 input 元素:</h4>';
70
- html += '<p>数量: ' + inputs.length + '</p>';
71
-
72
- inputs.forEach((input, index) => {
73
- html += '<p>Input ' + index + ': ' + input.tagName + ' (type: ' + input.type + ')</p>';
74
- });
75
-
76
- domInfo.innerHTML = html;
181
+ // 权限切换函数 - 修复无限递归问题
182
+ function togglePermission() {
183
+ if (btnsPermission.value.includes('delete_btn')) {
184
+ // 移除权限
185
+ btnsPermission.value = btnsPermission.value.filter(item =>
186
+ !['delete_btn', 'save_btn', 'view_btn', 'export_btn', 'import_btn'].includes(item)
187
+ )
188
+ eventResult.value = '权限已移除,页面将在1秒后刷新以应用更改'
189
+ } else {
190
+ // 添加权限
191
+ const newPermissions = ['delete_btn', 'save_btn', 'view_btn', 'export_btn', 'import_btn']
192
+ newPermissions.forEach(permission => {
193
+ if (!btnsPermission.value.includes(permission)) {
194
+ btnsPermission.value.push(permission)
195
+ }
196
+ })
197
+ eventResult.value = '权限已添加,页面将在1秒后刷新以应用更改'
198
+ }
199
+ sessionStorage.setItem('btnsPermission', JSON.stringify(btnsPermission.value))
200
+ // 延迟刷新页面以应用权限变更
201
+ setTimeout(() => {
202
+ window.location.reload()
203
+ }, 1000)
204
+ }
205
+
206
+ // 事件演示函数
207
+ function parentClick() {
208
+ eventResult.value = '父容器被点击了 - 这不应该发生,因为使用了v-event-unuse'
209
+ }
210
+
211
+ function childClick(event: Event) {
212
+ event.stopPropagation()
213
+ eventResult.value = '子容器被点击了 - v-event-use生效'
214
+ }
215
+
216
+ // 清空表单
217
+ function clearForm() {
218
+ username.value = ''
219
+ age.value = ''
220
+ description.value = ''
221
+ basicInput.value = ''
222
+ nativeInput.value = ''
223
+ numberInput.value = ''
224
+ regexInput.value = ''
225
+ chineseInput.value = ''
226
+ autocompleteInput.value = ''
227
+ eventResult.value = '表单已清空'
77
228
  }
78
229
  </script>
79
- <style scoped></style>
230
+ <style scoped>
231
+ .demo-section {
232
+ margin-bottom: 40px;
233
+ padding: 20px;
234
+ border: 1px solid #e4e7ed;
235
+ border-radius: 8px;
236
+ background-color: #fafafa;
237
+ }
238
+
239
+ .demo-section h2 {
240
+ color: #409eff;
241
+ margin-bottom: 20px;
242
+ border-bottom: 2px solid #409eff;
243
+ padding-bottom: 10px;
244
+ }
245
+
246
+ .demo-section h3 {
247
+ color: #606266;
248
+ margin: 20px 0 10px 0;
249
+ font-size: 16px;
250
+ }
251
+
252
+ .input-group {
253
+ display: flex;
254
+ align-items: center;
255
+ margin-bottom: 15px;
256
+ gap: 10px;
257
+ }
258
+
259
+ .input-group label {
260
+ min-width: 150px;
261
+ font-weight: 500;
262
+ color: #606266;
263
+ }
264
+
265
+ .input-group span {
266
+ color: #909399;
267
+ font-size: 14px;
268
+ }
269
+
270
+ .native-input {
271
+ width: 300px;
272
+ padding: 8px 12px;
273
+ border: 1px solid #dcdfe6;
274
+ border-radius: 4px;
275
+ font-size: 14px;
276
+ transition: border-color 0.2s;
277
+ }
278
+
279
+ .native-input:focus {
280
+ outline: none;
281
+ border-color: #409eff;
282
+ }
283
+
284
+ .button-group {
285
+ display: flex;
286
+ gap: 10px;
287
+ margin-bottom: 15px;
288
+ flex-wrap: wrap;
289
+ }
290
+
291
+ .event-demo-container {
292
+ border: 2px solid #f56c6c;
293
+ padding: 20px;
294
+ margin: 20px 0;
295
+ border-radius: 8px;
296
+ background-color: #fef0f0;
297
+ cursor: pointer;
298
+ }
299
+
300
+ .child-container {
301
+ border: 2px solid #67c23a;
302
+ padding: 15px;
303
+ margin: 10px 0;
304
+ border-radius: 6px;
305
+ background-color: #f0f9ff;
306
+ cursor: pointer;
307
+ }
308
+
309
+ .comprehensive-demo {
310
+ background-color: #fff;
311
+ padding: 20px;
312
+ border-radius: 8px;
313
+ border: 1px solid #e4e7ed;
314
+ }
315
+
316
+ .form-item {
317
+ display: flex;
318
+ align-items: center;
319
+ margin-bottom: 20px;
320
+ gap: 15px;
321
+ }
322
+
323
+ .form-item label {
324
+ min-width: 200px;
325
+ font-weight: 500;
326
+ color: #606266;
327
+ }
328
+
329
+ /* 响应式设计 */
330
+ @media (max-width: 768px) {
331
+ .input-group,
332
+ .form-item {
333
+ flex-direction: column;
334
+ align-items: flex-start;
335
+ }
336
+
337
+ .input-group label,
338
+ .form-item label {
339
+ min-width: auto;
340
+ margin-bottom: 5px;
341
+ }
342
+
343
+ .button-group {
344
+ flex-direction: column;
345
+ }
346
+ }
347
+ </style>
@@ -24,14 +24,14 @@ const videoData = reactive({
24
24
  {
25
25
  videoModel: 'easyplayer',
26
26
  id: '111',
27
- label: '视频A--1视频A--1视频A--1视频A--1视频A--1视频A--1视频A--1视频A--1视频A--1视频A--1视频A--1视频A--1视频A--1视频A--1视频A--1视频A--1',
28
- url: 'ws://199.10.9.192:30200/rtp/34020000001110000001_34020000001320000015.live.flv',
27
+ label: '视频A--1视频A--1视频A--1',
28
+ url: 'http://199.10.9.192:30200/rtp/34020000001110000001_34020000001320000001/hls.m3u8',
29
29
  deviceId: 'a1',
30
30
  channelId: 'a11',
31
31
  icontype: 'on',
32
32
  },
33
33
  {
34
- id: '222',
34
+ id: 'D',
35
35
  label: '视频A--2',
36
36
  url: 'ws://199.10.9.192:30200/rtp/34020000001110000001_34020000001320000013.live.flv',
37
37
  deviceId: 'b1',
@@ -95,7 +95,7 @@ const videoData = reactive({
95
95
  // 获取、设置打开的播放视频信息
96
96
  videoInfos: [
97
97
  {
98
- index: 3,
98
+ index: 0,
99
99
  url: 'ws://199.10.9.192:30200/rtp/34020000001110000001_34020000001320000001.live.flv',
100
100
  info: {
101
101
  videoModel: 'easyplayer',
@@ -105,6 +105,39 @@ const videoData = reactive({
105
105
  channelId: 'c11',
106
106
  },
107
107
  },
108
+ {
109
+ index: 1,
110
+ url: 'ws://199.10.9.192:30200/rtp/34020000001110000001_34020000001320000015.live.flv',
111
+ info: {
112
+ videoModel: 'easyplayer',
113
+ id: '222',
114
+ url: 'ws://199.10.9.192:30200/rtp/34020000001110000001_34020000001320000015.live.flv',
115
+ deviceId: 'c2',
116
+ channelId: 'c11',
117
+ },
118
+ },
119
+ {
120
+ index: 2,
121
+ url: 'ws://199.10.9.192:30200/rtp/34020000001110000001_34020000001320000009.live.flv',
122
+ info: {
123
+ videoModel: 'easyplayer',
124
+ id: 'xxx2',
125
+ url: 'ws://199.10.9.192:30200/rtp/34020000001110000001_34020000001320000009.live.flv',
126
+ deviceId: 'c3',
127
+ channelId: 'c11',
128
+ },
129
+ },
130
+ {
131
+ index: 3,
132
+ url: 'ws://199.10.9.192:30200/rtp/34020000001110000001_34020000001320000008.live.flv',
133
+ info: {
134
+ videoModel: 'easyplayer',
135
+ id: 'b3',
136
+ url: 'ws://199.10.9.192:30200/rtp/34020000001110000001_34020000001320000008.live.flv',
137
+ deviceId: 'c4',
138
+ channelId: 'c11',
139
+ },
140
+ },
108
141
  ],
109
142
  // !!! 单点播放
110
143
  videoSingleUrl: false,
@@ -7239,10 +7239,30 @@ function registerDirective(app2) {
7239
7239
  });
7240
7240
  app2.directive("permission", {
7241
7241
  mounted(el, binding) {
7242
- var _a2, _b, _c;
7243
- const btnsPermission = inject("btnsPermission") || [];
7244
- const selector = ((_a2 = binding.modifiers) == null ? void 0 : _a2["class"]) ? "class" : ((_b = binding.modifiers) == null ? void 0 : _b["id"]) ? "id" : "id";
7245
- const isDisplayNone = (_c = binding.modifiers) == null ? void 0 : _c["display"];
7242
+ var _a2, _b, _c, _d, _e, _f;
7243
+ let btnsPermission = [];
7244
+ try {
7245
+ if (sessionStorage.getItem("btnsPermission")) {
7246
+ Array.isArray(JSON.parse(sessionStorage.getItem("btnsPermission"))) ? btnsPermission = JSON.parse(sessionStorage.getItem("btnsPermission")) : null;
7247
+ } else if (localStorage.getItem("btnsPermission")) {
7248
+ Array.isArray(JSON.parse(localStorage.getItem("btnsPermission"))) ? btnsPermission = JSON.parse(localStorage.getItem("btnsPermission")) : null;
7249
+ }
7250
+ } catch (e) {
7251
+ btnsPermission = [];
7252
+ }
7253
+ if (btnsPermission.length === 0) {
7254
+ if (app2.config.globalProperties.$btnsPermission) {
7255
+ btnsPermission = app2.config.globalProperties.$btnsPermission;
7256
+ } else if (binding.instance && binding.instance.$.appContext.app.config.globalProperties.$btnsPermission) {
7257
+ btnsPermission = binding.instance.$.appContext.app.config.globalProperties.$btnsPermission;
7258
+ } else if (binding.instance && ((_a2 = binding.instance.$.provides) == null ? void 0 : _a2.btnsPermission)) {
7259
+ btnsPermission = binding.instance.$.provides.btnsPermission;
7260
+ } else if (binding.instance && ((_c = (_b = binding.instance.$.parent) == null ? void 0 : _b.provides) == null ? void 0 : _c.btnsPermission)) {
7261
+ btnsPermission = binding.instance.$.parent.provides.btnsPermission;
7262
+ }
7263
+ }
7264
+ const selector = ((_d = binding.modifiers) == null ? void 0 : _d["class"]) ? "class" : ((_e = binding.modifiers) == null ? void 0 : _e["id"]) ? "id" : "id";
7265
+ const isDisplayNone = (_f = binding.modifiers) == null ? void 0 : _f["display"];
7246
7266
  if (selector === "id") {
7247
7267
  if (!(btnsPermission == null ? void 0 : btnsPermission.includes(el.getAttribute(selector)))) {
7248
7268
  if (isDisplayNone) {