|
|
@@ -0,0 +1,525 @@
|
|
|
+<template>
|
|
|
+ <div class="sle-user-el-input " @click="show"
|
|
|
+ :style="`width: ${props.inputWidth ? props.inputWidth + 'px' : '100%'};height:${props.inputHeight ? props.inputHeight + 'px' : '32px'}; flex-grow: ${props.inputWidth ? 'none' :'1' };`">
|
|
|
+ <span style="color: #a8abb2" v-if="finalUsers?.length == 0">{{ placeholder }}</span>
|
|
|
+ <template v-else-if="finalUsers?.length == 1">
|
|
|
+ <el-tag style="margin: 3px 5px 3px 0px" v-for="item in finalUsers" :key="item.id" closable
|
|
|
+ @close="removeFinalUser(item)">
|
|
|
+ {{ item.realName }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-tag style="margin: 3px 5px 3px 0px" >
|
|
|
+ {{ finalUsers[0].realName }}
|
|
|
+ </el-tag>
|
|
|
+ <el-tag style="margin: 3px 5px 3px 0px" >
|
|
|
+ {{ finalUsers.length }} +
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ <el-input v-model="userIds" style="display: none;"></el-input>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-if="visible" class="modal-overlay" @click.self="visible">
|
|
|
+ <div class="modal create-modal" style="max-width: 1100px;">
|
|
|
+ <div class="modal-header">
|
|
|
+ <div class="modal-title">
|
|
|
+ 选择用户
|
|
|
+ </div>
|
|
|
+ <button class="modal-close" @click="closeCreateModal">
|
|
|
+ <i class="fas fa-times"></i>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <div class="modal-body">
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="4" style="border-right: 1px solid #344156;overflow-x: auto">
|
|
|
+ <el-scrollbar max-height="650px" min-height="650px" style="overflow-x: auto">
|
|
|
+ <el-tree :data="deptOptions" ref="deptRef" :default-checked-keys="defaultCheckedKeys"
|
|
|
+ show-checkbox @check="getCheckedNodes" node-key="treeId"
|
|
|
+ :check-strictly="!deptCheckStrictly" empty-text="加载中,请稍候"
|
|
|
+ :props="{ label: 'title', children: 'children' }"></el-tree>
|
|
|
+ </el-scrollbar>
|
|
|
+ </el-col>
|
|
|
+ <el-col v-loading="loadingGetData"
|
|
|
+ :span="15" style="padding: 0 10px;">
|
|
|
+
|
|
|
+ <el-form :model="queryParams" ref="queryFormRef" :inline="true">
|
|
|
+ <el-form-item prop="blurry" style="margin-right: 5px">
|
|
|
+ <el-input v-model="blurry" style="width: 160px" @clear="handleQuery" placeholder="请输入用户名称" clearable
|
|
|
+ @keyup.stop="handleQuery" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
|
|
|
+ <el-checkbox v-if="multiple" style="margin-left: 5px;margin-right: 5px"
|
|
|
+ v-model="checkAll"
|
|
|
+ @change="selectAll"
|
|
|
+ label="全选/全不选" border></el-checkbox>
|
|
|
+ <!-- <el-checkbox style="margin-left: 5px;margin-right: 5px" border v-model="reSelectValu" @change="reSelect" label="反选"></el-checkbox>-->
|
|
|
+
|
|
|
+ <el-checkbox style="margin-left: 5px;margin-right: 5px" border v-model="isIncludeResign" @change="getIncludeResign" label="离职人员"></el-checkbox>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <el-row type="flex">
|
|
|
+ <div class="userList" style="max-height: 600px;overflow-y: scroll">
|
|
|
+ <el-checkbox-group v-if="multiple" v-model="checkUserIds">
|
|
|
+ <template v-for="(item, index) in userList" :key="index">
|
|
|
+ <el-checkbox v-show="!item.hiden" :value="item.id" style="margin: 0 5px 5px 0" border>
|
|
|
+ {{ item.realName }}({{ item.deptName }}) {{item.resignDate ? '(离职)' : ''}}
|
|
|
+ </el-checkbox>
|
|
|
+ </template>
|
|
|
+ </el-checkbox-group>
|
|
|
+
|
|
|
+ <el-radio-group v-else v-model="checkUserId">
|
|
|
+ <template v-for="(item, index) in userList" :key="index">
|
|
|
+ <el-radio style="margin: 0 5px 5px 0" v-show="!item.hiden" :value="item.id" border>
|
|
|
+ {{ item.realName }}({{ item.deptName }}){{item.resignDate ? '(离职)' : ''}}
|
|
|
+ </el-radio>
|
|
|
+ </template>
|
|
|
+ </el-radio-group>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </el-row>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+
|
|
|
+
|
|
|
+ <el-card shadow="never" style="height: 100%">
|
|
|
+ <template #header>
|
|
|
+ <div class="card-header">
|
|
|
+ <span>已选择用户{{ multiple ? '(多选)' : '(单选)' }}</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <el-scrollbar max-height="550px" min-height="400px">
|
|
|
+ <el-row v-for="(item, index) in selectUsers" :key="index" style="margin-bottom: 5px">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-tag closable @close="remove(item)">
|
|
|
+ <el-icon color="#1874FF"><Select /></el-icon>
|
|
|
+ {{ item.realName }}
|
|
|
+ </el-tag>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-scrollbar>
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+ <div class="modal-footer">
|
|
|
+ <el-button @click="reset">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="handleSelectUser">提交</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import {ref, reactive, watch, computed, onMounted} from 'vue'
|
|
|
+import { getDeptTree, queryAllUser } from '@/api/layout'
|
|
|
+import { Search, Select } from '@element-plus/icons-vue'
|
|
|
+// import {useAllUserStore} from "@/store/modules/allUser";
|
|
|
+
|
|
|
+// const allUserStore = useAllUserStore()
|
|
|
+const emits = defineEmits(['onOk'])
|
|
|
+//组织树是否父子关联
|
|
|
+const deptCheckStrictly = ref(true)
|
|
|
+//是否全选
|
|
|
+const checkAll = ref(false)
|
|
|
+const reSelectValu = ref(false)
|
|
|
+const blurry = ref('')
|
|
|
+const isSearching = ref(false)
|
|
|
+const loadingGetData = ref(false)
|
|
|
+const isIncludeResign = ref(false)
|
|
|
+const deptRef = ref();
|
|
|
+// 组织树
|
|
|
+const deptOptions = ref([])
|
|
|
+const defaultCheckedKeys = ref([])
|
|
|
+//多选
|
|
|
+const checkUserIds = ref([]);
|
|
|
+//单选
|
|
|
+const checkUserId = ref();
|
|
|
+const userIds = defineModel('modelValue', { required: true })
|
|
|
+
|
|
|
+// const router = useRouter();
|
|
|
+//定义props
|
|
|
+const props = defineProps({
|
|
|
+
|
|
|
+ multiple: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ arrayToString: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ //建议使用复选框
|
|
|
+ showDeptCheckBox: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true
|
|
|
+ },
|
|
|
+ inputWidth: {
|
|
|
+ type: Number,
|
|
|
+ },
|
|
|
+ inputHeight: {
|
|
|
+ type: Number,
|
|
|
+ },
|
|
|
+ deptIds: {
|
|
|
+ type: [Array, String, Number],
|
|
|
+ },
|
|
|
+
|
|
|
+ placeholder: {
|
|
|
+ type: String,
|
|
|
+ default: '请选择用户'
|
|
|
+ },
|
|
|
+ authorty:{
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+watch(() => userIds.value, async (value) => {
|
|
|
+ init()
|
|
|
+})
|
|
|
+watch(() => props.deptIds, async (value) => {
|
|
|
+
|
|
|
+ if(!value){
|
|
|
+ defaultCheckedKeys.value = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //判断value如果是数组
|
|
|
+ if (Array.isArray(value)) {
|
|
|
+ if(value.length == 0) {
|
|
|
+ defaultCheckedKeys.value = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+ defaultCheckedKeys.value = value.map(item => "30-" + item)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ defaultCheckedKeys.value = ["30-" + value]
|
|
|
+
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+const remove = (item)=>{
|
|
|
+ if (props.multiple) {
|
|
|
+ checkUserIds.value = checkUserIds.value.filter(i => i != item.id)
|
|
|
+ } else {
|
|
|
+ checkUserId.value = undefined
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const removeFinalUser = (item) => {
|
|
|
+ if (props.multiple) {
|
|
|
+ finalUsers.value = finalUsers.value.filter(i => i.id != item.id)
|
|
|
+ userIds.value = finalUsers.value.map(item => item.id)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ finalUsers.value = []
|
|
|
+ userIds.value = undefined
|
|
|
+}
|
|
|
+//获取当前实例
|
|
|
+// const {proxy} = getCurrentInstance();
|
|
|
+//用户列表
|
|
|
+const userList = ref([]);
|
|
|
+//弹窗
|
|
|
+const visible = ref(false);
|
|
|
+//一共多少条数据
|
|
|
+const total = ref(0);
|
|
|
+
|
|
|
+//部门过滤id
|
|
|
+const filterDeptIdList = ref([]);
|
|
|
+
|
|
|
+const queryParams = reactive({
|
|
|
+ pageIndex: 1,
|
|
|
+ pageSize: 10000,
|
|
|
+})
|
|
|
+const selectUsers = computed(() => {
|
|
|
+ if (props.multiple) {
|
|
|
+ return userList.value.filter(item => checkUserIds.value.includes(item.id))
|
|
|
+ }
|
|
|
+ return userList.value.filter(item => checkUserId.value === item.id)
|
|
|
+})
|
|
|
+const finalUsers = ref([])
|
|
|
+const getIncludeResign = async (val)=>{
|
|
|
+ // allUserStore.clearUser()
|
|
|
+ // allUserStore.setIsIncludeResign(val)
|
|
|
+ await init()
|
|
|
+ if(checkAll.value) {
|
|
|
+ await selectAll()
|
|
|
+ }
|
|
|
+ userList.value.forEach(item => {
|
|
|
+ if(filterDeptIdList.value.length > 0) {
|
|
|
+ if (filterDeptIdList.value.some(i => i == item.deptId)) {
|
|
|
+ item.hiden = false
|
|
|
+ } else {
|
|
|
+ item.hiden = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const init = async () => {
|
|
|
+ await getList()
|
|
|
+ if (props.multiple) {
|
|
|
+ if (!!!userIds.value) {
|
|
|
+ checkUserIds.value = []
|
|
|
+ } else {
|
|
|
+ if (!Array.isArray(userIds.value)) {
|
|
|
+ throw new Error("接收到不是数组,请不要配置multiple属性")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ checkUserIds.value = userIds.value.concat()
|
|
|
+ }
|
|
|
+ finalUsers.value = userList.value.filter(item => checkUserIds.value.includes(item.id))
|
|
|
+ } else {
|
|
|
+ if (Array.isArray(userIds.value)) {
|
|
|
+ throw new Error("接收到数组,请配置multiple属性")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // checkUserId.value = userIds.value || ''
|
|
|
+
|
|
|
+ finalUsers.value = userList.value.filter(item => userIds.value == item.id)
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+const queryFormRef = ref();
|
|
|
+
|
|
|
+// const menuId = computed(()=>{
|
|
|
+// if(props.authorty){
|
|
|
+// return router.currentRoute.value?.meta?.menuId
|
|
|
+// }
|
|
|
+// return ''
|
|
|
+// })
|
|
|
+
|
|
|
+/** 查询组织树 */
|
|
|
+const handleDataAuthUpdate = async () => {
|
|
|
+ let typs = [10, 20, 30]
|
|
|
+ const res = await getDeptTree({ orgTypes: [10, 20, 30], reviewTag: 1 });
|
|
|
+ deptOptions.value = res.result;
|
|
|
+}
|
|
|
+
|
|
|
+const show = async () => {
|
|
|
+ filterDeptIdList.value = []
|
|
|
+ // isIncludeResign.value = allUserStore.getIsIncludeResign()
|
|
|
+ blurry.value = ''
|
|
|
+ await init()
|
|
|
+ filterByDeptId( defaultCheckedKeys.value)
|
|
|
+ handleDataAuthUpdate()
|
|
|
+ visible.value = true;
|
|
|
+}
|
|
|
+const getCheckedNodes = () => {
|
|
|
+ if (!props.showDeptCheckBox) return
|
|
|
+ if(checkAll.value ){
|
|
|
+
|
|
|
+ checkAll.value = false
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取部门
|
|
|
+ let nodes = deptRef.value?.getCheckedNodes() ?? []
|
|
|
+ filterDeptIdList.value = []
|
|
|
+
|
|
|
+ if (nodes.length == 0) {
|
|
|
+ userList.value.forEach(item => {
|
|
|
+ item.hiden = false
|
|
|
+ })
|
|
|
+ filterDeptIdList.value = []
|
|
|
+ // checkUserIds.value = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ let arr = nodes.map(item=>item.treeId)
|
|
|
+ filterByDeptId(arr)
|
|
|
+ // nodes.forEach(item => {
|
|
|
+ // let str: string[] = item.treeId.split('-')
|
|
|
+ // if (str[0] == '30') {
|
|
|
+ // filterDeptIdList.value.push(str[1])
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+ // userList.value.forEach(item => {
|
|
|
+ // if (filterDeptIdList.value.some(i => i == item.deptId)) {
|
|
|
+ // item.hiden = false
|
|
|
+ // } else {
|
|
|
+ // item.hiden = true
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+ // let filterUser = userList.value.filter(item => !item.hiden)
|
|
|
+ // console.log(filterUser, "filterUser")
|
|
|
+ // let ids = filterUser.map(item => item.id)
|
|
|
+ // checkUserIds.value = ids
|
|
|
+}
|
|
|
+
|
|
|
+const filterByDeptId = (deptIds)=>{
|
|
|
+ if(!deptIds || deptIds.length == 0) return
|
|
|
+ deptIds.forEach(item => {
|
|
|
+ let str = item.split('-')
|
|
|
+ if (str[0] == '30') {
|
|
|
+ filterDeptIdList.value.push(str[1])
|
|
|
+ }
|
|
|
+ })
|
|
|
+ userList.value.forEach(item => {
|
|
|
+ if (filterDeptIdList.value.some(i => i == item.deptId)) {
|
|
|
+ item.hiden = false
|
|
|
+ } else {
|
|
|
+ item.hiden = true
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const difference = (arr1, arr2) => {
|
|
|
+ return arr1.filter(x => !arr2.includes(x));
|
|
|
+}
|
|
|
+//全选/全不选
|
|
|
+const selectAll = async () => {
|
|
|
+
|
|
|
+ let filterUser = userList.value.filter(item => !item.hiden)
|
|
|
+ let ids = []
|
|
|
+ if(filterDeptIdList.value && filterDeptIdList.value.length > 0) {
|
|
|
+ ids = filterUser.map(item => filterDeptIdList.value.some(i => i == item.deptId) && item.id)
|
|
|
+ } else {
|
|
|
+ ids = filterUser.map(item => item.id)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!checkAll.value) {
|
|
|
+ checkUserIds.value = difference(checkUserIds.value, ids);
|
|
|
+ return
|
|
|
+ }
|
|
|
+ checkUserIds.value.push(...ids)
|
|
|
+}
|
|
|
+//reSelect 反选
|
|
|
+const reSelect = () => {
|
|
|
+ let filterUser = userList.value.filter(item => !item.hiden)
|
|
|
+ let ids = filterUser.map(item => item.id)
|
|
|
+ //已经选中的id集合
|
|
|
+ let checkedIds = ids.filter(item => checkUserIds.value.some(id => id == item))
|
|
|
+ //没有选中的集合
|
|
|
+ let noCheckedIds = ids.filter(item => !checkUserIds.value.includes(item))
|
|
|
+ console.log(checkedIds, noCheckedIds)
|
|
|
+ checkUserIds.value = difference(checkUserIds.value, checkedIds);
|
|
|
+ checkUserIds.value.push(...noCheckedIds)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/** 查询数据 */
|
|
|
+const getList = async () => {
|
|
|
+
|
|
|
+ // const res = await listUser(queryParams);
|
|
|
+ // if (allUserStore.getUser().length <= 0 || props.authorty) {
|
|
|
+ loadingGetData.value = true
|
|
|
+ let res = await queryAllUser({ isIncludeResign: isIncludeResign.value, reviewTag: 1, pageIndex: 1, pageSize: 10000 })
|
|
|
+ userList.value = res.result.records
|
|
|
+ loadingGetData.value = false
|
|
|
+ return
|
|
|
+ // }
|
|
|
+ // userList.value = JSON.parse(JSON.stringify(allUserStore.getUser()) )?? [];
|
|
|
+ // total.value = res.result.total;
|
|
|
+
|
|
|
+}
|
|
|
+/** 搜索按钮操作 */
|
|
|
+const handleQuery = () => {
|
|
|
+
|
|
|
+ userList.value.forEach(item => {
|
|
|
+
|
|
|
+ if (!!!blurry.value) {
|
|
|
+ if(filterDeptIdList.value.length <= 0){
|
|
|
+ item.hiden = false
|
|
|
+ }else {
|
|
|
+ if (filterDeptIdList.value.some(i => i == item.deptId)) {
|
|
|
+ item.hiden = false
|
|
|
+ } else {
|
|
|
+ item.hiden = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if(filterDeptIdList.value.length <= 0){
|
|
|
+ if ((item.realName.includes(blurry.value) || item.userName.includes(blurry.value)) ) {
|
|
|
+ item.hiden = false
|
|
|
+ } else {
|
|
|
+ item.hiden = true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (filterDeptIdList.value.some(i => i == item.deptId)) {
|
|
|
+ if ((item.realName.includes(blurry.value) || item.userName.includes(blurry.value)) ) {
|
|
|
+ item.hiden = false
|
|
|
+ } else {
|
|
|
+ item.hiden = true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ item.hiden = true
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+/** 重置按钮操作 */
|
|
|
+const reset = () => {
|
|
|
+ visible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+/**选择最终确认 */
|
|
|
+const handleSelectUser = async () => {
|
|
|
+ finalUsers.value = selectUsers.value
|
|
|
+ if (props.multiple) {
|
|
|
+ userIds.value = checkUserIds.value
|
|
|
+ } else {
|
|
|
+ userIds.value = checkUserId.value
|
|
|
+ }
|
|
|
+ emits('onOk', finalUsers.value)
|
|
|
+ visible.value = false
|
|
|
+}
|
|
|
+// 暴露
|
|
|
+defineExpose({
|
|
|
+ show,
|
|
|
+});
|
|
|
+onMounted(async () => {
|
|
|
+ init()
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.sle-user-el-input {
|
|
|
+ display: flex;
|
|
|
+ overflow-y: hidden;
|
|
|
+ overflow-x: hidden;
|
|
|
+ /*flex-grow: 1;*/
|
|
|
+ align-items: center;
|
|
|
+ justify-content: flex-start;
|
|
|
+ padding: 1px 11px;
|
|
|
+ background-color: var(--bg-dark);
|
|
|
+ background-image: none;
|
|
|
+ border: 1px solid var(--border);
|
|
|
+ border-radius: 8px;
|
|
|
+ transition: var(--el-transition-box-shadow);
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+.el-tree{
|
|
|
+ background: transparent;
|
|
|
+}
|
|
|
+.el-tree :deep(.el-text){
|
|
|
+ color: #FFF;
|
|
|
+}
|
|
|
+.el-tree :deep(.el-tree-node__content):hover{
|
|
|
+ background: transparent;
|
|
|
+}
|
|
|
+.el-row :deep(.el-checkbox__label){
|
|
|
+ color: #FFF;
|
|
|
+}
|
|
|
+.el-card{
|
|
|
+ background: transparent;
|
|
|
+ color: #FFF;
|
|
|
+ border-color: #344156;
|
|
|
+}
|
|
|
+.el-card :deep(.el-card__header){
|
|
|
+ border-bottom: 1px solid #344156;
|
|
|
+}
|
|
|
+</style>
|