@jari-ace/element-plus-component 0.3.2 → 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.
Files changed (159) hide show
  1. package/dist/components/autoComplete/JaAutoComplete.vue.d.ts +956 -1179
  2. package/dist/components/autoComplete/JaAutoComplete.vue.d.ts.map +1 -1
  3. package/dist/components/button/JaButton.vue.d.ts +114 -450
  4. package/dist/components/button/JaButton.vue.d.ts.map +1 -1
  5. package/dist/components/checkbox/JaCheckbox.vue.d.ts +228 -150
  6. package/dist/components/checkbox/JaCheckbox.vue.d.ts.map +1 -1
  7. package/dist/components/checkboxGroup/JaCheckboxGroup.vue.d.ts +215 -137
  8. package/dist/components/checkboxGroup/JaCheckboxGroup.vue.d.ts.map +1 -1
  9. package/dist/components/dropdownButton/JaDropdownButton.vue.d.ts +700 -1596
  10. package/dist/components/dropdownButton/JaDropdownButton.vue.d.ts.map +1 -1
  11. package/dist/components/form/JaForm.vue.d.ts +1 -1
  12. package/dist/components/formItem/JaFormItem.vue.d.ts +83 -293
  13. package/dist/components/formItem/JaFormItem.vue.d.ts.map +1 -1
  14. package/dist/components/input/JaInput.vue.d.ts +244 -609
  15. package/dist/components/input/JaInput.vue.d.ts.map +1 -1
  16. package/dist/components/inputI18n/I18nBundleEditor.vue.d.ts +1 -1
  17. package/dist/components/inputI18n/I18nBundleEditor.vue.d.ts.map +1 -1
  18. package/dist/components/inputI18n/I18nBundleEditor.vue.js +1 -1
  19. package/dist/components/inputI18n/I18nBundleEditor.vue.js.map +1 -1
  20. package/dist/components/inputI18n/InputI18n.vue.d.ts.map +1 -1
  21. package/dist/components/inputI18n/InputI18n.vue.js +14 -5
  22. package/dist/components/inputI18n/InputI18n.vue.js.map +1 -1
  23. package/dist/components/inputNumber/JaInputNumber.vue.d.ts +117 -471
  24. package/dist/components/inputNumber/JaInputNumber.vue.d.ts.map +1 -1
  25. package/dist/components/inputNumber/JaInputNumber.vue.js +4 -1
  26. package/dist/components/inputNumber/JaInputNumber.vue.js.map +1 -1
  27. package/dist/components/properyPicker/PropertyPicker.vue.d.ts.map +1 -1
  28. package/dist/components/properyPicker/PropertyPicker.vue.js +4 -8
  29. package/dist/components/properyPicker/PropertyPicker.vue.js.map +1 -1
  30. package/dist/components/radioGroup/JaRadioGroup.vue.d.ts +96 -287
  31. package/dist/components/radioGroup/JaRadioGroup.vue.d.ts.map +1 -1
  32. package/dist/components/rolePicker/RoleCategorySelector.vue.d.ts +14 -0
  33. package/dist/components/rolePicker/RoleCategorySelector.vue.d.ts.map +1 -0
  34. package/dist/components/rolePicker/RoleCategorySelector.vue.js +410 -0
  35. package/dist/components/rolePicker/RoleCategorySelector.vue.js.map +1 -0
  36. package/dist/components/rolePicker/RoleEditor.vue.d.ts +1 -0
  37. package/dist/components/rolePicker/RoleEditor.vue.d.ts.map +1 -1
  38. package/dist/components/rolePicker/RoleEditor.vue.js +64 -31
  39. package/dist/components/rolePicker/RoleEditor.vue.js.map +1 -1
  40. package/dist/components/rolePicker/baseRolePicker.vue.d.ts.map +1 -1
  41. package/dist/components/rolePicker/baseRolePicker.vue.js +7 -9
  42. package/dist/components/rolePicker/baseRolePicker.vue.js.map +1 -1
  43. package/dist/components/rolePicker/index.d.ts +2 -0
  44. package/dist/components/rolePicker/index.d.ts.map +1 -1
  45. package/dist/components/rolePicker/index.js +2 -0
  46. package/dist/components/rolePicker/index.js.map +1 -1
  47. package/dist/components/scrollbar/Scrollbar.vue.d.ts +110 -378
  48. package/dist/components/scrollbar/Scrollbar.vue.d.ts.map +1 -1
  49. package/dist/components/switch/JaSwitch.vue.d.ts +96 -431
  50. package/dist/components/switch/JaSwitch.vue.d.ts.map +1 -1
  51. package/dist/components/upload/JaUploader.vue.d.ts +58 -6
  52. package/dist/components/upload/JaUploader.vue.d.ts.map +1 -1
  53. package/dist/components/upload/index.d.ts +88 -9
  54. package/dist/components/upload/index.d.ts.map +1 -1
  55. package/dist/components/upload/index.js +1 -0
  56. package/dist/components/upload/index.js.map +1 -1
  57. package/dist/components/upload/types.d.ts +3 -0
  58. package/dist/components/upload/types.d.ts.map +1 -0
  59. package/dist/components/upload/types.js +2 -0
  60. package/dist/components/upload/types.js.map +1 -0
  61. package/dist/components/upload/uploader.vue.d.ts +31 -3
  62. package/dist/components/upload/uploader.vue.d.ts.map +1 -1
  63. package/dist/components/upload/uploader.vue.js +42 -15
  64. package/dist/components/upload/uploader.vue.js.map +1 -1
  65. package/dist/components/userGroupTree/src/userGroupTree.vue.d.ts +1808 -0
  66. package/dist/components/userGroupTree/src/userGroupTree.vue.d.ts.map +1 -0
  67. package/dist/components/userGroupTree/src/userGroupTree.vue.js +23 -14
  68. package/dist/components/userGroupTree/src/userGroupTree.vue.js.map +1 -1
  69. package/dist/components/userPicker/src/JaUserList.vue.d.ts +4 -0
  70. package/dist/components/userPicker/src/JaUserList.vue.d.ts.map +1 -1
  71. package/dist/components/userPicker/src/JaUserList.vue.js +9 -1
  72. package/dist/components/userPicker/src/JaUserList.vue.js.map +1 -1
  73. package/dist/components/userPicker/src/UserPicker.vue.d.ts +10 -0
  74. package/dist/components/userPicker/src/UserPicker.vue.d.ts.map +1 -1
  75. package/dist/components/userPicker/src/UserPicker.vue.js +46 -5
  76. package/dist/components/userPicker/src/UserPicker.vue.js.map +1 -1
  77. package/dist/components/userSelectDialog/src/userSelectDialog.vue.d.ts +19 -2
  78. package/dist/components/userSelectDialog/src/userSelectDialog.vue.d.ts.map +1 -1
  79. package/dist/components/userSelectDialog/src/userSelectDialog.vue.js +60 -12
  80. package/dist/components/userSelectDialog/src/userSelectDialog.vue.js.map +1 -1
  81. package/dist/hooks/useAppInstances.d.ts +17 -4
  82. package/dist/hooks/useAppInstances.d.ts.map +1 -1
  83. package/dist/hooks/useAppInstances.js +109 -24
  84. package/dist/hooks/useAppInstances.js.map +1 -1
  85. package/dist/hooks/useClassificationLevels.d.ts.map +1 -1
  86. package/dist/hooks/useClassificationLevels.js +30 -7
  87. package/dist/hooks/useClassificationLevels.js.map +1 -1
  88. package/dist/hooks/useConstraintProviders.d.ts +5 -0
  89. package/dist/hooks/useConstraintProviders.d.ts.map +1 -0
  90. package/dist/hooks/useConstraintProviders.js +31 -0
  91. package/dist/hooks/useConstraintProviders.js.map +1 -0
  92. package/dist/hooks/useEntities.d.ts +9 -0
  93. package/dist/hooks/useEntities.d.ts.map +1 -0
  94. package/dist/hooks/useEntities.js +40 -0
  95. package/dist/hooks/useEntities.js.map +1 -0
  96. package/dist/hooks/useEntityPropDataTypes.d.ts +5 -0
  97. package/dist/hooks/useEntityPropDataTypes.d.ts.map +1 -0
  98. package/dist/hooks/useEntityPropDataTypes.js +31 -0
  99. package/dist/hooks/useEntityPropDataTypes.js.map +1 -0
  100. package/dist/hooks/useFileConfigurations.d.ts +6 -0
  101. package/dist/hooks/useFileConfigurations.d.ts.map +1 -0
  102. package/dist/hooks/useFileConfigurations.js +37 -0
  103. package/dist/hooks/useFileConfigurations.js.map +1 -0
  104. package/dist/hooks/useGroups.d.ts +7 -0
  105. package/dist/hooks/useGroups.d.ts.map +1 -0
  106. package/dist/hooks/useGroups.js +75 -0
  107. package/dist/hooks/useGroups.js.map +1 -0
  108. package/dist/hooks/useNumberTemplates.d.ts +6 -0
  109. package/dist/hooks/useNumberTemplates.d.ts.map +1 -0
  110. package/dist/hooks/useNumberTemplates.js +37 -0
  111. package/dist/hooks/useNumberTemplates.js.map +1 -0
  112. package/dist/hooks/useProperties.d.ts +9 -0
  113. package/dist/hooks/useProperties.d.ts.map +1 -0
  114. package/dist/hooks/useProperties.js +40 -0
  115. package/dist/hooks/useProperties.js.map +1 -0
  116. package/dist/hooks/useRoleCategories.d.ts +6 -0
  117. package/dist/hooks/useRoleCategories.d.ts.map +1 -0
  118. package/dist/hooks/useRoleCategories.js +37 -0
  119. package/dist/hooks/useRoleCategories.js.map +1 -0
  120. package/dist/hooks/useRoles.d.ts +6 -0
  121. package/dist/hooks/useRoles.d.ts.map +1 -0
  122. package/dist/hooks/useRoles.js +38 -0
  123. package/dist/hooks/useRoles.js.map +1 -0
  124. package/dist/index.d.ts +9 -0
  125. package/dist/index.d.ts.map +1 -1
  126. package/dist/index.js +9 -0
  127. package/dist/index.js.map +1 -1
  128. package/lib/index.css +1 -1
  129. package/lib/index.js +9019 -8458
  130. package/lib/index.umd.cjs +39 -34
  131. package/package.json +7 -7
  132. package/packages/components/input/JaInput.vue +1 -1
  133. package/packages/components/inputI18n/I18nBundleEditor.vue +2 -2
  134. package/packages/components/inputI18n/InputI18n.vue +33 -25
  135. package/packages/components/inputNumber/JaInputNumber.vue +6 -5
  136. package/packages/components/properyPicker/PropertyPicker.vue +4 -8
  137. package/packages/components/rolePicker/RoleCategorySelector.vue +154 -0
  138. package/packages/components/rolePicker/RoleEditor.vue +16 -7
  139. package/packages/components/rolePicker/baseRolePicker.vue +6 -13
  140. package/packages/components/rolePicker/index.ts +3 -0
  141. package/packages/components/upload/index.ts +1 -0
  142. package/packages/components/upload/types.ts +4 -0
  143. package/packages/components/upload/uploader.vue +469 -381
  144. package/packages/components/userGroupTree/src/userGroupTree.vue +54 -17
  145. package/packages/components/userPicker/src/JaUserList.vue +14 -2
  146. package/packages/components/userPicker/src/UserPicker.vue +47 -4
  147. package/packages/components/userSelectDialog/src/userSelectDialog.vue +45 -8
  148. package/packages/hooks/useAppInstances.ts +121 -25
  149. package/packages/hooks/useClassificationLevels.ts +31 -7
  150. package/packages/hooks/useConstraintProviders.ts +36 -0
  151. package/packages/hooks/useEntities.ts +44 -0
  152. package/packages/hooks/useEntityPropDataTypes.ts +37 -0
  153. package/packages/hooks/useFileConfigurations.ts +41 -0
  154. package/packages/hooks/useGroups.ts +81 -0
  155. package/packages/hooks/useNumberTemplates.ts +43 -0
  156. package/packages/hooks/useProperties.ts +44 -0
  157. package/packages/hooks/useRoleCategories.ts +42 -0
  158. package/packages/hooks/useRoles.ts +44 -0
  159. package/packages/index.ts +9 -0
@@ -18,7 +18,7 @@
18
18
  import {computed, ref, shallowReactive, watch} from "vue";
19
19
  import {
20
20
  createAxiosWithoutCache,
21
- type Group,
21
+ type Group, type ProjectedGroup,
22
22
  useAppApi,
23
23
  useLoading,
24
24
  useUserGroupApi,
@@ -26,20 +26,47 @@ import {
26
26
  import {type TreeNodeType, useTreeData} from "../../../hooks/useTreeData";
27
27
  import {ElOption, ElSelect, ElTree, vLoading} from "element-plus";
28
28
  import type {TreeNodeData} from "element-plus/es/components/tree/src/tree.type";
29
+ import {useAppInstances} from "../../../hooks/useAppInstances";
30
+ import {useGroups} from "../../../hooks/useGroups";
29
31
 
30
32
  interface Props {
33
+ /**
34
+ * 用户域ID
35
+ */
31
36
  realmId?: string;
37
+ /**
38
+ * 是否多选
39
+ */
32
40
  multiple?: boolean;
41
+ /**
42
+ * 是否显示控制台应用
43
+ */
33
44
  showConsoleApp?: boolean
45
+ /**
46
+ * 只显示指定应用下的用户组(不可自选应用)
47
+ */
34
48
  appId?: string;
49
+ /**
50
+ * 节点高度
51
+ */
35
52
  nodeHeight?: string;
53
+ /**
54
+ * 业务类别
55
+ */
56
+ category?: string;
57
+ /**
58
+ * 是否全局用户组
59
+ */
60
+ global?: boolean;
61
+ /**
62
+ * 是否显示所有分类
63
+ */
64
+ showAllCategory? :boolean;
36
65
  }
37
66
 
38
67
  const groupTree = ref<typeof ElTree>();
39
68
  const axios = createAxiosWithoutCache()
40
69
  const loading = useLoading(axios);
41
- const departmentApi = useUserGroupApi(axios);
42
- const appApi = useAppApi(axios);
43
70
  const props = withDefaults(defineProps<Props>(), {nodeHeight: 'auto'});
44
71
  const emits = defineEmits(["change", "loaded"]);
45
72
  const selected = defineModel<Group | null>();
@@ -53,23 +80,28 @@ const id = computed({
53
80
  }
54
81
  })
55
82
 
56
- const [globalApp, apps] = await Promise.all([
57
- appApi.getGlobalApp(),
58
- appApi.getAccessible()
83
+ const {getGlobal, getAccessible} = useAppInstances()
84
+ const {getGroups, getGlobalGroups} = useGroups()
85
+
86
+ let [globalApp, _apps] = await Promise.all([
87
+ getGlobal(),
88
+ getAccessible(),
59
89
  ])
90
+ _apps = [..._apps];
91
+ _apps.unshift(globalApp);
60
92
 
61
- apps.unshift(globalApp);
62
93
  if (!props.showConsoleApp) {
63
- const index = apps.findIndex(a => a.name == "ace-app-manage");
94
+ const index = _apps.findIndex(a => a.name == "ace-app-manage");
64
95
  if (index >= 0) {
65
- apps.splice(index, 1);
96
+ _apps.splice(index, 1);
66
97
  }
67
98
  }
99
+ const apps = ref(_apps)
100
+
68
101
  if (!currentApp.value) {
69
102
  currentApp.value = globalApp.id;
70
103
  }
71
104
 
72
-
73
105
  const state = shallowReactive<{
74
106
  groups: (TreeNodeType & Group)[];
75
107
  }>({
@@ -78,7 +110,12 @@ const state = shallowReactive<{
78
110
 
79
111
  const getList = async () => {
80
112
  if (!props.realmId || !currentApp.value) return;
81
- const res = await departmentApi.getByAppIdAndRealm(currentApp.value, props.realmId);
113
+ let res: ProjectedGroup[]
114
+ if (props.global) {
115
+ res = await getGlobalGroups(props.realmId);
116
+ } else {
117
+ res = await getGroups(currentApp.value, props.realmId, props.category, props.showAllCategory);
118
+ }
82
119
  state.groups = [
83
120
  ...useTreeData<Group>(res, "name"),
84
121
  ];
@@ -94,25 +131,25 @@ const currentChange = (data: TreeNodeType & Group) => {
94
131
  };
95
132
 
96
133
  watch(
97
- () => props.realmId,
134
+ () => (
135
+ {appId: props.appId, realmId: props.realmId, category: props.category}
136
+ ),
98
137
  () => {
99
138
  //重新获取
100
139
  getList();
140
+ }, {
141
+ deep: true,
142
+ immediate: true,
101
143
  }
102
144
  );
103
145
  watch(() => props.appId, () => {
104
146
  currentApp.value = props.appId;
105
147
  })
106
- watch(currentApp, () => {
107
- getList();
108
- })
109
148
 
110
149
  defineExpose({
111
150
  reload: getList,
112
151
  elTree: groupTree
113
152
  });
114
-
115
- getList();
116
153
  </script>
117
154
 
118
155
  <style lang="scss" scoped>
@@ -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
- arr.push(...users.value.filter(u => !arr.some(su => su.id === u.id)));
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: false},
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
- users.forEach(u => map.set(u.id, u))
235
- tempSel.value.push(...users);
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
- users.forEach(u => map.set(u.id, u))
251
- tempSel.value.splice(0);
252
- tempSel.value.push(...users);
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
  }
@@ -351,7 +388,7 @@ defineExpose({
351
388
  </el-tab-pane>
352
389
  <el-tab-pane name="group" label="按用户组">
353
390
  <el-scrollbar height="400">
354
- <ja-user-group-tree v-model="currentGroup"
391
+ <ja-user-group-tree v-model="currentGroup" show-all-category
355
392
  :realm-id="localRealmId"></ja-user-group-tree>
356
393
  </el-scrollbar>
357
394
  </el-tab-pane>
@@ -1,34 +1,130 @@
1
- import {type AppInstance, createAxiosWithoutCache, useAppApi} from "@jari-ace/app-bolts";
1
+ import {
2
+ type AppInstance,
3
+ createAxiosWithoutCache,
4
+ type IAceAxios,
5
+ useAppApi
6
+ } from "@jari-ace/app-bolts";
7
+ import {ref, readonly, type Ref} from 'vue'; // 1. 引入 ref 和 readonly
2
8
 
9
+ type LoadType = "all" | "accessible" | "manageable" | "global"
10
+ const appCache: Map<LoadType, AppInstance[]> = new Map()
11
+ const promises: Map<LoadType, Promise<AppInstance[]>> = new Map();
3
12
 
4
- let appCache: AppInstance[] = [];
13
+ let axios: IAceAxios = null
14
+ let api: ReturnType<typeof useAppApi>
5
15
 
6
- export async function useAppInstances() {
7
- const axios = createAxiosWithoutCache()
8
- const api = useAppApi(axios)
9
- if (appCache.length === 0) {
10
- appCache = await api.getAll(true);
16
+ async function loadApps(load: () => Promise<AppInstance[]>, loadType: LoadType): Promise<AppInstance[]> {
17
+ let result = appCache.get(loadType)
18
+ // 如果已经有数据或正在加载,则直接返回
19
+ if (result) {
20
+ return result;
11
21
  }
12
- return {
13
- async getById(appId: string) {
14
- let app = appCache.find(a => a.id === appId);
15
- if (!app) {
16
- app = await api.getById(appId);
17
- if (app) {
18
- appCache.push(app);
19
- }
22
+ let promise = promises.get(loadType)
23
+ if (promise) {
24
+ return await promise;
25
+ }
26
+ promise = load()
27
+ .then(data => {
28
+ appCache.set(loadType, data)
29
+ return data;
30
+ })
31
+ .finally(() => {
32
+ // 成功后也重置,但保留数据
33
+ promises.delete(loadType)
34
+ });
35
+ promises.set(loadType, promise)
36
+ return await promise;
37
+ }
38
+
39
+ async function getAll(includeConsoleApp?: boolean) {
40
+ if (!api) {
41
+ axios = axios || createAxiosWithoutCache();
42
+ api = api || useAppApi(axios);
43
+ }
44
+ const apps =await loadApps(() => api.getAll(true), "all");
45
+ if (includeConsoleApp) {
46
+ return apps
47
+ } else {
48
+ return apps.filter(a=>a.name !== 'ace-app-manage')
49
+ }
50
+ }
51
+ async function getById(appId: string) {
52
+ if (!api) {
53
+ axios = axios || createAxiosWithoutCache();
54
+ api = api || useAppApi(axios);
55
+ }
56
+ await loadApps(() => api.getAll(true), "all")
57
+ let app = appCache.get("all").find(a => a.id === appId);
58
+ if (!app) {
59
+ axios = axios || createAxiosWithoutCache();
60
+ api = api || useAppApi(axios);
61
+ app = await api.getById(appId);
62
+ if (app) {
63
+ if (!appCache.get("all").find(a => a.id === app.id)) {
64
+ appCache.get("all").push(app); // 这将触发UI更新
20
65
  }
21
- return app;
22
- },
23
- async getByName(appName: string) {
24
- let app = appCache.find(a => a.name === appName);
25
- if (!app) {
26
- app = await api.getByName(appName);
27
- if (app) {
28
- appCache.push(app);
29
- }
66
+ }
67
+ }
68
+ return app;
69
+ }
70
+ async function getByName(appName: string) {
71
+ if (!api) {
72
+ axios = axios || createAxiosWithoutCache();
73
+ api = api || useAppApi(axios);
74
+ }
75
+ await loadApps(() => api.getAll(true), "all")
76
+ let app = appCache.get("all").find(a => a.name === appName);
77
+ if (!app) {
78
+ axios = axios || createAxiosWithoutCache();
79
+ api = api || useAppApi(axios);
80
+ app = await api.getByName(appName);
81
+ if (app) {
82
+ if (!appCache.get("all").find(a => a.id === app.id)) {
83
+ appCache.get("all").push(app);
30
84
  }
31
- return app;
32
85
  }
33
86
  }
87
+ return app;
88
+ }
89
+
90
+ async function getManageable() {
91
+ if (!api) {
92
+ axios = axios || createAxiosWithoutCache();
93
+ api = api || useAppApi(axios);
94
+ }
95
+ return await loadApps(api.getManageable, "manageable")
96
+ }
97
+
98
+ async function getAccessible() {
99
+ if (!api) {
100
+ axios = axios || createAxiosWithoutCache();
101
+ api = api || useAppApi(axios);
102
+ }
103
+ return await loadApps(api.getAccessible, "accessible")
104
+ }
105
+
106
+ async function getGlobal() {
107
+ if (!api) {
108
+ axios = axios || createAxiosWithoutCache();
109
+ api = api || useAppApi(axios);
110
+ }
111
+ return (await loadApps(()=> api.getGlobalApp().then(a=>[a]), "global"))[0]
112
+ }
113
+
114
+ async function refresh() {
115
+ appCache.clear()
116
+ await Promise.all([getAll(), getManageable(), getAccessible(), getGlobal()])
117
+ }
118
+
119
+ // --- 导出的 Hook (非 async) ---
120
+ export function useAppInstances() {
121
+ return {
122
+ getAll,
123
+ getByName,
124
+ getById,
125
+ getManageable,
126
+ getAccessible,
127
+ getGlobal,
128
+ refresh
129
+ };
34
130
  }
@@ -5,15 +5,38 @@ import {
5
5
  } from "@jari-ace/app-bolts";
6
6
  import {ref} from "vue";
7
7
 
8
- const levelList = ref<ClassificationLevelList>()
8
+ let levelList = ref<ClassificationLevelList>()
9
+ let loadingPromise: Promise<ClassificationLevelList> = undefined
9
10
 
10
11
  async function loadLevels(serviceName: string) {
11
- if (!levelList.value) {
12
- if (!serviceName) serviceName = 'ace-global-app'
13
- const axios = createAxiosWithoutCache()
14
- const api = useAppServiceApi(axios)
15
- levelList.value = await api.getClassificationLevels(serviceName)
12
+ if (levelList.value) {
13
+ return levelList.value
16
14
  }
15
+ if (loadingPromise) {
16
+ return await loadingPromise
17
+ }
18
+ if (!serviceName) serviceName = 'ace-global-app'
19
+ const axios = createAxiosWithoutCache()
20
+ const api = useAppServiceApi(axios)
21
+ loadingPromise = api.getClassificationLevels(serviceName)
22
+ .then(levels => {
23
+ if (levels) {
24
+ // 检查并按 value 倒序排序 system 数组
25
+ if (levels.system) {
26
+ // 修改点:b.value - a.value 实现降序
27
+ levels.system.sort((a, b) => b.value - a.value);
28
+ }
29
+ // 检查并按 value 倒序排序 user 数组
30
+ if (levels.user) {
31
+ // 修改点:b.value - a.value 实现降序
32
+ levels.user.sort((a, b) => b.value - a.value);
33
+ }
34
+ }
35
+ levelList.value = levels
36
+ return levels
37
+ })
38
+ .finally(() => loadingPromise = undefined)
39
+ return await loadingPromise;
17
40
  }
18
41
 
19
42
  /**
@@ -47,11 +70,12 @@ export async function useUserClassificationLevelMap(serviceName?: string) {
47
70
  }
48
71
  return map;
49
72
  }
73
+
50
74
  /**
51
75
  * 获取系统密级反向映射,可以根据密级获取密级对应的中文标签
52
76
  * @param serviceName 服务名
53
77
  */
54
- export async function useSystemClassificationLevelMap(serviceName?: string){
78
+ export async function useSystemClassificationLevelMap(serviceName?: string) {
55
79
  await loadLevels(serviceName);
56
80
  const map = new Map<number, string>()
57
81
  for (let i = 0; i < levelList.value.system.length; i++) {
@@ -0,0 +1,36 @@
1
+ import {
2
+ type ConstraintProvider,
3
+ createAxiosWithoutCache, useConstraintApi
4
+ } from "@jari-ace/app-bolts";
5
+
6
+ let cache: ConstraintProvider[] = null
7
+ let loadingPromise:Promise<ConstraintProvider[]> = undefined
8
+
9
+ export function useConstraintProviders() {
10
+ return {
11
+ async getConstraintProviders() {
12
+ let dataTypes = cache;
13
+ if (dataTypes) {
14
+ return dataTypes;
15
+ }
16
+ if (loadingPromise) {
17
+ return await loadingPromise
18
+ }
19
+ // 3. 没有缓存,也没有正在进行的请求,创建新请求
20
+ const axios = createAxiosWithoutCache();
21
+ const api = useConstraintApi(axios);
22
+
23
+ // 创建 Promise
24
+ loadingPromise = api.getConstraintProviders()
25
+ .then(result => {
26
+ // 缓存结果
27
+ cache = result
28
+ return result;
29
+ })
30
+ .finally(() => {
31
+ loadingPromise = undefined
32
+ });
33
+ return await loadingPromise;
34
+ }
35
+ }
36
+ }