|
@@ -1,11 +1,452 @@
|
|
|
<template>
|
|
|
- <div>
|
|
|
- 团队
|
|
|
+ <div class="h-full flex flex-col teamstyle">
|
|
|
+ <!-- 头部 -->
|
|
|
+ <div class="bg-white flex justify-between team-header">
|
|
|
+ <div class="flex items-center">
|
|
|
+ <el-link type="primary" class="text-nowrap mr-20" :icon="CirclePlusFilled"
|
|
|
+ @click="dialogFromCli('addDeptDialogVisible')">创建部门</el-link>
|
|
|
+ <el-link class="text-nowrap textFont textFont mr-10" type="primary" :icon="Edit"
|
|
|
+ @click="updateDepartment('addDeptDialogVisible')">{{ deptListItem.label || '全部人员' }}</el-link>
|
|
|
+ <span class="textSpan">共 0 人</span>
|
|
|
+ </div>
|
|
|
+ <div class="teamForm flex items-center">
|
|
|
+ <el-input v-model="teamForm.keyword" style="max-width: 650px" size="default" placeholder="请输入姓名搜索" class="mr-6">
|
|
|
+ <template #prepend>
|
|
|
+ <el-select v-model="teamForm.matchingType" style="width: 80px">
|
|
|
+ <el-option label="姓名" :value="0" />
|
|
|
+ <el-option label="电话" :value="1" />
|
|
|
+ <el-option label="工号" :value="2" />
|
|
|
+ </el-select>
|
|
|
+ </template>
|
|
|
+ <template #append>
|
|
|
+ <el-button :icon="Search" />
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+
|
|
|
+ <div class="formItem mr-6 flex items-center">
|
|
|
+ <div class="text-nowrap">状态:</div>
|
|
|
+ <el-select v-model="teamForm.status" placeholder="请选择" size="default" style="width: 100px">
|
|
|
+ <el-option v-for="item in stateOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="formItem mr-6 flex items-center">
|
|
|
+ <div class="text-nowrap">角色:</div>
|
|
|
+ <el-select v-model="teamForm.roleId" placeholder="请选择" size="default" style="width: 150px">
|
|
|
+ <el-option v-for="item in roleList" :key="item.id" :label="item.rolename" :value="item.id" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-dropdown>
|
|
|
+ <el-button type="primary">
|
|
|
+ 更多操作<el-icon class="el-icon--right"><arrow-down /></el-icon>
|
|
|
+ </el-button>
|
|
|
+ <template #dropdown>
|
|
|
+ <el-dropdown-menu>
|
|
|
+ <el-dropdown-item @click="addPersone(false)">添加人员</el-dropdown-item>
|
|
|
+ <el-dropdown-item>导出人员</el-dropdown-item>
|
|
|
+ <el-dropdown-item>批量导入</el-dropdown-item>
|
|
|
+ <el-dropdown-item>导入薪资</el-dropdown-item>
|
|
|
+ <el-dropdown-item>自定义配置</el-dropdown-item>
|
|
|
+ </el-dropdown-menu>
|
|
|
+ </template>
|
|
|
+ </el-dropdown>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 内容 -->
|
|
|
+ <div class="flex-1 flex">
|
|
|
+ <div class="p-5 w-80 pr-0">
|
|
|
+ <div class="bg-white w-full h-full shadow-md rounded-md flex flex-col">
|
|
|
+ <div class="flex-1 overflow-y-auto const-left">
|
|
|
+ <el-tree style="max-width: 600px" :data="deptList" :props="treeProps" @node-click="treeNode">
|
|
|
+ <template #default="{ node, data }">
|
|
|
+ <div class="flex justify-between treeContent">
|
|
|
+ <div class="custom-tree-node">
|
|
|
+ <div class="treeLabel">{{ node.label }}</div>
|
|
|
+ <div class="treeIcon" v-if="data.id > 0">
|
|
|
+ <el-link type="primary" :icon="CirclePlus" :underline="false"
|
|
|
+ @click.stop="dialogFromCli('addDeptDialogVisible', data, true)"></el-link>
|
|
|
+ <el-link type="primary" :icon="Delete" :underline="false" style="margin-left: 6px;"
|
|
|
+ @click.stop="deteleDept(data)"></el-link>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-tree>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="flex-1 p-5 overflow-auto">
|
|
|
+ <div class="bg-white w-full h-full shadow-md rounded-md flex flex-col">
|
|
|
+ <div class="flex-1 p-3">
|
|
|
+ <el-table ref="multipleTableRef" :data="tableData" v-loading="loadingFrom.tableLoading"
|
|
|
+ style="width: 100%;height: 100%;">
|
|
|
+ <el-table-column type="selection" width="55" />
|
|
|
+ <el-table-column label="姓名" property="name" width="150"></el-table-column>
|
|
|
+ <el-table-column label="手机" property="phone" ></el-table-column>
|
|
|
+ <el-table-column label="工号" property="jobNumber"></el-table-column>
|
|
|
+ <el-table-column label="部门" property="departmentName"></el-table-column>
|
|
|
+ <el-table-column label="角色" property="roleName"></el-table-column>
|
|
|
+ <el-table-column label="创建时间" property="createTime"></el-table-column>
|
|
|
+ <el-table-column label="操作" width="150" fixed="right">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-button :size="'small'">重置</el-button>
|
|
|
+ <el-button type="primary" :size="'small'" @click="addPersone(scope.row)">编辑</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ <div class="flex items-center justify-between p-3 bg-slate-100">
|
|
|
+ <div class="flex">
|
|
|
+ <el-button size="default">取消</el-button>
|
|
|
+ <el-dropdown class="ml-3">
|
|
|
+ <el-button type="primary">
|
|
|
+ 更多操作<el-icon class="el-icon--right"><arrow-down /></el-icon>
|
|
|
+ </el-button>
|
|
|
+ <template #dropdown>
|
|
|
+ <el-dropdown-menu>
|
|
|
+ <el-dropdown-item>批量修改部门</el-dropdown-item>
|
|
|
+ <el-dropdown-item>批量修改角色</el-dropdown-item>
|
|
|
+ <el-dropdown-item>修正工时所属部门</el-dropdown-item>
|
|
|
+ <el-dropdown-item>批量启用员工</el-dropdown-item>
|
|
|
+ </el-dropdown-menu>
|
|
|
+ </template>
|
|
|
+ </el-dropdown>
|
|
|
+ </div>
|
|
|
+ <div class="pr-4">
|
|
|
+ <el-pagination layout="total, prev, pager, next, sizes" :total="totalTable" :hide-on-single-page="true" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 新增部门 -->
|
|
|
+ <el-dialog v-model="dialogFrom.addDeptDialogVisible" :title="deptListItem.label || '创建部门'" width="500"
|
|
|
+ :before-close="handleClose">
|
|
|
+ <div>
|
|
|
+ <el-form ref="deptRuleFormRef" style="max-width: 500px" :model="deptForm" :rules="deptRules" label-width="auto"
|
|
|
+ size="large" status-icon>
|
|
|
+ <el-form-item label="部门名称" prop="name">
|
|
|
+ <el-input v-model="deptForm.name" placeholder="请输入部门名称" clearable />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="主要负责人">
|
|
|
+ <el-select v-model="deptForm.managerId" placeholder="请选择" style="width: 100%" clearable>
|
|
|
+ <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="其他负责人">
|
|
|
+ <el-select v-model="deptForm.otherManagerIds" placeholder="请选择" style="width: 100%" multiple clearable>
|
|
|
+ <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button @click="dialogFrom.addDeptDialogVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="createDepartment(deptRuleFormRef)"
|
|
|
+ v-bind:loading="loadingFrom.deptDialogVisibleLoading">
|
|
|
+ 确定
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 新增人员 -->
|
|
|
+ <AddPersonnelModal :data="{
|
|
|
+ addPersonnelDialogVisible: dialogFrom.addPersonnelDialogVisible,
|
|
|
+ deptList: deptListUntreated,
|
|
|
+ roleList: roleList,
|
|
|
+ personnelFromData: personnelFromData
|
|
|
+ }" @closeModal="closeModal" @personnelModalConfirm="personnelModalConfirm" />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
+import { ref, reactive, onMounted, onBeforeMount, inject } from 'vue';
|
|
|
+import { dayjs } from 'element-plus'
|
|
|
+import { Search, CirclePlusFilled, Edit, CirclePlus, Delete } from '@element-plus/icons-vue'
|
|
|
+import { FormInstance, FormRules, ElMessageBox } from 'element-plus'
|
|
|
+import { useStore } from '@/store/index'
|
|
|
+import { GET_DATA_LIST, DETELE_DEPT, MOD, GET_USERINFO, GET_ROUTELIST, GET_DEPTLIST, GET_USERLIST, GET_ADDDEPT, ADD_USER } from './api'
|
|
|
+import { post } from "@/utils/request";
|
|
|
+import { getFromValue, updateDepTreeData, resetFromValue } from '@/utils/tools'
|
|
|
+
|
|
|
+// 导入页面
|
|
|
+import AddPersonnelModal from './module/AddPersonnelModal.vue'
|
|
|
+
|
|
|
+const { getFunctionList, getUserInfoVal } = useStore()
|
|
|
+const globalPopup = inject<GlobalPopup>('globalPopup')
|
|
|
+
|
|
|
+// 定义类型
|
|
|
+interface deptRuleForm { // 部门表单类型
|
|
|
+ name: string,
|
|
|
+ id: string | number,
|
|
|
+ parentId: string | number,
|
|
|
+ managerId: string | number,
|
|
|
+ otherManagerIds: string[] | number[],
|
|
|
+}
|
|
|
+
|
|
|
+// 固定数据
|
|
|
+const stateOptions = [{ value: '3', label: '全部' }, { value: '1', label: '在职' }, { value: '0', label: '停用' }]
|
|
|
+
|
|
|
+// 定义变量
|
|
|
+const pagePermission: any = ref([]) // 功能权限
|
|
|
+const loadingFrom = reactive({ // 所有加载状态
|
|
|
+ tableLoading: false,
|
|
|
+ deptDialogVisibleLoading: false
|
|
|
+})
|
|
|
+const dialogFrom: any = reactive({ // 所有弹窗状态
|
|
|
+ addDeptDialogVisible: false,
|
|
|
+ addPersonnelDialogVisible: false
|
|
|
+});
|
|
|
+const totalTable = ref(0) // 表格总数
|
|
|
+const tableData: any = ref([]) // 表格数据
|
|
|
+const roleList: any = ref([]) // 角色列表
|
|
|
+const userList: any = ref([]) // 用户列表
|
|
|
+const deptList: any = ref([]) // 部门数据
|
|
|
+const deptListUntreated: any = ref([]) // 部门数据(未处理)
|
|
|
+const deptListItem: any = ref({}) // 选中的部门数据
|
|
|
+const personnelFromData = ref({}) // 人员表单数据
|
|
|
+const teamForm = reactive({ // 筛选条件表单
|
|
|
+ matchingType: 0,
|
|
|
+ keyword: '',
|
|
|
+ status: '3',
|
|
|
+ pageIndex: 1,
|
|
|
+ pageSize: 20,
|
|
|
+ roleId: '',
|
|
|
+ onlyDirect: '',
|
|
|
+ departmentId: '-1',
|
|
|
+});
|
|
|
+const deptRuleFormRef = ref<FormInstance>() // 表单实例
|
|
|
+const deptForm = reactive<deptRuleForm>({ // 部门表单
|
|
|
+ name: '',
|
|
|
+ id: '',
|
|
|
+ parentId: '',
|
|
|
+ managerId: '',
|
|
|
+ otherManagerIds: [],
|
|
|
+})
|
|
|
+const treeProps = { // 部门树配置
|
|
|
+ children: 'children',
|
|
|
+ label: 'label',
|
|
|
+}
|
|
|
+
|
|
|
+// 定义校验规则
|
|
|
+const deptRules = reactive<FormRules<typeof deptForm>>({ // 部门表单校验规则
|
|
|
+ name: [{ required: true, trigger: 'blur', message: '请输入部门名称' }]
|
|
|
+})
|
|
|
+
|
|
|
+// 定义方法
|
|
|
+function addPersone(item: any) {
|
|
|
+ console.log(item)
|
|
|
+ if(!item) {
|
|
|
+ dialogFrom.addPersonnelDialogVisible = true
|
|
|
+ return
|
|
|
+ }
|
|
|
+ post(GET_USERINFO, { userId: item.id }).then(res => {
|
|
|
+ const { id, name, phone, jobNumber, roleId, departmentCascade, inductionDate } = res.data
|
|
|
+ let newData = { id, name, phone, jobNumber, roleId, departmentId:
|
|
|
+ departmentCascade && departmentCascade.split(',').map(Number).reverse(),
|
|
|
+ inductionDate
|
|
|
+ }
|
|
|
+ personnelFromData.value = newData
|
|
|
+ dialogFrom.addPersonnelDialogVisible = true
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+async function personnelModalConfirm(data: any, modelType: string) {
|
|
|
+ post(ADD_USER, { ...data }).then(res => {
|
|
|
+ if (res.code != 'ok') {
|
|
|
+ dialogFrom[modelType] = false
|
|
|
+ globalPopup?.showError(res.msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ dialogFrom[modelType] = false
|
|
|
+ globalPopup?.showSuccess('添加成功')
|
|
|
+ getTableData()
|
|
|
+ }).catch(_err => {
|
|
|
+ dialogFrom[modelType] = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function createDepartment(formEl: FormInstance | undefined) {
|
|
|
+ if (!formEl) return
|
|
|
+ let data = getFromValue(deptForm)
|
|
|
+ loadingFrom.deptDialogVisibleLoading = true
|
|
|
+ post(GET_ADDDEPT, { ...deptForm, otherManagerIds: data.otherManagerIds && data.otherManagerIds.join(',') }).then(res => {
|
|
|
+ if (res.code != 'ok') {
|
|
|
+ loadingFrom.deptDialogVisibleLoading = false
|
|
|
+ globalPopup?.showError(res.msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ loadingFrom.deptDialogVisibleLoading = false
|
|
|
+ globalPopup?.showSuccess('创建成功')
|
|
|
+ getDeptList()
|
|
|
+ dialogFrom.addDeptDialogVisible = false
|
|
|
+ }).catch(_err => {
|
|
|
+ loadingFrom.deptDialogVisibleLoading = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function updateDepartment(type: string) {
|
|
|
+ if (!deptListItem.value.id || deptListItem.value.id <= 0) return
|
|
|
+ const { id, label, parentId, managerId, otherManagerIds } = deptListItem.value
|
|
|
+ console.log(deptListItem.value)
|
|
|
+ let data = { id, name: label, parentId, managerId, otherManagerIds }
|
|
|
+ Object.assign(deptForm, data)
|
|
|
+ dialogFrom[type] = true
|
|
|
+}
|
|
|
+
|
|
|
+function treeNode(item: any) {
|
|
|
+ deptListItem.value = item
|
|
|
+ teamForm.departmentId = item.id
|
|
|
+ getTableData()
|
|
|
+}
|
|
|
+
|
|
|
+function deteleDept(data: any) {
|
|
|
+ console.log(data)
|
|
|
+ ElMessageBox.confirm(
|
|
|
+ `确定删除【${data.label}】部门吗?`, '',
|
|
|
+ {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning',
|
|
|
+ }
|
|
|
+ )
|
|
|
+ .then(() => {
|
|
|
+ post(DETELE_DEPT, { id: data.id }).then(res => {
|
|
|
+ if (res.code != 'ok') {
|
|
|
+ globalPopup?.showError(res.msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ globalPopup?.showSuccess('删除成功')
|
|
|
+ getDeptList()
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
|
|
|
+function getTableData() {
|
|
|
+ loadingFrom.tableLoading = true
|
|
|
+ post(GET_DATA_LIST, { ...teamForm }).then(res => {
|
|
|
+ if (res.code != 'ok') {
|
|
|
+ loadingFrom.tableLoading = false
|
|
|
+ globalPopup?.showError(res.msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ loadingFrom.tableLoading = false
|
|
|
+ totalTable.value = res.data.total
|
|
|
+ tableData.value = res.data.records
|
|
|
+ }).catch(_err => {
|
|
|
+ loadingFrom.tableLoading = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function getRoleList() {
|
|
|
+ const companyId = getUserInfoVal('companyId') || ''
|
|
|
+ post(GET_ROUTELIST, { companyId }).then(res => {
|
|
|
+ if (res.code != 'ok') {
|
|
|
+ globalPopup?.showError(res.msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ roleList.value = res.data
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function getDeptList() {
|
|
|
+ post(GET_DEPTLIST, {}).then(res => {
|
|
|
+ if (res.code != 'ok') {
|
|
|
+ globalPopup?.showError(res.msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ deptListUntreated.value = updateDepTreeData(res.data, false)
|
|
|
+ deptList.value = updateDepTreeData(res.data, true)
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function getUserList() {
|
|
|
+ post(GET_USERLIST, {}).then(res => {
|
|
|
+ if (res.code != 'ok') {
|
|
|
+ globalPopup?.showError(res.msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ userList.value = res.data
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function dialogFromCli(type: string, data: any = {}, flag: boolean = false) {
|
|
|
+ resetDialog()
|
|
|
+ if (flag) {
|
|
|
+ const { id } = data
|
|
|
+ deptForm.parentId = id
|
|
|
+ }
|
|
|
+ dialogFrom[type] = true
|
|
|
+}
|
|
|
+
|
|
|
+function resetDialog() {
|
|
|
+ let newDeptForm = resetFromValue(deptForm)
|
|
|
+ Object.assign(deptForm, newDeptForm)
|
|
|
+}
|
|
|
+
|
|
|
+function handleClose(done: any) {
|
|
|
+ done()
|
|
|
+}
|
|
|
+
|
|
|
+function closeModal(modelType: string) {
|
|
|
+ dialogFrom[modelType] = false
|
|
|
+}
|
|
|
+
|
|
|
+onBeforeMount(() => {
|
|
|
+ pagePermission.value = getFunctionList(MOD)
|
|
|
+})
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getRoleList()
|
|
|
+ getUserList()
|
|
|
+ getTableData()
|
|
|
+ getDeptList()
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
-<style lang="scss" scoped></style>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.teamstyle {
|
|
|
+ .team-header {
|
|
|
+ padding: 0.75rem 1.25rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .textFont {
|
|
|
+ font-size: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .textSpan {
|
|
|
+ color: $fontGray;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.const-left {
|
|
|
+ padding: 0.75rem 0;
|
|
|
+
|
|
|
+ .treeContent {
|
|
|
+ width: 87%;
|
|
|
+
|
|
|
+ .custom-tree-node {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .treeLabel {
|
|
|
+ width: 80%;
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ }
|
|
|
+
|
|
|
+ .treeIcon {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-self: flex-end;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|