feat: 新增考勤,请假,出差的管理页面

This commit is contained in:
砂糖
2025-08-06 17:09:15 +08:00
parent 86f40f2a9a
commit 4c1b88dfc7
8 changed files with 1684 additions and 500 deletions

View File

@@ -0,0 +1,139 @@
<template>
<el-tree-select
:model-value="modelVal"
:data="treeData"
style="width: 300px;"
:props="defaultProps"
searchable
clearable
v-bind="$attrs"
@update:model-value="updateValue"
@change="handleChange"
/>
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
import { listDept } from '@/api/system/dept'
import { listUser } from '@/api/system/user'
defineOptions({
name: 'UserSelect'
})
const emit = defineEmits(['update:modelValue', 'change'])
const props = defineProps({
modelValue: {
type: [String, Number, Array],
default: undefined
},
// 是否只选择用户false 表示部门也可以选择
userOnly: {
type: Boolean,
default: false
},
// 是否多选
multiple: {
type: Boolean,
default: false
}
})
const treeData = ref([])
const defaultProps = {
value: 'id',
label: 'label',
children: 'children'
}
// 加载部门和用户数据
const loadData = async () => {
try {
// 获取部门列表
const { data: deptList } = await listDept()
// 获取用户列表
const { rows: userList } = await listUser()
// 转换部门数据
const transformedDeptList = deptList.map(dept => ({
id: `dept_${dept.deptId}`,
label: dept.deptName,
parentId: dept.parentId === 0 ? null : `dept_${dept.parentId}`,
type: 'dept'
}))
// 转换用户数据
const transformedUserList = userList.map(user => ({
id: `user_${user.userId}`,
label: user.nickName || user.userName,
parentId: `dept_${user.deptId}`,
type: 'user'
}))
// 如果只选择用户,过滤掉部门节点
let allNodes = props.userOnly
? transformedUserList
: [...transformedDeptList, ...transformedUserList]
// 构建树形结构
treeData.value = buildTree(allNodes)
} catch (error) {
console.error('加载数据失败:', error)
}
}
// 构建树形结构
const buildTree = (nodes) => {
const map = {}
const result = []
// 创建节点映射
nodes.forEach(node => {
map[node.id] = { ...node, children: [] }
})
// 构建树形关系
nodes.forEach(node => {
const current = map[node.id]
if (node.parentId) {
const parent = map[node.parentId]
if (parent) {
parent.children.push(current)
}
} else {
result.push(current)
}
})
return result
}
// 使用计算属性处理双向绑定
const modelVal = computed({
get: () => props.modelValue,
set: (value) => {
emit('update:modelValue', value)
}
})
// 处理值更新
const updateValue = (value) => {
modelVal.value = value
}
// 处理选择变化
const handleChange = (value) => {
emit('change', value)
}
// 组件挂载时加载数据
onMounted(() => {
loadData()
})
</script>
<style scoped>
.el-tree-select {
width: 100%;
}
</style>