|
|
@@ -0,0 +1,658 @@
|
|
|
+<template>
|
|
|
+ <el-dialog :title="title" :visible.sync="dialogVisible" :width="width" :top="top" append-to-body
|
|
|
+ @close="handleClose">
|
|
|
+ <div class="user-select-container">
|
|
|
+ <div class="department-panel">
|
|
|
+ <div class="panel-header">
|
|
|
+ <h4>请选择部门</h4>
|
|
|
+ </div>
|
|
|
+ <el-tree ref="tree" v-loading="deptLoading" :data="departmentData" :props="defaultProps" node-key="id"
|
|
|
+ @node-click="handleNodeClick" :highlight-current="true"
|
|
|
+ :default-expand-all="defaultExpandAll"
|
|
|
+ class="department-tree"></el-tree>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="user-panel">
|
|
|
+ <div class="selected-users" v-if="selectedUsers && selectedUsers.length > 0">
|
|
|
+ <div class="selected-header">
|
|
|
+ <span>已选中人员 ({{ selectedUsers.length }})</span>
|
|
|
+ </div>
|
|
|
+ <div class="selected-list">
|
|
|
+ <el-tag v-for="(user, index) in selectedUsers" :key="user.userId" closable
|
|
|
+ @close="removeSelectedUser(user, index)" class="selected-tag">
|
|
|
+ {{ user.nickName || user.userName }}
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 暂时注释掉搜索功能 -->
|
|
|
+ <!-- <div class="search-form">
|
|
|
+ <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
|
|
|
+ <el-form-item label="用户名称" prop="userName">
|
|
|
+ <el-input v-model="searchText" placeholder="请输入用户名称" clearable
|
|
|
+ @keyup.enter.native="handleSearch" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" icon="el-icon-search" size="mini"
|
|
|
+ @click="handleSearch">搜索</el-button>
|
|
|
+ <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div> -->
|
|
|
+
|
|
|
+ <!-- 暂时注释掉搜索结果展示 -->
|
|
|
+ <!-- <div class="search-results" v-if="searchText && filteredUsers.length > 0">
|
|
|
+ <div class="result-header">
|
|
|
+ <span>搜索结果 ({{ filteredUsers.length }})</span>
|
|
|
+ </div>
|
|
|
+ <el-table v-loading="userLoading" @row-click="clickRow" ref="table" :data="paginatedSearchResults"
|
|
|
+ @selection-change="handleSelectionChange" style="flex: 1">
|
|
|
+ <el-table-column type="selection" width="55"></el-table-column>
|
|
|
+ <el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="状态" align="center" prop="status">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <div class="pagination-container">
|
|
|
+ <pagination v-show="searchTotal > 0" :total="searchTotal" :page.sync="queryParams.pageNum"
|
|
|
+ :limit.sync="queryParams.pageSize" @pagination="() => { }" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="empty-state" v-else-if="searchText">
|
|
|
+ <i class="el-icon-warning"></i>
|
|
|
+ <p>未找到匹配的用户</p>
|
|
|
+ </div> -->
|
|
|
+
|
|
|
+ <div class="user-table" v-if="currentDepartment">
|
|
|
+ <el-table v-loading="userLoading" @row-click="clickRow" ref="table" :data="userList"
|
|
|
+ @selection-change="handleSelectionChange" style="flex: 1">
|
|
|
+ <el-table-column type="selection" width="55"></el-table-column>
|
|
|
+ <el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="状态" align="center" prop="status">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <div class="pagination-container">
|
|
|
+ <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
|
|
|
+ :limit.sync="queryParams.pageSize" @pagination="getUsers" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="empty-state" v-if="!currentDepartment">
|
|
|
+ <i class="el-icon-warning"></i>
|
|
|
+ <p>请先选择一个部门</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="handleConfirm">确 定</el-button>
|
|
|
+ <el-button @click="handleCancel">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { listUser, deptTreeSelect } from "@/api/system/user";
|
|
|
+export default {
|
|
|
+ name: "DepartmentUserSelect",
|
|
|
+ dicts: ['sys_normal_disable'],
|
|
|
+ props: {
|
|
|
+ visible: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ title: {
|
|
|
+ type: String,
|
|
|
+ default: "分配用户"
|
|
|
+ },
|
|
|
+ width: {
|
|
|
+ type: String,
|
|
|
+ default: "900px"
|
|
|
+ },
|
|
|
+ top: {
|
|
|
+ type: String,
|
|
|
+ default: "5vh"
|
|
|
+ },
|
|
|
+ defaultExpandAll: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true
|
|
|
+ },
|
|
|
+ departments: {
|
|
|
+ type: Array,
|
|
|
+ default: () => []
|
|
|
+ },
|
|
|
+ extraParams: {
|
|
|
+ type: Object,
|
|
|
+ default: () => ({})
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ dialogVisible: false,
|
|
|
+ selectedUserIds: [],
|
|
|
+ selectedUsers: [],
|
|
|
+ total: 0,
|
|
|
+ userList: [],
|
|
|
+ currentDepartment: null,
|
|
|
+ defaultProps: {
|
|
|
+ children: 'children',
|
|
|
+ label: 'label'
|
|
|
+ },
|
|
|
+ queryParams: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ userName: undefined,
|
|
|
+ deptId: undefined
|
|
|
+ },
|
|
|
+ // 加载状态标识
|
|
|
+ deptLoading: false,
|
|
|
+ userLoading: false,
|
|
|
+ // 内部部门数据存储
|
|
|
+ internalDepartments: [],
|
|
|
+ // 搜索关键词(暂时不用)
|
|
|
+ // searchText: '',
|
|
|
+ // 搜索结果总数(暂时不用)
|
|
|
+ // searchTotal: 0
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ // 部门数据
|
|
|
+ departmentData() {
|
|
|
+ return this.departments.length > 0 ? this.departments : this.internalDepartments;
|
|
|
+ },
|
|
|
+ // 以下计算属性暂时注释(搜索相关)
|
|
|
+ // filteredUsers() {
|
|
|
+ // if (!this.searchText) return [];
|
|
|
+
|
|
|
+ // const results = [];
|
|
|
+ // this.findUsersInDept(this.departmentData, this.searchText, results);
|
|
|
+ // return results;
|
|
|
+ // },
|
|
|
+ // keysToExpand() {
|
|
|
+ // if (!this.searchText) return [];
|
|
|
+
|
|
|
+ // const keys = [];
|
|
|
+ // this.findDeptKeysToExpand(this.departmentData, this.searchText, keys);
|
|
|
+ // return keys;
|
|
|
+ // },
|
|
|
+ // paginatedSearchResults() {
|
|
|
+ // if (!this.filteredUsers || this.filteredUsers.length === 0) return [];
|
|
|
+
|
|
|
+ // // 计算分页范围
|
|
|
+ // const start = (this.queryParams.pageNum - 1) * this.queryParams.pageSize;
|
|
|
+ // const end = start + this.queryParams.pageSize;
|
|
|
+ // this.searchTotal = this.filteredUsers.length;
|
|
|
+ // return this.filteredUsers.slice(start, end);
|
|
|
+ // }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ visible(val) {
|
|
|
+ this.dialogVisible = val;
|
|
|
+ if (val) {
|
|
|
+ if (this.departmentData.length === 0) {
|
|
|
+ // 首次打开时加载部门数据
|
|
|
+ this.loadDepartmentData();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 监听内部状态变化,同步到外部
|
|
|
+ dialogVisible(val) {
|
|
|
+ this.$emit('update:visible', val);
|
|
|
+ },
|
|
|
+ // 暂时注释掉搜索相关的监听
|
|
|
+ // searchText(val) {
|
|
|
+ // this.$nextTick(() => {
|
|
|
+ // if (this.$refs.tree) {
|
|
|
+ // this.$refs.tree.store.getNodeMap().forEach(node => {
|
|
|
+ // if (node.visible) {
|
|
|
+ // this.$refs.tree.store.setCurrentNode(node);
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+
|
|
|
+ // // 恢复表格选中状态
|
|
|
+ // if (this.$refs.table) {
|
|
|
+ // this.restoreSelection();
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 使用真实API加载部门数据
|
|
|
+ async loadDepartmentData() {
|
|
|
+ this.deptLoading = true;
|
|
|
+ try {
|
|
|
+ const response = await deptTreeSelect();
|
|
|
+ if (response.code === 200) {
|
|
|
+ this.internalDepartments = response.data || [];
|
|
|
+ } else {
|
|
|
+ this.$modal.msgError("加载部门数据失败: " + response.msg);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ this.$modal.msgError("加载部门数据失败");
|
|
|
+ console.error("加载部门数据失败:", error);
|
|
|
+ } finally {
|
|
|
+ this.deptLoading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 只有点击叶子节点时才加载用户
|
|
|
+ handleNodeClick(data) {
|
|
|
+ this.currentDepartment = data;
|
|
|
+ this.queryParams.deptId = data.id;
|
|
|
+ this.queryParams.pageNum = 1;
|
|
|
+ this.queryParams.userName = undefined;
|
|
|
+ this.getUsers();
|
|
|
+
|
|
|
+ // 加载用户后恢复选中状态
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.restoreSelection();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 处理行点击事件,切换选中状态
|
|
|
+ clickRow(row) {
|
|
|
+ // 获取当前表格选中状态
|
|
|
+ const selection = this.$refs.table.selection || [];
|
|
|
+ const isSelected = selection.some(item => item.userId === row.userId);
|
|
|
+
|
|
|
+ // 切换选中状态
|
|
|
+ if (isSelected) {
|
|
|
+ // 如果已选中,从选择中移除
|
|
|
+ this.$refs.table.toggleRowSelection(row, false);
|
|
|
+ const newSelection = selection.filter(item => item.userId !== row.userId);
|
|
|
+ this.handleSelectionChange(newSelection);
|
|
|
+ } else {
|
|
|
+ // 如果未选中,添加到选择中
|
|
|
+ this.$refs.table.toggleRowSelection(row, true);
|
|
|
+ const newSelection = [...selection, row];
|
|
|
+ this.handleSelectionChange(newSelection);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleSelectionChange(selection) {
|
|
|
+ // 获取当前表格中选中的用户ID
|
|
|
+ const currentTableSelectedIds = selection.map(item => item.userId);
|
|
|
+
|
|
|
+ // 获取当前表格中所有用户的ID
|
|
|
+ const currentTableUserIds = this.userList.map(user => user.userId);
|
|
|
+
|
|
|
+ // 保留不在当前表格中的已选用户(来自其他部门的选择)
|
|
|
+ const otherSelectedUsers = this.selectedUsers.filter(user =>
|
|
|
+ !currentTableUserIds.includes(user.userId)
|
|
|
+ );
|
|
|
+ const otherSelectedUserIds = this.selectedUserIds.filter(id =>
|
|
|
+ !currentTableUserIds.includes(id)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 合并结果:其他部门的已选用户 + 当前表格选中的用户
|
|
|
+ this.selectedUsers = [...otherSelectedUsers, ...selection];
|
|
|
+ this.selectedUserIds = [...otherSelectedUserIds, ...currentTableSelectedIds];
|
|
|
+ },
|
|
|
+ // 使用真实API获取部门用户数据:/system/user/list?pageNum=1&pageSize=10&deptId=xxx
|
|
|
+ async getUsers() {
|
|
|
+ if (!this.queryParams.deptId) return;
|
|
|
+
|
|
|
+ this.userLoading = true;
|
|
|
+ try {
|
|
|
+ const response = await listUser({
|
|
|
+ pageNum: this.queryParams.pageNum,
|
|
|
+ pageSize: this.queryParams.pageSize,
|
|
|
+ deptId: this.queryParams.deptId
|
|
|
+ });
|
|
|
+
|
|
|
+ if (response.code === 200) {
|
|
|
+ this.userList = response.rows || [];
|
|
|
+ this.total = response.total || 0;
|
|
|
+ } else {
|
|
|
+ this.$modal.msgError("获取用户数据失败: " + response.msg);
|
|
|
+ this.userList = [];
|
|
|
+ this.total = 0;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ this.$modal.msgError("获取用户数据失败");
|
|
|
+ console.error("获取用户数据失败:", error);
|
|
|
+ this.userList = [];
|
|
|
+ this.total = 0;
|
|
|
+ } finally {
|
|
|
+ this.userLoading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 暂时注释掉搜索相关的方法
|
|
|
+ // async getList() {
|
|
|
+ // if (!this.queryParams.deptId) return;
|
|
|
+
|
|
|
+ // this.userLoading = true;
|
|
|
+ // this.userList = [];
|
|
|
+ // this.total = 0;
|
|
|
+ // this.userLoading = false;
|
|
|
+ // },
|
|
|
+ // /* 查找所有部门中匹配的用户 */
|
|
|
+ // findUsersInDept(depts, searchText, results) {
|
|
|
+ // if (!depts || !Array.isArray(depts)) return;
|
|
|
+
|
|
|
+ // depts.forEach(dept => {
|
|
|
+ // // 检查当前部门的用户
|
|
|
+ // if (dept.users && dept.users.length > 0) {
|
|
|
+ // dept.users.forEach(user => {
|
|
|
+ // if (user.userName.includes(searchText) || user.nickName.includes(searchText)) {
|
|
|
+ // results.push({
|
|
|
+ // ...user,
|
|
|
+ // deptId: dept.id,
|
|
|
+ // deptName: dept.label
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+
|
|
|
+ // if (dept.children && dept.children.length > 0) {
|
|
|
+ // this.findUsersInDept(dept.children, searchText, results);
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ // },
|
|
|
+ // /* 递归查找包含匹配用户的部门节点 */
|
|
|
+ // findDeptKeysToExpand(depts, searchText, keys) {
|
|
|
+ // if (!depts || !Array.isArray(depts)) return;
|
|
|
+
|
|
|
+ // depts.forEach(dept => {
|
|
|
+ // let hasMatch = false;
|
|
|
+
|
|
|
+ // // 检查当前部门是否有匹配用户
|
|
|
+ // if (dept.users && dept.users.length > 0) {
|
|
|
+ // hasMatch = dept.users.some(user =>
|
|
|
+ // user.userName.includes(searchText) || user.nickName.includes(searchText)
|
|
|
+ // );
|
|
|
+ // }
|
|
|
+
|
|
|
+ // // 检查子部门是否有匹配用户
|
|
|
+ // if (!hasMatch && dept.children && dept.children.length > 0) {
|
|
|
+ // hasMatch = this.deptContainsMatch(dept.children, searchText);
|
|
|
+ // }
|
|
|
+
|
|
|
+ // if (hasMatch) {
|
|
|
+ // keys.push(dept.id);
|
|
|
+ // }
|
|
|
+
|
|
|
+ // // 递归处理子部门
|
|
|
+ // if (dept.children && dept.children.length > 0) {
|
|
|
+ // this.findDeptKeysToExpand(dept.children, searchText, keys);
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ // },
|
|
|
+ // deptContainsMatch(depts, searchText) {
|
|
|
+ // if (!depts || !Array.isArray(depts)) return false;
|
|
|
+
|
|
|
+ // for (const dept of depts) {
|
|
|
+ // if (dept.users && dept.users.length > 0) {
|
|
|
+ // if (dept.users.some(user =>
|
|
|
+ // user.userName.includes(searchText) || user.nickName.includes(searchText)
|
|
|
+ // )) {
|
|
|
+ // return true;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // if (dept.children && dept.children.length > 0) {
|
|
|
+ // if (this.deptContainsMatch(dept.children, searchText)) {
|
|
|
+ // return true;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // return false;
|
|
|
+ // },
|
|
|
+ // handleSearch() {
|
|
|
+ // this.queryParams.pageNum = 1;
|
|
|
+ // this.$nextTick(() => {
|
|
|
+ // this.restoreSelection();
|
|
|
+ // });
|
|
|
+ // },
|
|
|
+ // resetQuery() {
|
|
|
+ // this.searchText = '';
|
|
|
+ // this.queryParams.pageNum = 1;
|
|
|
+ // },
|
|
|
+ // 确认选择
|
|
|
+ handleConfirm() {
|
|
|
+ if (this.selectedUserIds.length === 0) {
|
|
|
+ this.$modal.msgError("请选择要分配的用户");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const actualSelectedUsers = this.selectedUsers.filter(user =>
|
|
|
+ this.selectedUserIds.includes(user.userId)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 传递完整的选择信息
|
|
|
+ this.$emit('confirm', {
|
|
|
+ userIds: this.selectedUserIds,
|
|
|
+ users: actualSelectedUsers,
|
|
|
+ deptId: this.queryParams.deptId,
|
|
|
+ deptName: this.currentDepartment ? this.currentDepartment.label : '',
|
|
|
+ ...this.extraParams
|
|
|
+ });
|
|
|
+
|
|
|
+ this.dialogVisible = false;
|
|
|
+ },
|
|
|
+ handleCancel() {
|
|
|
+ this.dialogVisible = false;
|
|
|
+ },
|
|
|
+ /* 恢复表格中的选中状态 */
|
|
|
+ restoreSelection() {
|
|
|
+ if (!this.$refs.table || !this.userList || !this.selectedUsers) return;
|
|
|
+
|
|
|
+
|
|
|
+ this.$refs.table.clearSelection();
|
|
|
+ const originalSelectedUserIds = [...this.selectedUserIds];
|
|
|
+
|
|
|
+
|
|
|
+ this.userList.forEach(row => {
|
|
|
+ if (originalSelectedUserIds.includes(row.userId)) {
|
|
|
+ this.$refs.table.toggleRowSelection(row, true);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 移除已选中用户
|
|
|
+ removeSelectedUser(user, index) {
|
|
|
+ this.selectedUsers.splice(index, 1);
|
|
|
+ this.selectedUserIds.splice(this.selectedUserIds.indexOf(user.userId), 1);
|
|
|
+ // 同步取消表格中的选中状态,需要找到表格中对应的行对象
|
|
|
+ if (this.$refs.table) {
|
|
|
+ const tableRow = this.userList.find(row => row.userId === user.userId);
|
|
|
+ if (tableRow) {
|
|
|
+ this.$refs.table.toggleRowSelection(tableRow, false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleClose() {
|
|
|
+ this.currentDepartment = null;
|
|
|
+ this.userList = [];
|
|
|
+ this.selectedUsers = [];
|
|
|
+ this.selectedUserIds = [];
|
|
|
+ // this.searchText = '';
|
|
|
+ this.queryParams.pageNum = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.user-select-container {
|
|
|
+ display: flex;
|
|
|
+ height: 500px;
|
|
|
+ min-height: 500px;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.department-panel {
|
|
|
+ width: 280px;
|
|
|
+ border-right: 2px solid #d1d5db;
|
|
|
+ padding: 10px;
|
|
|
+ overflow-y: auto;
|
|
|
+ background-color: #f9fafb;
|
|
|
+ box-shadow: 2px 0 5px rgba(0, 0, 0, 0.05);
|
|
|
+}
|
|
|
+
|
|
|
+.user-panel {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ padding: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.panel-header {
|
|
|
+ padding-bottom: 10px;
|
|
|
+ border-bottom: 1px solid #e4e7ed;
|
|
|
+ margin-bottom: 15px;
|
|
|
+}
|
|
|
+
|
|
|
+.panel-header h4 {
|
|
|
+ margin: 0;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #1f2937;
|
|
|
+ padding-bottom: 6px;
|
|
|
+ border-bottom: 2px solid #1890ff;
|
|
|
+ display: inline-block;
|
|
|
+}
|
|
|
+
|
|
|
+.selected-users {
|
|
|
+ margin-bottom: 15px;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 10px;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+}
|
|
|
+
|
|
|
+.selected-header {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #303133;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ border-bottom: 1px solid #ebeef5;
|
|
|
+ padding-bottom: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.selected-list {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.selected-tag {
|
|
|
+ margin: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.search-form {
|
|
|
+ margin-bottom: 15px;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.search-results {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.result-header {
|
|
|
+ padding: 8px 0;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #303133;
|
|
|
+ border-bottom: 1px solid #e4e7ed;
|
|
|
+ margin-bottom: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.user-table {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.pagination-container {
|
|
|
+ flex-shrink: 0;
|
|
|
+ padding-top: 10px;
|
|
|
+ text-align: right;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-state {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ height: 100%;
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-state i {
|
|
|
+ font-size: 48px;
|
|
|
+ margin-bottom: 15px;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-state p {
|
|
|
+ margin: 0;
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+
|
|
|
+.department-tree {
|
|
|
+ background: transparent;
|
|
|
+}
|
|
|
+
|
|
|
+.department-tree /deep/ .el-tree-node {
|
|
|
+ margin-bottom: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.department-tree /deep/ .el-tree-node__content {
|
|
|
+ padding: 8px 10px;
|
|
|
+ border-radius: 4px;
|
|
|
+ transition: all 0.3s;
|
|
|
+}
|
|
|
+
|
|
|
+.department-tree /deep/ .el-tree-node__content:hover {
|
|
|
+ background-color: #e6f7ff;
|
|
|
+}
|
|
|
+
|
|
|
+/* 当前选中节点高亮样式 */
|
|
|
+.department-tree /deep/ .el-tree-node.is-current>.el-tree-node__content {
|
|
|
+ background-color: #1890ff !important;
|
|
|
+ color: #fff !important;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+/* 展开图标样式 */
|
|
|
+.department-tree /deep/ .el-tree-node__expand-icon {
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+
|
|
|
+.department-tree /deep/ .el-tree-node__expand-icon.expanded {
|
|
|
+ transform: rotate(90deg);
|
|
|
+}
|
|
|
+
|
|
|
+/* 隐藏没有子节点的展开图标 */
|
|
|
+.department-tree /deep/ .el-tree-node__expand-icon.is-leaf {
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+
|
|
|
+.department-tree /deep/ .el-tree-node__children .el-tree-node__content {
|
|
|
+ padding-left: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+.department-tree /deep/ .el-tree-node__children .el-tree-node__children .el-tree-node__content {
|
|
|
+ padding-left: 50px;
|
|
|
+}
|
|
|
+
|
|
|
+.department-tree /deep/ .el-tree-node__label {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #303133;
|
|
|
+}
|
|
|
+</style>
|