@ebiz/designer-components 0.1.82 → 0.1.84
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 +17674 -17608
- package/package.json +1 -1
- package/src/components/EbizDictionarySelect.vue +24 -23
- package/src/components/EbizTreeSelector.vue +73 -40
- package/src/components/mItems/UserInfo.vue +40 -33
- package/src/components/senior/EbizSForm/item.vue +14 -2
package/package.json
CHANGED
|
@@ -195,29 +195,30 @@ const handleChange = (value, context) => {
|
|
|
195
195
|
|
|
196
196
|
// 组件挂载时,如果有默认值则加载对应的选项
|
|
197
197
|
onMounted(async () => {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
queryParams
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
198
|
+
loading.value = true;
|
|
199
|
+
try {
|
|
200
|
+
const params = {
|
|
201
|
+
queryParams: {
|
|
202
|
+
...queryParams.value,
|
|
203
|
+
dictionaryKey: props.dictionaryKey
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
const res = await dataService.fetch(params, {
|
|
207
|
+
"key": "query_dictionary_option",
|
|
208
|
+
"apiId": 2978,
|
|
209
|
+
"apiType": 0
|
|
210
|
+
});
|
|
211
|
+
const { labelField, valueField } = props.optionsConfig;
|
|
212
|
+
|
|
213
|
+
options.value = res.data.at(0).value.map(item => ({
|
|
214
|
+
...item,
|
|
215
|
+
label: labelField ? item[labelField] : (item.label || item.name),
|
|
216
|
+
value: valueField ? item[valueField] : (item.value || item.id)
|
|
217
|
+
}));
|
|
218
|
+
} catch (error) {
|
|
219
|
+
console.error('加载默认选项失败:', error);
|
|
220
|
+
} finally {
|
|
221
|
+
loading.value = false;
|
|
221
222
|
}
|
|
222
223
|
});
|
|
223
224
|
</script>
|
|
@@ -25,11 +25,9 @@
|
|
|
25
25
|
|
|
26
26
|
<!-- 选项卡 -->
|
|
27
27
|
<t-tabs v-model="activeTab" class="selector-tabs">
|
|
28
|
-
<t-tab-panel value="organization" label="组织架构"
|
|
29
|
-
|
|
30
|
-
</t-tab-panel>
|
|
28
|
+
<t-tab-panel value="organization" label="组织架构"></t-tab-panel>
|
|
31
29
|
<!-- <t-tab-panel value="department" label="部门"></t-tab-panel> -->
|
|
32
|
-
|
|
30
|
+
<t-tab-panel value="GW" label="岗位"></t-tab-panel>
|
|
33
31
|
<t-tab-panel value="employee" label="员工"></t-tab-panel>
|
|
34
32
|
</t-tabs>
|
|
35
33
|
|
|
@@ -47,14 +45,16 @@
|
|
|
47
45
|
:items="filteredData."
|
|
48
46
|
v-model="checkedNodes"
|
|
49
47
|
:disable-check="disableCheck"
|
|
50
|
-
/>
|
|
48
|
+
/> -->
|
|
51
49
|
<EbizTree
|
|
52
|
-
|
|
50
|
+
ref="postTree"
|
|
51
|
+
v-show="activeTab === 'GW'"
|
|
53
52
|
checkable
|
|
54
|
-
:items="
|
|
55
|
-
|
|
53
|
+
:items="postData"
|
|
54
|
+
:keys="{ label: 'label', value: 'bindid', children: 'childs' }"
|
|
55
|
+
v-model="checkedPostNodes"
|
|
56
56
|
:disable-check="disableCheck"
|
|
57
|
-
/>
|
|
57
|
+
/>
|
|
58
58
|
<EbizTree ref="employeeTree" v-show="activeTab === 'employee'" checkable :items="employeeData"
|
|
59
59
|
:keys="{ label: 'label', value: 'bindid', children: 'childs' }" v-model="checkedUserNodes"
|
|
60
60
|
:disable-check="disableCheck" />
|
|
@@ -64,15 +64,15 @@
|
|
|
64
64
|
<!-- 右侧已选区域 -->
|
|
65
65
|
<div class="right-panel">
|
|
66
66
|
<div class="selected-title">已选择的部门、成员</div>
|
|
67
|
-
<div class="selected-count">共 {{ [...selectPreview, ...selectPreviewUser].length }} 项</div>
|
|
67
|
+
<div class="selected-count">共 {{ [...selectPreview, ...selectPreviewPost,...selectPreviewUser].length }} 项</div>
|
|
68
68
|
<div class="selected-list">
|
|
69
|
-
<div v-for="(item, index) in [...selectPreview,...selectPreviewUser]" :key="index"
|
|
69
|
+
<div v-for="(item, index) in [...selectPreview,...selectPreviewPost,...selectPreviewUser]" :key="index"
|
|
70
70
|
class="selected-list-item">
|
|
71
71
|
<t-icon :name="getIconForType(item)" class="item-icon" />
|
|
72
72
|
<span class="selected-label">{{ item.label }}</span>
|
|
73
73
|
<t-icon name="close-circle" class="remove-icon" @click="removePreviewItem(item)" />
|
|
74
74
|
</div>
|
|
75
|
-
<div v-if="[...selectPreview, ...selectPreviewUser].length === 0" class="no-selection">
|
|
75
|
+
<div v-if="[...selectPreview,...selectPreviewPost, ...selectPreviewUser].length === 0" class="no-selection">
|
|
76
76
|
<t-icon name="info-circle" />
|
|
77
77
|
<span style="user-select: none">请在左侧选择部门或成员</span>
|
|
78
78
|
</div>
|
|
@@ -129,6 +129,7 @@ const searchText = ref('')
|
|
|
129
129
|
// 选中的节点
|
|
130
130
|
const checkedNodes = ref([])
|
|
131
131
|
const checkedUserNodes = ref([]);
|
|
132
|
+
const checkedPostNodes = ref([])
|
|
132
133
|
// 展开的节点
|
|
133
134
|
const expandedNodes = ref([])
|
|
134
135
|
// 当前活动的选项卡
|
|
@@ -136,32 +137,55 @@ const activeTab = ref('organization')
|
|
|
136
137
|
// 弹窗内预览的选中项
|
|
137
138
|
const selectPreview = ref([])
|
|
138
139
|
const selectPreviewUser = ref([])
|
|
140
|
+
const selectPreviewPost = ref([])
|
|
139
141
|
// 加载状态
|
|
140
142
|
const loading = ref(false)
|
|
141
143
|
// API返回的数据
|
|
142
144
|
const organizationData = ref([])
|
|
143
145
|
const employeeData = ref([])
|
|
146
|
+
const postData = ref([]);
|
|
147
|
+
|
|
144
148
|
const organizationTree = ref()
|
|
145
149
|
const employeeTree = ref()
|
|
150
|
+
const postTree = ref()
|
|
146
151
|
|
|
147
152
|
// 获取API数据
|
|
148
153
|
const fetchApiData = async () => {
|
|
149
154
|
loading.value = true
|
|
150
155
|
try {
|
|
151
|
-
|
|
156
|
+
dataService.fetch(
|
|
152
157
|
{ keyWord: activeTab.value === 'organization' ? searchText.value : '' },
|
|
153
158
|
{},
|
|
154
159
|
'/appdata/execute/plugin?key=organizational_structure'
|
|
155
|
-
)
|
|
156
|
-
|
|
160
|
+
).then(res=>{
|
|
161
|
+
organizationData.value = res || []
|
|
162
|
+
})
|
|
163
|
+
dataService.fetch(
|
|
157
164
|
{postEnable:true, keyWord:activeTab.value === 'employee' ? searchText.value : ''},
|
|
158
165
|
{},
|
|
159
166
|
"/appdata/execute/plugin?key=all_active_employesse"
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
167
|
+
).then(res=>{
|
|
168
|
+
employeeData.value = (res || []).map(i=>({
|
|
169
|
+
label:i.name,
|
|
170
|
+
bindid:i.id,
|
|
171
|
+
type:'employee'
|
|
172
|
+
}));
|
|
173
|
+
})
|
|
174
|
+
dataService.fetch({
|
|
175
|
+
apiKey:'all_active_post',
|
|
176
|
+
queryParams:{
|
|
177
|
+
name:searchText.value,
|
|
178
|
+
status:true
|
|
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'
|
|
186
|
+
}))
|
|
187
|
+
})
|
|
188
|
+
console.log(postData.value)
|
|
165
189
|
} catch (error) {
|
|
166
190
|
} finally {
|
|
167
191
|
loading.value = false
|
|
@@ -176,7 +200,7 @@ const getIconForType = (item) => {
|
|
|
176
200
|
GW: 'user-list',
|
|
177
201
|
employee: 'user'
|
|
178
202
|
}
|
|
179
|
-
return iconMap[item
|
|
203
|
+
return iconMap[item?.type] || 'user'
|
|
180
204
|
}
|
|
181
205
|
|
|
182
206
|
// 显示对话框
|
|
@@ -184,8 +208,9 @@ function showDialog() {
|
|
|
184
208
|
// 获取API数据
|
|
185
209
|
fetchApiData()
|
|
186
210
|
// 重置选中的节点
|
|
187
|
-
checkedNodes.value = props.modelValue.filter(i => i.type
|
|
211
|
+
checkedNodes.value = props.modelValue.filter(i => i.type === 'DEPT').map((item) => item.bindid);
|
|
188
212
|
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);
|
|
189
214
|
dialogVisible.value = true
|
|
190
215
|
}
|
|
191
216
|
|
|
@@ -195,11 +220,10 @@ function handleConfirm() {
|
|
|
195
220
|
label: item.label,
|
|
196
221
|
bindid: item.bindid,
|
|
197
222
|
type: item.type
|
|
198
|
-
})), ...selectPreviewUser.value];
|
|
199
|
-
emit(
|
|
200
|
-
'update:modelValue', finalValue
|
|
201
|
-
)
|
|
223
|
+
})), ...selectPreviewUser.value,...selectPreviewPost.value];
|
|
224
|
+
emit('update:modelValue', finalValue)
|
|
202
225
|
emit('change', finalValue)
|
|
226
|
+
console.log(finalValue)
|
|
203
227
|
dialogVisible.value = false
|
|
204
228
|
}
|
|
205
229
|
|
|
@@ -210,18 +234,24 @@ function handleCancel() {
|
|
|
210
234
|
|
|
211
235
|
// 移除已选择预览中的项目
|
|
212
236
|
function removePreviewItem(item) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
237
|
+
let {selects,nodes} = {
|
|
238
|
+
'DEPT':{
|
|
239
|
+
selects:selectPreview.value,
|
|
240
|
+
nodes:checkedNodes.value
|
|
241
|
+
},
|
|
242
|
+
'GW':{
|
|
243
|
+
selects:selectPreviewPost.value,
|
|
244
|
+
nodes:checkedPostNodes.value
|
|
245
|
+
},
|
|
246
|
+
'employee':{
|
|
247
|
+
selects:selectPreviewUser.value,
|
|
248
|
+
nodes:checkedUserNodes.value
|
|
249
|
+
}
|
|
250
|
+
}[item.type]
|
|
251
|
+
let index = selects.value.findIndex(i=>i.bindid === item.bindid);
|
|
252
|
+
const removedUser = selects.value[index];
|
|
253
|
+
selects.value.splice(index,1);
|
|
254
|
+
nodes.value = nodes.value.filter((value) => value !== removedUser.bindid)
|
|
225
255
|
}
|
|
226
256
|
|
|
227
257
|
// 移除选中项
|
|
@@ -248,13 +278,16 @@ watch(
|
|
|
248
278
|
watch(checkedUserNodes,nVal=>{
|
|
249
279
|
selectPreviewUser.value = employeeData.value.filter(i=>nVal.includes(i.bindid))
|
|
250
280
|
},{deep:true})
|
|
281
|
+
watch(checkedPostNodes,nVal=>{
|
|
282
|
+
selectPreviewPost.value = postData.value.filter(i=>nVal.includes(i.bindid))
|
|
283
|
+
},{deep:true})
|
|
251
284
|
// 监听modelValue变化,同步到选中节点
|
|
252
285
|
watch(
|
|
253
286
|
() => props.modelValue,
|
|
254
287
|
(newValue) => {
|
|
255
|
-
checkedNodes.value = newValue.filter(i=>i.type
|
|
288
|
+
checkedNodes.value = newValue.filter(i=>i.type === 'DEPT').map((item) => item.bindid);
|
|
256
289
|
checkedUserNodes.value = newValue.filter(i => i.type === 'employee').map((item) => item.bindid);
|
|
257
|
-
|
|
290
|
+
checkedPostNodes.value = newValue.filter(i=>i.type === 'GW').map(item=>item.bindid);
|
|
258
291
|
},
|
|
259
292
|
{ deep: true ,immediate:true}
|
|
260
293
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="user-info" :class="{ 'user-info-loading': state.loading }">
|
|
2
|
+
<div class="user-info" :class="{ 'user-info-loading': state.loading }" @click="handleClick">
|
|
3
3
|
<div v-if="state.loading && showLoading" class="user-loading">
|
|
4
4
|
<div class="loading-avatar"></div>
|
|
5
5
|
<div class="loading-text"></div>
|
|
@@ -7,17 +7,13 @@
|
|
|
7
7
|
<div v-else class="user-content" :class="layout">
|
|
8
8
|
<!-- 头像 -->
|
|
9
9
|
<div class="user-avatar" :class="avatarSize">
|
|
10
|
-
<img
|
|
11
|
-
|
|
12
|
-
:src="state.userInfo.avatar"
|
|
13
|
-
:alt="state.userInfo.name || '用户头像'"
|
|
14
|
-
@error="handleAvatarError"
|
|
15
|
-
/>
|
|
10
|
+
<img v-if="state.userInfo?.avatar" :src="state.userInfo.avatar" :alt="state.userInfo.name || '用户头像'"
|
|
11
|
+
@error="handleAvatarError" />
|
|
16
12
|
<div v-else class="default-avatar">
|
|
17
13
|
{{ getAvatarText() }}
|
|
18
14
|
</div>
|
|
19
15
|
</div>
|
|
20
|
-
|
|
16
|
+
|
|
21
17
|
<!-- 用户信息 -->
|
|
22
18
|
<div class="user-details" v-if="showDetails">
|
|
23
19
|
<div class="user-name" :class="nameSize">
|
|
@@ -39,48 +35,48 @@ import * as vue from 'vue'
|
|
|
39
35
|
import { defineProps, defineEmits } from 'vue'
|
|
40
36
|
|
|
41
37
|
const props = defineProps({
|
|
42
|
-
userId: {
|
|
43
|
-
type: String,
|
|
44
|
-
default: ''
|
|
38
|
+
userId: {
|
|
39
|
+
type: String,
|
|
40
|
+
default: ''
|
|
45
41
|
},
|
|
46
42
|
userInfo: {
|
|
47
43
|
type: Object,
|
|
48
44
|
default: null
|
|
49
45
|
},
|
|
50
|
-
layout: {
|
|
51
|
-
type: String,
|
|
46
|
+
layout: {
|
|
47
|
+
type: String,
|
|
52
48
|
default: 'horizontal', // horizontal, vertical
|
|
53
49
|
validator: (value) => ['horizontal', 'vertical'].includes(value)
|
|
54
50
|
},
|
|
55
|
-
avatarSize: {
|
|
56
|
-
type: String,
|
|
51
|
+
avatarSize: {
|
|
52
|
+
type: String,
|
|
57
53
|
default: 'medium', // small, medium, large
|
|
58
54
|
validator: (value) => ['small', 'medium', 'large'].includes(value)
|
|
59
55
|
},
|
|
60
|
-
nameSize: {
|
|
61
|
-
type: String,
|
|
56
|
+
nameSize: {
|
|
57
|
+
type: String,
|
|
62
58
|
default: 'normal', // small, normal, large
|
|
63
59
|
validator: (value) => ['small', 'normal', 'large'].includes(value)
|
|
64
60
|
},
|
|
65
|
-
showDetails: {
|
|
66
|
-
type: Boolean,
|
|
67
|
-
default: true
|
|
61
|
+
showDetails: {
|
|
62
|
+
type: Boolean,
|
|
63
|
+
default: true
|
|
68
64
|
},
|
|
69
|
-
showJobNumber: {
|
|
70
|
-
type: Boolean,
|
|
71
|
-
default: true
|
|
65
|
+
showJobNumber: {
|
|
66
|
+
type: Boolean,
|
|
67
|
+
default: true
|
|
72
68
|
},
|
|
73
|
-
showDepartment: {
|
|
74
|
-
type: Boolean,
|
|
75
|
-
default: false
|
|
69
|
+
showDepartment: {
|
|
70
|
+
type: Boolean,
|
|
71
|
+
default: false
|
|
76
72
|
},
|
|
77
|
-
showLoading: {
|
|
78
|
-
type: Boolean,
|
|
79
|
-
default: false
|
|
73
|
+
showLoading: {
|
|
74
|
+
type: Boolean,
|
|
75
|
+
default: false
|
|
80
76
|
},
|
|
81
|
-
clickable: {
|
|
82
|
-
type: Boolean,
|
|
83
|
-
default: false
|
|
77
|
+
clickable: {
|
|
78
|
+
type: Boolean,
|
|
79
|
+
default: false
|
|
84
80
|
}
|
|
85
81
|
})
|
|
86
82
|
|
|
@@ -106,6 +102,16 @@ const state = vue.reactive({
|
|
|
106
102
|
error: null
|
|
107
103
|
})
|
|
108
104
|
|
|
105
|
+
import { wwJsSdk } from "../../index"
|
|
106
|
+
const handleClick = () => {
|
|
107
|
+
wwJsSdk((ww) => {
|
|
108
|
+
ww.openUserProfile({
|
|
109
|
+
type: 1,
|
|
110
|
+
userid: employeeInfo.value.no
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
109
115
|
// 获取头像文字(取姓名最后一个字符)
|
|
110
116
|
const getAvatarText = () => {
|
|
111
117
|
const name = state.userInfo?.name || props.userId || '?'
|
|
@@ -331,6 +337,7 @@ vue.watch(
|
|
|
331
337
|
0% {
|
|
332
338
|
background-position: 200% 0;
|
|
333
339
|
}
|
|
340
|
+
|
|
334
341
|
100% {
|
|
335
342
|
background-position: -200% 0;
|
|
336
343
|
}
|
|
@@ -340,4 +347,4 @@ vue.watch(
|
|
|
340
347
|
.user-content.vertical .user-details {
|
|
341
348
|
align-items: center;
|
|
342
349
|
}
|
|
343
|
-
</style>
|
|
350
|
+
</style>
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
</div>
|
|
170
170
|
|
|
171
171
|
<!-- 表格 -->
|
|
172
|
-
<t-table :data="computedModelValue" :columns="computedTableColumns"
|
|
172
|
+
<t-table :data="computedModelValue" :columns="computedTableColumns"
|
|
173
173
|
row-key="__id" size="small" bordered :empty="'暂无数据'">
|
|
174
174
|
<!-- 序号列 -->
|
|
175
175
|
<template #index="{ rowIndex }">
|
|
@@ -192,12 +192,18 @@
|
|
|
192
192
|
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
193
193
|
|
|
194
194
|
<!-- 选择器 -->
|
|
195
|
-
<t-select v-else-if="col.type === 'select'" v-model="row[col.key]" :disabled="disabled"
|
|
195
|
+
<t-select v-else-if="col.type === 'select' && col.isRemote !== true" v-model="row[col.key]" :disabled="disabled"
|
|
196
196
|
:placeholder="col.placeholder || `请选择${col.name}`" :options="col.options || []"
|
|
197
197
|
:clearable="col.clearable !== false" :filterable="col.filterable"
|
|
198
198
|
:multiple="col.multiple"
|
|
199
199
|
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
200
200
|
|
|
201
|
+
<!-- 远程搜索 -->
|
|
202
|
+
<ebiz-remote-select v-else-if="col.type === 'select' && col.isRemote === true" v-model="row[col.key]" :queryParams="col.queryParams"
|
|
203
|
+
:placeholder="col.placeholder || `请选择${col.name}`" :disabled="disabled" :clearable="col.clearable !== false"
|
|
204
|
+
:filterable="true" :multiple="col.multiple" :apiConfig="col.remoteApiConfig"
|
|
205
|
+
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
206
|
+
|
|
201
207
|
<!-- 日期选择器 -->
|
|
202
208
|
<t-date-picker v-else-if="col.type === 'date'" v-model="row[col.key]"
|
|
203
209
|
:disabled="disabled" :placeholder="col.placeholder || `请选择${col.name}`"
|
|
@@ -231,6 +237,11 @@
|
|
|
231
237
|
:disabled="disabled" :options="col.options || []" :max="col.max"
|
|
232
238
|
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
233
239
|
|
|
240
|
+
<ebiz-employee-selector v-else-if="col.type === 'employee'" v-model="row[col.key]"
|
|
241
|
+
:placeholder="col.placeholder || '请选择员工'" :disabled="disabled"
|
|
242
|
+
:clearable="col.clearable !== false" :single="col.single" :defaultTab="col.defaultTab"
|
|
243
|
+
:maxCount="col.maxCount" @update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
244
|
+
|
|
234
245
|
<!-- 默认文本显示 -->
|
|
235
246
|
<span v-else>{{ row[col.key] || '' }}</span>
|
|
236
247
|
</template>
|
|
@@ -301,6 +312,7 @@ import EbizEmployeeSelector from '../../EbizEmployeeSelector.vue';
|
|
|
301
312
|
import EbizDepartmentSelector from '../../EbizDepartmentSelector.vue';
|
|
302
313
|
import { EbizUpload } from '../../../index.js'
|
|
303
314
|
import EbizRichTextEditor from '../../EbizRichTextEditor.vue';
|
|
315
|
+
import EbizDictionarySelect from '../../EbizDictionarySelect.vue';
|
|
304
316
|
|
|
305
317
|
const props = defineProps({
|
|
306
318
|
/**
|