|
|
@@ -82,6 +82,23 @@
|
|
|
:value="p.id"
|
|
|
/>
|
|
|
</el-select>
|
|
|
+ <el-tree-select
|
|
|
+ v-else-if="isDeptLikeField(rule.field)"
|
|
|
+ :model-value="personValueIds(rule.value)"
|
|
|
+ multiple
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ check-strictly
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ default-expand-all
|
|
|
+ :data="deptTreeData"
|
|
|
+ :props="{ value: 'value', label: 'label', children: 'children' }"
|
|
|
+ placeholder="选择部门(任一命中)"
|
|
|
+ :disabled="disabled"
|
|
|
+ class="cond-rule-editor__dept-select"
|
|
|
+ @update:model-value="(v) => onValueChange(idx, Array.isArray(v) ? v.map(String) : [])"
|
|
|
+ />
|
|
|
<el-select
|
|
|
v-else-if="optionsFor(rule.field)?.length"
|
|
|
:model-value="rule.value"
|
|
|
@@ -132,7 +149,7 @@
|
|
|
<script setup lang="ts">
|
|
|
import { computed, onMounted, ref, watch } from 'vue'
|
|
|
import { Delete, Plus } from '@element-plus/icons-vue'
|
|
|
- import { fetchPostList, fetchUserList } from '@/api/admin'
|
|
|
+ import { fetchDeptTree, fetchPostList, fetchUserList } from '@/api/admin'
|
|
|
import { MAX_ADMIN_LIST_PAGE_SIZE } from '@/utils/fetch-paged-list'
|
|
|
import {
|
|
|
opsForFieldType,
|
|
|
@@ -166,6 +183,10 @@
|
|
|
const userOptions = ref<Array<{ id: string; label: string }>>([])
|
|
|
const postOptions = ref<Array<{ id: string; label: string }>>([])
|
|
|
|
|
|
+ type DeptTreeNode = { value: string; label: string; children?: DeptTreeNode[] }
|
|
|
+
|
|
|
+ const deptTreeData = ref<DeptTreeNode[]>([])
|
|
|
+
|
|
|
function meta(field: string) {
|
|
|
return props.candidates.find((c) => c.field === field)
|
|
|
}
|
|
|
@@ -179,6 +200,19 @@
|
|
|
return meta(field)?.type === 'post'
|
|
|
}
|
|
|
|
|
|
+ function isDeptLikeField(field: string) {
|
|
|
+ const t = meta(field)?.type
|
|
|
+ return t === 'dept' || t === 'ownerDept'
|
|
|
+ }
|
|
|
+
|
|
|
+ function mapDeptTree(nodes: Api.Dept.DeptItem[]): DeptTreeNode[] {
|
|
|
+ return (nodes || []).map((n) => ({
|
|
|
+ value: String(n.id),
|
|
|
+ label: String(n.deptName || n.id),
|
|
|
+ children: n.children?.length ? mapDeptTree(n.children) : undefined
|
|
|
+ }))
|
|
|
+ }
|
|
|
+
|
|
|
function personValueIds(v: unknown): string[] {
|
|
|
if (Array.isArray(v)) return v.map(String)
|
|
|
if (v == null || v === '') return []
|
|
|
@@ -186,7 +220,14 @@
|
|
|
}
|
|
|
|
|
|
function defaultValueForType(type: string, opts?: ConditionCandidate['options']) {
|
|
|
- if (type === 'person' || type === 'ownerPerson' || type === 'post' || type === 'initiator') {
|
|
|
+ if (
|
|
|
+ type === 'person' ||
|
|
|
+ type === 'ownerPerson' ||
|
|
|
+ type === 'dept' ||
|
|
|
+ type === 'ownerDept' ||
|
|
|
+ type === 'post' ||
|
|
|
+ type === 'initiator'
|
|
|
+ ) {
|
|
|
return [] as string[]
|
|
|
}
|
|
|
return opts?.[0]?.value ?? ''
|
|
|
@@ -336,6 +377,15 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ async function loadDepts() {
|
|
|
+ try {
|
|
|
+ const tree = (await fetchDeptTree()) || []
|
|
|
+ deptTreeData.value = mapDeptTree(tree as Api.Dept.DeptItem[])
|
|
|
+ } catch {
|
|
|
+ deptTreeData.value = []
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
onMounted(() => {
|
|
|
if (props.candidates.some((c) => c.type === 'person' || c.type === 'ownerPerson' || c.type === 'initiator')) {
|
|
|
loadUsers()
|
|
|
@@ -343,6 +393,9 @@
|
|
|
if (props.candidates.some((c) => c.type === 'post')) {
|
|
|
loadPosts()
|
|
|
}
|
|
|
+ if (props.candidates.some((c) => c.type === 'dept' || c.type === 'ownerDept')) {
|
|
|
+ loadDepts()
|
|
|
+ }
|
|
|
})
|
|
|
|
|
|
watch(
|
|
|
@@ -361,6 +414,13 @@
|
|
|
if (need && !postOptions.value.length) loadPosts()
|
|
|
}
|
|
|
)
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => props.candidates.some((c) => c.type === 'dept' || c.type === 'ownerDept'),
|
|
|
+ (need) => {
|
|
|
+ if (need && !deptTreeData.value.length) loadDepts()
|
|
|
+ }
|
|
|
+ )
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
@@ -404,4 +464,8 @@
|
|
|
.cond-rule-editor__post-select :deep(.el-select__selection) {
|
|
|
flex-wrap: wrap;
|
|
|
}
|
|
|
+
|
|
|
+ .cond-rule-editor__dept-select :deep(.el-select__selection) {
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
</style>
|