@ebiz/designer-components 0.1.98 → 0.1.100
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/designer-components.css +1 -1
- package/dist/index.mjs +15921 -15616
- package/package.json +1 -1
- package/src/components/EbizMeetingRoomSelector.vue +898 -411
- package/src/components/EbizTreeSelector.vue +118 -116
- package/src/components/senior/EbizSDialog/index.vue +4 -1
|
@@ -1,85 +1,80 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="ebiz-tree-selector">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
</div>
|
|
3
|
+
<div class="selected-items" v-if="modelValue && modelValue.length">
|
|
4
|
+
<div v-for="(item, index) in modelValue" :key="index" class="selected-item">
|
|
5
|
+
<span class="item-text">{{ item.label }}</span>
|
|
6
|
+
<span class="item-remove" @click="removeItem(index)">×</span>
|
|
8
7
|
</div>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
</
|
|
24
|
-
</
|
|
8
|
+
</div>
|
|
9
|
+
<t-button @click="showDialog" variant="text" theme="primary" size="small"> 添加 </t-button>
|
|
10
|
+
|
|
11
|
+
<EbizDialog attach="body" :zIndex="10000" v-model:visible="dialogVisible" header="选择人员/部门" width="800px"
|
|
12
|
+
placement="center" confirmBtn="确定" cancelBtn="取消" @confirm="handleConfirm" @cancel="handleCancel"
|
|
13
|
+
@close="handleCancel">
|
|
14
|
+
<div class="selector-container">
|
|
15
|
+
<!-- 左侧选择区域 -->
|
|
16
|
+
<div class="left-panel">
|
|
17
|
+
<!-- 顶部搜索区域 -->
|
|
18
|
+
<div class="search-box">
|
|
19
|
+
<t-input v-model="searchText" placeholder="搜索成员、部门或标签" clearable>
|
|
20
|
+
<template #suffix-icon>
|
|
21
|
+
<t-icon name="search"></t-icon>
|
|
22
|
+
</template>
|
|
23
|
+
</t-input>
|
|
24
|
+
</div>
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
26
|
+
<!-- 选项卡 -->
|
|
27
|
+
<t-tabs v-model="activeTab" class="selector-tabs">
|
|
28
|
+
<t-tab-panel value="organization" label="组织架构"></t-tab-panel>
|
|
29
|
+
<!-- <t-tab-panel value="department" label="部门"></t-tab-panel> -->
|
|
30
|
+
<t-tab-panel value="GW" label="岗位"></t-tab-panel>
|
|
31
|
+
<t-tab-panel value="employee" label="员工"></t-tab-panel>
|
|
32
|
+
</t-tabs>
|
|
33
|
+
|
|
34
|
+
<!-- 树形结构区域 -->
|
|
35
|
+
<div class="tree-content">
|
|
36
|
+
<div v-if="loading" class="loading-container">
|
|
37
|
+
<t-loading />
|
|
38
|
+
</div>
|
|
39
|
+
<EbizTree ref="organizationTree" v-show="activeTab === 'organization'" checkable :items="organizationData"
|
|
40
|
+
v-model="checkedNodes" v-model:expanded="expandedNodes" :disable-check="disableCheck"
|
|
41
|
+
:keys="{ label: 'name', value: 'id', children: 'childs' }" />
|
|
42
|
+
<!-- <EbizTree
|
|
43
43
|
v-else-if="activeTab === 'department'"
|
|
44
44
|
checkable
|
|
45
45
|
:items="filteredData."
|
|
46
46
|
v-model="checkedNodes"
|
|
47
47
|
:disable-check="disableCheck"
|
|
48
48
|
/> -->
|
|
49
|
-
<EbizTree
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
:
|
|
54
|
-
:
|
|
55
|
-
v-model="checkedPostNodes"
|
|
56
|
-
:disable-check="disableCheck"
|
|
57
|
-
/>
|
|
58
|
-
<EbizTree ref="employeeTree" v-show="activeTab === 'employee'" checkable :items="employeeData"
|
|
59
|
-
:keys="{ label: 'label', value: 'bindid', children: 'childs' }" v-model="checkedUserNodes"
|
|
60
|
-
:disable-check="disableCheck" />
|
|
61
|
-
</div>
|
|
49
|
+
<EbizTree ref="postTree" v-show="activeTab === 'GW'" checkable :items="postData"
|
|
50
|
+
:keys="{ label: 'label', value: 'bindid', children: 'childs' }" v-model="checkedPostNodes"
|
|
51
|
+
:disable-check="disableCheck" />
|
|
52
|
+
<EbizTree ref="employeeTree" v-show="activeTab === 'employee'" checkable :items="employeeData"
|
|
53
|
+
:keys="{ label: 'label', value: 'bindid', children: 'childs' }" v-model="checkedUserNodes"
|
|
54
|
+
:disable-check="disableCheck" />
|
|
62
55
|
</div>
|
|
56
|
+
</div>
|
|
63
57
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
58
|
+
<!-- 右侧已选区域 -->
|
|
59
|
+
<div class="right-panel">
|
|
60
|
+
<div class="selected-title">已选择的部门、成员</div>
|
|
61
|
+
<div class="selected-count">共 {{ [...selectPreview, ...selectPreviewPost, ...selectPreviewUser].length }} 项
|
|
62
|
+
</div>
|
|
63
|
+
<div class="selected-list">
|
|
64
|
+
<div v-for="(item, index) in [...selectPreview, ...selectPreviewPost, ...selectPreviewUser]" :key="index"
|
|
65
|
+
class="selected-list-item">
|
|
66
|
+
<t-icon :name="getIconForType(item)" class="item-icon" />
|
|
67
|
+
<span class="selected-label">{{ item.label }}</span>
|
|
68
|
+
<t-icon name="close-circle" class="remove-icon" @click="removePreviewItem(item)" />
|
|
69
|
+
</div>
|
|
70
|
+
<div v-if="[...selectPreview, ...selectPreviewPost, ...selectPreviewUser].length === 0" class="no-selection">
|
|
71
|
+
<t-icon name="info-circle" />
|
|
72
|
+
<span style="user-select: none">请在左侧选择部门或成员</span>
|
|
79
73
|
</div>
|
|
80
74
|
</div>
|
|
81
75
|
</div>
|
|
82
|
-
</
|
|
76
|
+
</div>
|
|
77
|
+
</EbizDialog>
|
|
83
78
|
</div>
|
|
84
79
|
</template>
|
|
85
80
|
|
|
@@ -128,7 +123,7 @@ const dialogVisible = ref(false)
|
|
|
128
123
|
const searchText = ref('')
|
|
129
124
|
// 选中的节点
|
|
130
125
|
const checkedNodes = ref([])
|
|
131
|
-
const
|
|
126
|
+
const checkedUserNodes = ref([]);
|
|
132
127
|
const checkedPostNodes = ref([])
|
|
133
128
|
// 展开的节点
|
|
134
129
|
const expandedNodes = ref([])
|
|
@@ -153,36 +148,36 @@ const postTree = ref()
|
|
|
153
148
|
const fetchApiData = async () => {
|
|
154
149
|
loading.value = true
|
|
155
150
|
try {
|
|
156
|
-
|
|
151
|
+
dataService.fetch(
|
|
157
152
|
{ keyWord: activeTab.value === 'organization' ? searchText.value : '' },
|
|
158
153
|
{},
|
|
159
154
|
'/appdata/execute/plugin?key=organizational_structure'
|
|
160
|
-
).then(res=>{
|
|
161
|
-
|
|
155
|
+
).then(res => {
|
|
156
|
+
organizationData.value = res || []
|
|
162
157
|
})
|
|
163
|
-
|
|
164
|
-
{postEnable:true, keyWord:activeTab.value === 'employee' ? searchText.value : ''},
|
|
158
|
+
dataService.fetch(
|
|
159
|
+
{ postEnable: true, keyWord: activeTab.value === 'employee' ? searchText.value : '' },
|
|
165
160
|
{},
|
|
166
161
|
"/appdata/execute/plugin?key=all_active_employesse"
|
|
167
|
-
).then(res=>{
|
|
168
|
-
employeeData.value = (res || []).map(i=>({
|
|
169
|
-
label:i.name,
|
|
170
|
-
bindid:i.id,
|
|
171
|
-
type:'employee'
|
|
162
|
+
).then(res => {
|
|
163
|
+
employeeData.value = (res || []).map(i => ({
|
|
164
|
+
label: i.name,
|
|
165
|
+
bindid: i.id,
|
|
166
|
+
type: 'employee'
|
|
172
167
|
}));
|
|
173
168
|
})
|
|
174
169
|
dataService.fetch({
|
|
175
|
-
apiKey:'all_active_post',
|
|
176
|
-
queryParams:{
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
},{
|
|
181
|
-
},'/appdata/process?key=all_active_post').then(res=>{
|
|
182
|
-
postData.value = (res?.data || []).map(i=>({
|
|
183
|
-
label:i.name,
|
|
184
|
-
bindid:i.id,
|
|
185
|
-
type:'GW'
|
|
170
|
+
apiKey: 'all_active_post',
|
|
171
|
+
queryParams: {
|
|
172
|
+
name: searchText.value,
|
|
173
|
+
status: true
|
|
174
|
+
}
|
|
175
|
+
}, {
|
|
176
|
+
}, '/appdata/process?key=all_active_post').then(res => {
|
|
177
|
+
postData.value = (res?.data || []).map(i => ({
|
|
178
|
+
label: i.name,
|
|
179
|
+
bindid: i.id,
|
|
180
|
+
type: 'GW'
|
|
186
181
|
}))
|
|
187
182
|
})
|
|
188
183
|
console.log(postData.value)
|
|
@@ -210,7 +205,7 @@ function showDialog() {
|
|
|
210
205
|
// 重置选中的节点
|
|
211
206
|
checkedNodes.value = props.modelValue.filter(i => i.type === 'DEPT').map((item) => item.bindid);
|
|
212
207
|
checkedUserNodes.value = props.modelValue.filter(i => i.type === 'employee').map((item) => item.bindid);
|
|
213
|
-
checkedPostNodes.value = props.modelValue.filter(i=>i.type === 'GW').map(item=>item.bindid);
|
|
208
|
+
checkedPostNodes.value = props.modelValue.filter(i => i.type === 'GW').map(item => item.bindid);
|
|
214
209
|
dialogVisible.value = true
|
|
215
210
|
}
|
|
216
211
|
|
|
@@ -220,7 +215,7 @@ function handleConfirm() {
|
|
|
220
215
|
label: item.label,
|
|
221
216
|
bindid: item.bindid,
|
|
222
217
|
type: item.type
|
|
223
|
-
})), ...selectPreviewUser.value
|
|
218
|
+
})), ...selectPreviewUser.value, ...selectPreviewPost.value];
|
|
224
219
|
emit('update:modelValue', finalValue)
|
|
225
220
|
emit('change', finalValue)
|
|
226
221
|
console.log(finalValue)
|
|
@@ -234,24 +229,24 @@ function handleCancel() {
|
|
|
234
229
|
|
|
235
230
|
// 移除已选择预览中的项目
|
|
236
231
|
function removePreviewItem(item) {
|
|
237
|
-
let {selects,nodes} = {
|
|
238
|
-
'DEPT':{
|
|
239
|
-
selects:selectPreview.value,
|
|
240
|
-
nodes:checkedNodes.value
|
|
232
|
+
let { selects, nodes } = {
|
|
233
|
+
'DEPT': {
|
|
234
|
+
selects: selectPreview.value,
|
|
235
|
+
nodes: checkedNodes.value
|
|
241
236
|
},
|
|
242
|
-
'GW':{
|
|
243
|
-
selects:selectPreviewPost.value,
|
|
244
|
-
nodes:checkedPostNodes.value
|
|
237
|
+
'GW': {
|
|
238
|
+
selects: selectPreviewPost.value,
|
|
239
|
+
nodes: checkedPostNodes.value
|
|
245
240
|
},
|
|
246
|
-
'employee':{
|
|
247
|
-
selects:selectPreviewUser.value,
|
|
248
|
-
nodes:checkedUserNodes.value
|
|
241
|
+
'employee': {
|
|
242
|
+
selects: selectPreviewUser.value,
|
|
243
|
+
nodes: checkedUserNodes.value
|
|
249
244
|
}
|
|
250
245
|
}[item.type]
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
246
|
+
let index = selects.value.findIndex(i => i.bindid === item.bindid);
|
|
247
|
+
const removedUser = selects.value[index];
|
|
248
|
+
selects.value.splice(index, 1);
|
|
249
|
+
nodes.value = nodes.value.filter((value) => value !== removedUser.bindid)
|
|
255
250
|
}
|
|
256
251
|
|
|
257
252
|
// 移除选中项
|
|
@@ -275,26 +270,33 @@ watch(
|
|
|
275
270
|
},
|
|
276
271
|
{ deep: true }
|
|
277
272
|
)
|
|
278
|
-
watch(checkedUserNodes,nVal=>{
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
273
|
+
watch(checkedUserNodes, nVal => {
|
|
274
|
+
// 获取新选中的用户数据
|
|
275
|
+
const newSelectedUsers = employeeData.value.filter(i => nVal.includes(i.bindid))
|
|
276
|
+
// 获取现有用户的bindid列表,避免重复添加
|
|
277
|
+
const existingBindIds = selectPreviewUser.value.map(user => user.bindid)
|
|
278
|
+
// 过滤出真正新增的用户(不在现有列表中的)
|
|
279
|
+
const usersToAdd = newSelectedUsers.filter(user => !existingBindIds.includes(user.bindid))
|
|
280
|
+
// 增量添加新用户到现有列表中
|
|
281
|
+
selectPreviewUser.value = [...selectPreviewUser.value, ...usersToAdd]
|
|
282
|
+
}, { deep: true })
|
|
283
|
+
watch(checkedPostNodes, nVal => {
|
|
284
|
+
selectPreviewPost.value = postData.value.filter(i => nVal.includes(i.bindid))
|
|
285
|
+
}, { deep: true })
|
|
284
286
|
// 监听modelValue变化,同步到选中节点
|
|
285
287
|
watch(
|
|
286
288
|
() => props.modelValue,
|
|
287
289
|
(newValue) => {
|
|
288
|
-
checkedNodes.value = newValue.filter(i=>i.type === 'DEPT').map((item) => item.bindid);
|
|
290
|
+
checkedNodes.value = newValue.filter(i => i.type === 'DEPT').map((item) => item.bindid);
|
|
289
291
|
checkedUserNodes.value = newValue.filter(i => i.type === 'employee').map((item) => item.bindid);
|
|
290
|
-
checkedPostNodes.value = newValue.filter(i=>i.type === 'GW').map(item=>item.bindid);
|
|
292
|
+
checkedPostNodes.value = newValue.filter(i => i.type === 'GW').map(item => item.bindid);
|
|
291
293
|
},
|
|
292
|
-
{ deep: true
|
|
294
|
+
{ deep: true, immediate: true }
|
|
293
295
|
)
|
|
294
|
-
watch(activeTab,nVal=>{
|
|
296
|
+
watch(activeTab, nVal => {
|
|
295
297
|
searchText.value = ''
|
|
296
298
|
})
|
|
297
|
-
watch(searchText,nVal=>{
|
|
299
|
+
watch(searchText, nVal => {
|
|
298
300
|
fetchApiData()
|
|
299
301
|
})
|
|
300
302
|
</script>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<t-dialog v-model:visible="dialogVisible" :header="title || computedTitle" :width="dialogWidth" :top="dialogTop"
|
|
15
15
|
:attach="dialogAttach" :destroy-on-close="dialogDestroyOnClose" :mode="dialogMode" :placement="dialogPlacement"
|
|
16
16
|
:show-overlay="dialogShowOverlay" :close-on-esc-keydown="dialogCloseOnEscKeydown"
|
|
17
|
-
:close-on-overlay-click="dialogCloseOnOverlayClick" :
|
|
17
|
+
:close-on-overlay-click="dialogCloseOnOverlayClick" :confirm-btn="dialogShowFooterCompute" :cancel-btn="dialogShowFooterCompute" @close="handleDialogClose"
|
|
18
18
|
@confirm="handleDialogConfirm" @cancel="handleDialogCancel">
|
|
19
19
|
<template #header>
|
|
20
20
|
<slot name="header">
|
|
@@ -302,6 +302,9 @@ const currentParams = ref({})
|
|
|
302
302
|
// 本地维护一份表单数据的副本
|
|
303
303
|
const initFormData = ref(props.formData ? { ...props.formData } : {})
|
|
304
304
|
const localFormData = ref({ ...initFormData.value })
|
|
305
|
+
const dialogShowFooterCompute = computed(() => {
|
|
306
|
+
return props.dialogShowFooter ? {} : null
|
|
307
|
+
})
|
|
305
308
|
|
|
306
309
|
// 监听 props.formData 的变化,同步到本地数据
|
|
307
310
|
watch(() => props.formData, (newFormData) => {
|