@jari-ace/element-plus-component 0.3.3 → 0.3.4
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/dist/components/upload/JaUploader.vue.d.ts +8 -0
- package/dist/components/upload/JaUploader.vue.d.ts.map +1 -1
- package/dist/components/upload/index.d.ts +12 -0
- package/dist/components/upload/index.d.ts.map +1 -1
- package/dist/components/upload/uploader.vue.d.ts +5 -0
- package/dist/components/upload/uploader.vue.d.ts.map +1 -1
- package/dist/components/upload/uploader.vue.js +14 -4
- package/dist/components/upload/uploader.vue.js.map +1 -1
- package/dist/components/userPicker/src/JaUserList.vue.d.ts +4 -0
- package/dist/components/userPicker/src/JaUserList.vue.d.ts.map +1 -1
- package/dist/components/userPicker/src/JaUserList.vue.js +9 -1
- package/dist/components/userPicker/src/JaUserList.vue.js.map +1 -1
- package/dist/components/userPicker/src/UserPicker.vue.d.ts +10 -0
- package/dist/components/userPicker/src/UserPicker.vue.d.ts.map +1 -1
- package/dist/components/userPicker/src/UserPicker.vue.js +46 -5
- package/dist/components/userPicker/src/UserPicker.vue.js.map +1 -1
- package/dist/components/userSelectDialog/src/userSelectDialog.vue.d.ts +19 -2
- package/dist/components/userSelectDialog/src/userSelectDialog.vue.d.ts.map +1 -1
- package/dist/components/userSelectDialog/src/userSelectDialog.vue.js +58 -12
- package/dist/components/userSelectDialog/src/userSelectDialog.vue.js.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.js +4334 -4243
- package/lib/index.umd.cjs +22 -17
- package/package.json +1 -1
- package/packages/components/upload/uploader.vue +68 -55
- package/packages/components/userPicker/src/JaUserList.vue +14 -2
- package/packages/components/userPicker/src/UserPicker.vue +47 -4
- package/packages/components/userSelectDialog/src/userSelectDialog.vue +44 -7
package/package.json
CHANGED
|
@@ -6,21 +6,21 @@ import {
|
|
|
6
6
|
useLoginUser,
|
|
7
7
|
type ClassificationLevel, type UploadInitParams, useLoading
|
|
8
8
|
} from "@jari-ace/app-bolts";
|
|
9
|
-
import {nextTick, onMounted, onUnmounted, ref, watch} from "vue";
|
|
10
|
-
import {ArrowDown, Download, Upload} from "@element-plus/icons-vue";
|
|
9
|
+
import { nextTick, onMounted, onUnmounted, ref, watch } from "vue";
|
|
10
|
+
import { ArrowDown, Download, Upload } from "@element-plus/icons-vue";
|
|
11
11
|
import {
|
|
12
12
|
useSystemClassificationLevelMap,
|
|
13
13
|
useSystemClassificationLevels
|
|
14
14
|
} from "../../hooks/useClassificationLevels";
|
|
15
15
|
import Ace = Jari.Ace;
|
|
16
|
-
import {ElMessageBox} from "element-plus";
|
|
16
|
+
import { ElMessageBox } from "element-plus";
|
|
17
17
|
import "@uppy/core/css/style.min.css";
|
|
18
18
|
import "@uppy/dashboard/css/style.min.css";
|
|
19
19
|
import "@uppy/audio/css/style.min.css";
|
|
20
20
|
import "@uppy/screen-capture/css/style.min.css";
|
|
21
21
|
import "@uppy/webcam/css/style.min.css";
|
|
22
22
|
import "@uppy/image-editor/css/style.min.css";
|
|
23
|
-
import Uppy, {type Meta, type UppyFile} from "@uppy/core";
|
|
23
|
+
import Uppy, { type Meta, type UppyFile } from "@uppy/core";
|
|
24
24
|
import Tus from "@uppy/tus";
|
|
25
25
|
import Webcam from "@uppy/webcam";
|
|
26
26
|
import ScreenCapture from "@uppy/screen-capture";
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
ElIcon,
|
|
42
42
|
ElTag
|
|
43
43
|
} from "element-plus";
|
|
44
|
-
import type {AceFile} from "./types";
|
|
44
|
+
import type { AceFile } from "./types";
|
|
45
45
|
|
|
46
46
|
const props = defineProps<{
|
|
47
47
|
/**
|
|
@@ -138,8 +138,14 @@ const emits = defineEmits<{
|
|
|
138
138
|
* 单个文件上传失败事件
|
|
139
139
|
*/
|
|
140
140
|
uploadError: [file: AceFile, error: Error]
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
/**
|
|
142
|
+
* 下载完成事件
|
|
143
|
+
*/
|
|
144
|
+
downloaded: [file: FileInfo]
|
|
145
|
+
/**
|
|
146
|
+
* 打包下载完成事件
|
|
147
|
+
*/
|
|
148
|
+
zipDownloaded: [file: FileInfo[]]
|
|
143
149
|
}>();
|
|
144
150
|
let uppy: Uppy | undefined;
|
|
145
151
|
curAttachToken.value = props.attachToken;
|
|
@@ -150,6 +156,13 @@ onMounted(async () => {
|
|
|
150
156
|
classificationLevels.value = await useSystemClassificationLevels();
|
|
151
157
|
classificationLevelMap.value = await useSystemClassificationLevelMap();
|
|
152
158
|
allowedClassificationLevels.value = classificationLevels.value.filter(l => l.value >= cl);
|
|
159
|
+
console.log(`附件控件密级调试:
|
|
160
|
+
表单密级:`, props.classificationLevel, `
|
|
161
|
+
用户密级:`, user.value?.classifiedLevel, `
|
|
162
|
+
表单/用户密级比较后取最低密级:`, cl, `
|
|
163
|
+
系统密级:`, classificationLevels.value, `
|
|
164
|
+
最终可选密级:`, allowedClassificationLevels.value
|
|
165
|
+
)
|
|
153
166
|
if (props.attachToken) {
|
|
154
167
|
await initLoad();
|
|
155
168
|
} else {
|
|
@@ -188,7 +201,7 @@ function createUppyInstance() {
|
|
|
188
201
|
withCredentials: true,
|
|
189
202
|
retryDelays: undefined,
|
|
190
203
|
chunkSize: !uploadInitParams.value?.chunkSize || uploadInitParams.value?.chunkSize
|
|
191
|
-
|
|
204
|
+
== 0 ? Infinity : uploadInitParams.value?.chunkSize,
|
|
192
205
|
parallelUploads: 1,
|
|
193
206
|
headers: {
|
|
194
207
|
aceAttachId: attachId.value!,
|
|
@@ -264,17 +277,17 @@ function createUppyInstance() {
|
|
|
264
277
|
emits('upload', uploadID, files);
|
|
265
278
|
}).on('progress', progress => {
|
|
266
279
|
emits('progress', progress)
|
|
267
|
-
}).on('upload-progress', file=> {
|
|
280
|
+
}).on('upload-progress', file => {
|
|
268
281
|
emits('uploadProgress', file)
|
|
269
|
-
}).on('upload-pause', (file, isPaused)=>{
|
|
282
|
+
}).on('upload-pause', (file, isPaused) => {
|
|
270
283
|
emits("uploadPause", file, isPaused)
|
|
271
284
|
}).on('upload-success', file => {
|
|
272
285
|
emits('uploadSuccess', file)
|
|
273
|
-
}).on('complete', (result)=> {
|
|
286
|
+
}).on('complete', (result) => {
|
|
274
287
|
emits('complete', result.successful, result.failed)
|
|
275
|
-
}).on('error', (error)=> {
|
|
288
|
+
}).on('error', (error) => {
|
|
276
289
|
emits('error', error)
|
|
277
|
-
}).on('upload-error', (file,error)=> {
|
|
290
|
+
}).on('upload-error', (file, error) => {
|
|
278
291
|
emits('uploadError', file, error)
|
|
279
292
|
})
|
|
280
293
|
}
|
|
@@ -292,9 +305,9 @@ async function onUploadBtnClick() {
|
|
|
292
305
|
if (dashboard) {
|
|
293
306
|
dashboard.setOptions({
|
|
294
307
|
note: (
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
308
|
+
cfg.uploadNote ? cfg.uploadNote : ""
|
|
309
|
+
)
|
|
310
|
+
+ `(正在上传${classificationLevelMap.value?.get(selectedFileClassificationLevel.value)}文件)`
|
|
298
311
|
});
|
|
299
312
|
}
|
|
300
313
|
dashboard?.openModal();
|
|
@@ -317,9 +330,9 @@ function handleClassificationLevelSelCmd(level: number) {
|
|
|
317
330
|
if (cfg) {
|
|
318
331
|
dashboard.setOptions({
|
|
319
332
|
note: (
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
333
|
+
cfg.uploadNote ? cfg.uploadNote : ""
|
|
334
|
+
)
|
|
335
|
+
+ `(正在上传${classificationLevelMap.value?.get(selectedFileClassificationLevel.value)}文件)`
|
|
323
336
|
});
|
|
324
337
|
}
|
|
325
338
|
dashboard?.openModal();
|
|
@@ -357,8 +370,11 @@ function previewFile(fileToken: string) {
|
|
|
357
370
|
pdfViewerVisible.value = true;
|
|
358
371
|
}
|
|
359
372
|
|
|
360
|
-
function downloadFile(fileToken: string) {
|
|
361
|
-
api.downloadFile(fileToken);
|
|
373
|
+
async function downloadFile(fileToken: string) {
|
|
374
|
+
await api.downloadFile(fileToken);
|
|
375
|
+
var file = files.value.filter(f => fileToken === f.token)
|
|
376
|
+
if (file && file.length > 0)
|
|
377
|
+
emits('downloaded', file[0]);
|
|
362
378
|
}
|
|
363
379
|
|
|
364
380
|
function viewUppyDashboard() {
|
|
@@ -368,11 +384,12 @@ function viewUppyDashboard() {
|
|
|
368
384
|
}
|
|
369
385
|
}
|
|
370
386
|
|
|
371
|
-
function downloadAll() {
|
|
387
|
+
async function downloadAll() {
|
|
372
388
|
if (!curAttachToken.value) {
|
|
373
389
|
return;
|
|
374
390
|
}
|
|
375
|
-
api.downloadZipFile(curAttachToken.value);
|
|
391
|
+
await api.downloadZipFile(curAttachToken.value);
|
|
392
|
+
emits('zipDownloaded', files.value);
|
|
376
393
|
}
|
|
377
394
|
|
|
378
395
|
function checkAllowUpload() {
|
|
@@ -451,42 +468,39 @@ watch(() => props.attachToken, () => {
|
|
|
451
468
|
<template>
|
|
452
469
|
<div class="ja-uploader">
|
|
453
470
|
<div class="ja-uploader-tools">
|
|
454
|
-
<el-button plain type="success" :icon="Upload" @click="onUploadBtnClick"
|
|
455
|
-
|
|
456
|
-
v-if="allowedClassificationLevels.length <= 1 && checkAllowUpload()">
|
|
471
|
+
<el-button plain type="success" :icon="Upload" @click="onUploadBtnClick" :loading="loading"
|
|
472
|
+
:disabled="loading" size="small" v-if="allowedClassificationLevels.length <= 1 && checkAllowUpload()">
|
|
457
473
|
上传{{ uploadInitParams?.fileConfig.enableClassifiedLevel ? "(非密)" : "" }}
|
|
458
474
|
</el-button>
|
|
459
|
-
<el-button plain :icon="Download" @click="downloadAll" v-if="checkAllowDownload()"
|
|
460
|
-
|
|
475
|
+
<el-button plain :icon="Download" @click="downloadAll" v-if="checkAllowDownload()" :loading="loading"
|
|
476
|
+
:disabled="loading || files?.length === 0" size="small">
|
|
461
477
|
全部下载
|
|
462
478
|
</el-button>
|
|
463
|
-
<el-dropdown v-if="allowedClassificationLevels.length > 1
|
|
464
|
-
|
|
479
|
+
<el-dropdown v-if="allowedClassificationLevels.length > 1 && checkAllowUpload()"
|
|
480
|
+
@command="handleClassificationLevelSelCmd" size="small">
|
|
465
481
|
<el-button type="success" size="small">
|
|
466
482
|
上传
|
|
467
483
|
<el-icon class="el-icon--right">
|
|
468
|
-
<arrow-down/>
|
|
484
|
+
<arrow-down />
|
|
469
485
|
</el-icon>
|
|
470
486
|
</el-button>
|
|
471
487
|
<template #dropdown>
|
|
472
488
|
<el-dropdown-menu>
|
|
473
|
-
<el-dropdown-item v-for="cl in allowedClassificationLevels"
|
|
474
|
-
|
|
475
|
-
:command="cl.value">{{ cl.label }}
|
|
489
|
+
<el-dropdown-item v-for="cl in allowedClassificationLevels" :key="cl.value"
|
|
490
|
+
:command="cl.value">{{ cl.label }}
|
|
476
491
|
</el-dropdown-item>
|
|
477
492
|
</el-dropdown-menu>
|
|
478
493
|
</template>
|
|
479
494
|
</el-dropdown>
|
|
480
|
-
<div class="container" @click="viewUppyDashboard"
|
|
481
|
-
v-if="uploadingProgress < 100 && uploadingProgress > 0">
|
|
495
|
+
<div class="container" @click="viewUppyDashboard" v-if="uploadingProgress < 100 && uploadingProgress > 0">
|
|
482
496
|
<p>
|
|
483
497
|
<span class="loader-shimmer">正在上传,已完成{{ uploadingProgress }}%...</span>
|
|
484
498
|
</p>
|
|
485
499
|
</div>
|
|
486
500
|
</div>
|
|
487
|
-
<el-table :data="files" :show-header="true" style="width: 100%" empty-text="暂无文件"
|
|
488
|
-
|
|
489
|
-
<el-table-column prop="fileName"/>
|
|
501
|
+
<el-table :data="files" :show-header="true" style="width: 100%" empty-text="暂无文件" :height="props.height"
|
|
502
|
+
:max-height="props.maxHeight">
|
|
503
|
+
<el-table-column prop="fileName" />
|
|
490
504
|
<el-table-column prop="fileSize" width="100">
|
|
491
505
|
<template #default="scope">
|
|
492
506
|
{{ prettyBytes(scope.row.fileSize) }}
|
|
@@ -495,7 +509,7 @@ watch(() => props.attachToken, () => {
|
|
|
495
509
|
<el-table-column prop="classifiedLevel" width="60">
|
|
496
510
|
<template #default="scope">
|
|
497
511
|
<el-tag
|
|
498
|
-
:type="scope.row.classifiedLevel < 50? (
|
|
512
|
+
:type="scope.row.classifiedLevel < 50 ? (scope.row.classifiedLevel < 30 ? 'danger' : 'warning') : 'info'">
|
|
499
513
|
{{ classificationLevelMap?.get(scope.row.classifiedLevel) }}
|
|
500
514
|
</el-tag>
|
|
501
515
|
</template>
|
|
@@ -503,13 +517,11 @@ watch(() => props.attachToken, () => {
|
|
|
503
517
|
<el-table-column align="right" width="150" fixed="right">
|
|
504
518
|
<template #default="scope">
|
|
505
519
|
<el-button link type="warning" @click="previewFile(scope.row.token)"
|
|
506
|
-
|
|
520
|
+
v-if="checkAllowPreview(scope.row)">预览
|
|
507
521
|
</el-button>
|
|
508
|
-
<el-button link type="primary" @click="downloadFile(scope.row.token)"
|
|
509
|
-
v-if="checkAllowDownload()">下载
|
|
522
|
+
<el-button link type="primary" @click="downloadFile(scope.row.token)" v-if="checkAllowDownload()">下载
|
|
510
523
|
</el-button>
|
|
511
|
-
<el-button link type="danger" @click="delUploadedFile(scope.row)"
|
|
512
|
-
v-if="checkAllowDelete()">删除
|
|
524
|
+
<el-button link type="danger" @click="delUploadedFile(scope.row)" v-if="checkAllowDelete()">删除
|
|
513
525
|
</el-button>
|
|
514
526
|
</template>
|
|
515
527
|
</el-table-column>
|
|
@@ -552,7 +564,8 @@ watch(() => props.attachToken, () => {
|
|
|
552
564
|
font-size: 0.9em;
|
|
553
565
|
font-weight: 500;
|
|
554
566
|
position: relative;
|
|
555
|
-
overflow: hidden;
|
|
567
|
+
overflow: hidden;
|
|
568
|
+
/* 隐藏闪光效果的溢出 */
|
|
556
569
|
vertical-align: middle;
|
|
557
570
|
}
|
|
558
571
|
|
|
@@ -560,17 +573,17 @@ watch(() => props.attachToken, () => {
|
|
|
560
573
|
content: '';
|
|
561
574
|
position: absolute;
|
|
562
575
|
top: 0;
|
|
563
|
-
left: -100%;
|
|
564
|
-
|
|
576
|
+
left: -100%;
|
|
577
|
+
/* 从左侧外部开始 */
|
|
578
|
+
width: 50%;
|
|
579
|
+
/* 闪光宽度 */
|
|
565
580
|
height: 100%;
|
|
566
581
|
|
|
567
582
|
/* 闪光效果:透明 -> 亮白色 -> 透明 */
|
|
568
|
-
background: linear-gradient(
|
|
569
|
-
90deg,
|
|
583
|
+
background: linear-gradient(90deg,
|
|
570
584
|
transparent,
|
|
571
585
|
rgba(255, 255, 255, 0.8),
|
|
572
|
-
transparent
|
|
573
|
-
);
|
|
586
|
+
transparent);
|
|
574
587
|
|
|
575
588
|
/* 动画: 1.5秒, 缓入缓出, 无限循环 */
|
|
576
589
|
animation: shimmer 1.5s ease-in-out infinite;
|
|
@@ -580,11 +593,11 @@ watch(() => props.attachToken, () => {
|
|
|
580
593
|
0% {
|
|
581
594
|
left: -100%;
|
|
582
595
|
}
|
|
596
|
+
|
|
583
597
|
100% {
|
|
584
|
-
left: 150%;
|
|
598
|
+
left: 150%;
|
|
599
|
+
/* 移动到右侧外部 */
|
|
585
600
|
}
|
|
586
601
|
}
|
|
587
602
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
603
|
</style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
|
|
3
|
-
import {ElEmpty, ElIcon, ElScrollbar, vLoading} from "element-plus";
|
|
3
|
+
import {ElEmpty, ElIcon, ElScrollbar, vLoading, ElMessage} from "element-plus";
|
|
4
4
|
import {Check} from "@element-plus/icons-vue";
|
|
5
5
|
import {JaUserInfoTag} from "../../userTag";
|
|
6
6
|
import {computed, nextTick, onUnmounted, ref, watch} from "vue";
|
|
@@ -14,7 +14,11 @@ const props = defineProps<{
|
|
|
14
14
|
pageSize: number,
|
|
15
15
|
height?: number | string,
|
|
16
16
|
loading: boolean,
|
|
17
|
-
users: UserReference[]
|
|
17
|
+
users: UserReference[],
|
|
18
|
+
/**
|
|
19
|
+
* 最多选择数量,为0则不限制
|
|
20
|
+
*/
|
|
21
|
+
maxSelect?: number
|
|
18
22
|
}>();
|
|
19
23
|
const activeIndex = ref(0);
|
|
20
24
|
const scrollbar = ref<InstanceType<typeof ElScrollbar>>();
|
|
@@ -50,6 +54,14 @@ function switchUserSelect(u: UserReference) {
|
|
|
50
54
|
}
|
|
51
55
|
const index = selectedUsers.value.findIndex(su => su.id == u.id);
|
|
52
56
|
if (index < 0) {
|
|
57
|
+
if (props.maxSelect && props.maxSelect > 0 && selectedUsers.value.length >= props.maxSelect) {
|
|
58
|
+
ElMessage({
|
|
59
|
+
message: `已超过最大选择数量 ${props.maxSelect}`,
|
|
60
|
+
plain: true,
|
|
61
|
+
type: 'warning',
|
|
62
|
+
})
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
53
65
|
selectedUsers.value.push(u);
|
|
54
66
|
} else {
|
|
55
67
|
selectedUsers.value.splice(index, 1);
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
ElButton,
|
|
4
4
|
ElIcon,
|
|
5
5
|
ElInput,
|
|
6
|
+
ElMessage,
|
|
6
7
|
ElPopover,
|
|
7
8
|
ElText,
|
|
8
9
|
ElSpace,
|
|
@@ -79,7 +80,15 @@ const props = withDefaults( defineProps<{
|
|
|
79
80
|
/**
|
|
80
81
|
* 是否显示已选用户标签
|
|
81
82
|
*/
|
|
82
|
-
showUserTag?:boolean
|
|
83
|
+
showUserTag?:boolean,
|
|
84
|
+
/**
|
|
85
|
+
* 最多选择数量,为0则不限制
|
|
86
|
+
*/
|
|
87
|
+
maxSelect?:number,
|
|
88
|
+
/**
|
|
89
|
+
* 是否禁用
|
|
90
|
+
*/
|
|
91
|
+
disabled?:boolean
|
|
83
92
|
|
|
84
93
|
}>(),{
|
|
85
94
|
trigger:'hover',
|
|
@@ -89,6 +98,8 @@ const props = withDefaults( defineProps<{
|
|
|
89
98
|
maxShowCount: 20,
|
|
90
99
|
maxHeight: '100%',
|
|
91
100
|
showUserTag: true,
|
|
101
|
+
maxSelect: 0,
|
|
102
|
+
disabled: false,
|
|
92
103
|
})
|
|
93
104
|
|
|
94
105
|
// const props = defineProps({
|
|
@@ -183,6 +194,14 @@ function switchUserSelect(u: UserReference) {
|
|
|
183
194
|
}
|
|
184
195
|
const index = selectedUsers.value.findIndex(su => su.id == u.id);
|
|
185
196
|
if (index < 0) {
|
|
197
|
+
if (props.maxSelect > 0 && selectedUsers.value.length >= props.maxSelect) {
|
|
198
|
+
ElMessage({
|
|
199
|
+
message: `已超过最大选择数量 ${props.maxSelect}`,
|
|
200
|
+
plain: true,
|
|
201
|
+
type: 'warning',
|
|
202
|
+
})
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
186
205
|
selectedUsers.value.push(u);
|
|
187
206
|
} else {
|
|
188
207
|
selectedUsers.value.splice(index, 1);
|
|
@@ -230,6 +249,9 @@ function onSaveToCustomGroupClick() {
|
|
|
230
249
|
}
|
|
231
250
|
|
|
232
251
|
function onDeselected(uid?: string) {
|
|
252
|
+
if (props.disabled) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
233
255
|
if (Array.isArray(selectedUsers.value)) {
|
|
234
256
|
const index = selectedUsers.value.findIndex(su => su.id == uid);
|
|
235
257
|
if (index >= 0) {
|
|
@@ -255,6 +277,9 @@ function onInputKeyEnter() {
|
|
|
255
277
|
}
|
|
256
278
|
|
|
257
279
|
function popup() {
|
|
280
|
+
if (props.disabled) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
258
283
|
popoverVisible.value = true;
|
|
259
284
|
}
|
|
260
285
|
|
|
@@ -262,7 +287,15 @@ function selectAll() {
|
|
|
262
287
|
const arr = (
|
|
263
288
|
selectedUsers.value as UserReference[]
|
|
264
289
|
);
|
|
265
|
-
|
|
290
|
+
const availableUsers = users.value.filter(u => !arr.some(su => su.id === u.id));
|
|
291
|
+
if (props.maxSelect > 0) {
|
|
292
|
+
const remaining = props.maxSelect - arr.length;
|
|
293
|
+
if (remaining > 0) {
|
|
294
|
+
arr.push(...availableUsers.slice(0, remaining));
|
|
295
|
+
}
|
|
296
|
+
} else {
|
|
297
|
+
arr.push(...availableUsers);
|
|
298
|
+
}
|
|
266
299
|
}
|
|
267
300
|
|
|
268
301
|
function clearSelection() {
|
|
@@ -292,11 +325,17 @@ const selectedForBinding = computed(() => {
|
|
|
292
325
|
})
|
|
293
326
|
|
|
294
327
|
function showUserSelectDialog() {
|
|
328
|
+
if (props.disabled) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
295
331
|
dialogUserSelector.value?.show();
|
|
296
332
|
popoverVisible.value = false;
|
|
297
333
|
}
|
|
298
334
|
|
|
299
335
|
function handleMouseOver() {
|
|
336
|
+
if (props.disabled) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
300
339
|
popoverVisible.value = true
|
|
301
340
|
}
|
|
302
341
|
|
|
@@ -314,12 +353,13 @@ watch(()=>props.classificationLevel, ()=>{
|
|
|
314
353
|
<template>
|
|
315
354
|
<ja-scrollbar :max-height="props.maxHeight" :height="props.height" v-bind="$attrs"
|
|
316
355
|
style="overflow-x: hidden;">
|
|
317
|
-
<div class="ja-user-picker__root" v-shortcut:[props.shortcut]="popup">
|
|
356
|
+
<div class="ja-user-picker__root" v-shortcut:[props.shortcut]="!props.disabled ? popup : undefined">
|
|
318
357
|
|
|
319
358
|
<el-popover ref="bookmarkDropdown" @show="onPopoverShow" @hide="onPopoverHide"
|
|
320
359
|
v-model:visible="popoverVisible"
|
|
321
360
|
width="auto" teleported
|
|
322
361
|
:trigger="props.trigger"
|
|
362
|
+
:disabled="props.disabled"
|
|
323
363
|
>
|
|
324
364
|
<template #reference>
|
|
325
365
|
<div style="display: flex;align-items: center;">
|
|
@@ -327,6 +367,7 @@ watch(()=>props.classificationLevel, ()=>{
|
|
|
327
367
|
v-if="$slots.default"
|
|
328
368
|
name="default"></slot>
|
|
329
369
|
<el-button v-else circle :icon="Plus" :size="'small'" ref="btn"
|
|
370
|
+
:disabled="props.disabled"
|
|
330
371
|
@mouseover="handleMouseOver">
|
|
331
372
|
</el-button>
|
|
332
373
|
</div>
|
|
@@ -394,6 +435,7 @@ watch(()=>props.classificationLevel, ()=>{
|
|
|
394
435
|
v-model="selectedUsers"
|
|
395
436
|
v-model:page="pageParams.currentPage"
|
|
396
437
|
:multiple="props.multiple"
|
|
438
|
+
:maxSelect="props.maxSelect"
|
|
397
439
|
@item-clicked="onArrowKeyDown"
|
|
398
440
|
@arrow-key-down="onArrowKeyDown"></ja-user-list>
|
|
399
441
|
</div>
|
|
@@ -401,7 +443,7 @@ watch(()=>props.classificationLevel, ()=>{
|
|
|
401
443
|
</el-popover>
|
|
402
444
|
<div v-if="props.showUserTag" class="ja-user-picker__tag-container">
|
|
403
445
|
<ja-user-info-tag v-for="u in selectedUsersForRender" :key="u.id" :user-id="u.id"
|
|
404
|
-
:full-name="u.fullName" closable :has-avatar="u.hasAvatar"
|
|
446
|
+
:full-name="u.fullName" :closable="!props.disabled" :has-avatar="u.hasAvatar"
|
|
405
447
|
@closed="onDeselected">
|
|
406
448
|
</ja-user-info-tag>
|
|
407
449
|
<div class="more-tag" v-if="selectedForBinding.length > props.maxShowCount">
|
|
@@ -417,6 +459,7 @@ watch(()=>props.classificationLevel, ()=>{
|
|
|
417
459
|
:realm-id="localRealmId"
|
|
418
460
|
:classificationLevel="props.classificationLevel"
|
|
419
461
|
:customFilter="props.customFilter"
|
|
462
|
+
:maxSelect="props.maxSelect"
|
|
420
463
|
v-model="selectedUsers"></ja-user-select-dialog>
|
|
421
464
|
</div>
|
|
422
465
|
</ja-scrollbar>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
ElDialog,
|
|
4
4
|
ElIcon,
|
|
5
|
+
ElMessage,
|
|
5
6
|
ElTableV2,
|
|
6
7
|
ElText,
|
|
7
8
|
ElTabs,
|
|
@@ -51,14 +52,18 @@ const props = defineProps({
|
|
|
51
52
|
/**
|
|
52
53
|
* 密级过滤
|
|
53
54
|
*/
|
|
54
|
-
classificationLevel: {type: Number, required: false, default:
|
|
55
|
+
classificationLevel: {type: Number, required: false, default: 0},
|
|
55
56
|
/**
|
|
56
57
|
* 自定义筛选过滤条件,可以在此回调方法内使用qUser参数构造自定义的查询条件。例如 qUser => qUser.fullName.startWith('王')
|
|
57
58
|
*/
|
|
58
59
|
customFilter: {
|
|
59
60
|
type: Function as PropType<(qUser: InstanceType<typeof QUser>) => BooleanResultExpression>,
|
|
60
61
|
required: false
|
|
61
|
-
}
|
|
62
|
+
},
|
|
63
|
+
/**
|
|
64
|
+
* 最多选择数量,为0则不限制
|
|
65
|
+
*/
|
|
66
|
+
maxSelect: {type: Number, required: false, default: 0}
|
|
62
67
|
})
|
|
63
68
|
const selectedUsers = defineModel<UserReference[] | UserReference | null>({
|
|
64
69
|
required: true
|
|
@@ -212,6 +217,14 @@ function switchUserSelect(user: UserReference) {
|
|
|
212
217
|
map.delete(user.id);
|
|
213
218
|
tempSel.value.splice(index, 1);
|
|
214
219
|
} else {
|
|
220
|
+
if (props.maxSelect > 0 && tempSel.value.length >= props.maxSelect) {
|
|
221
|
+
ElMessage({
|
|
222
|
+
message: `已超过最大选择数量 ${props.maxSelect}`,
|
|
223
|
+
type: 'warning',
|
|
224
|
+
plain: true,
|
|
225
|
+
})
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
215
228
|
map.set(user.id, user)
|
|
216
229
|
tempSel.value.push(user);
|
|
217
230
|
}
|
|
@@ -231,8 +244,17 @@ onUnmounted(() => {
|
|
|
231
244
|
function selectAll() {
|
|
232
245
|
if (Array.isArray(tempSel.value)) {
|
|
233
246
|
const users = userQuery.queryResult.value.users.filter(u => !userSelected(u));
|
|
234
|
-
|
|
235
|
-
|
|
247
|
+
if (props.maxSelect > 0) {
|
|
248
|
+
const remaining = props.maxSelect - tempSel.value.length;
|
|
249
|
+
if (remaining > 0) {
|
|
250
|
+
const usersToAdd = users.slice(0, remaining);
|
|
251
|
+
usersToAdd.forEach(u => map.set(u.id, u))
|
|
252
|
+
tempSel.value.push(...usersToAdd);
|
|
253
|
+
}
|
|
254
|
+
} else {
|
|
255
|
+
users.forEach(u => map.set(u.id, u))
|
|
256
|
+
tempSel.value.push(...users);
|
|
257
|
+
}
|
|
236
258
|
}
|
|
237
259
|
}
|
|
238
260
|
|
|
@@ -247,13 +269,28 @@ function inverseSelection() {
|
|
|
247
269
|
if (Array.isArray(tempSel.value)) {
|
|
248
270
|
const users = userQuery.queryResult.value.users.filter(u => !userSelected(u))
|
|
249
271
|
map.clear();
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
272
|
+
if (props.maxSelect > 0) {
|
|
273
|
+
const usersToAdd = users.slice(0, props.maxSelect);
|
|
274
|
+
usersToAdd.forEach(u => map.set(u.id, u))
|
|
275
|
+
tempSel.value.splice(0);
|
|
276
|
+
tempSel.value.push(...usersToAdd);
|
|
277
|
+
} else {
|
|
278
|
+
users.forEach(u => map.set(u.id, u))
|
|
279
|
+
tempSel.value.splice(0);
|
|
280
|
+
tempSel.value.push(...users);
|
|
281
|
+
}
|
|
253
282
|
}
|
|
254
283
|
}
|
|
255
284
|
|
|
256
285
|
function onConfirm() {
|
|
286
|
+
if (props.multiple && Array.isArray(tempSel.value) && props.maxSelect > 0 && tempSel.value.length > props.maxSelect) {
|
|
287
|
+
ElMessage({
|
|
288
|
+
message: `已超过最大选择数量 ${props.maxSelect}`,
|
|
289
|
+
type: 'warning',
|
|
290
|
+
plain: true,
|
|
291
|
+
})
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
257
294
|
selectedUsers.value = tempSel.value;
|
|
258
295
|
visible.value = false;
|
|
259
296
|
}
|