init
This commit is contained in:
BIN
src/components/OrgSelector/assets/check_box.png
Normal file
BIN
src/components/OrgSelector/assets/check_box.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 325 B |
BIN
src/components/OrgSelector/assets/jiaojiao.png
Normal file
BIN
src/components/OrgSelector/assets/jiaojiao.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
42
src/components/OrgSelector/common.ts
Normal file
42
src/components/OrgSelector/common.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* @Date: 2022-08-29 14:00:42
|
||||
* @LastEditors: StavinLi 495727881@qq.com
|
||||
* @LastEditTime: 2023-03-29 15:53:05
|
||||
* @FilePath: /Workflow-Vue3/src/components/dialog/common.js
|
||||
*/
|
||||
|
||||
import {deptRoleList} from '/@/api/admin/role';
|
||||
import {orgTree, orgTreeSearcheUser} from '/@/api/admin/dept';
|
||||
|
||||
export const searchVal = ref('');
|
||||
export const departments = ref({
|
||||
titleDepartments: [], childDepartments: [], roleList: [], employees: [],
|
||||
});
|
||||
export const roles = ref({});
|
||||
export const getRoleList = async () => {
|
||||
let {
|
||||
data: {list},
|
||||
} = await deptRoleList();
|
||||
roles.value = list;
|
||||
};
|
||||
export const getDepartmentList = async (parentId = 0, type = 'org') => {
|
||||
// let { data } = await getDepartments({ parentId })
|
||||
|
||||
let {data} = await orgTree(type, parentId);
|
||||
|
||||
departments.value = data;
|
||||
};
|
||||
export const getDebounceData = async (event: any, type = 1) => {
|
||||
if (event) {
|
||||
let data = {
|
||||
username: event, pageNum: 1, pageSize: 30,
|
||||
};
|
||||
if (type === 1) {
|
||||
departments.value.childDepartments = [];
|
||||
let res = await orgTreeSearcheUser(data);
|
||||
departments.value.employees = res.data;
|
||||
}
|
||||
} else {
|
||||
type === 1 ? await getDepartmentList() : await getRoleList();
|
||||
}
|
||||
};
|
||||
30
src/components/OrgSelector/dialog.css
Normal file
30
src/components/OrgSelector/dialog.css
Normal file
@@ -0,0 +1,30 @@
|
||||
.person_body {
|
||||
border: 1px solid #f5f5f5;
|
||||
height: 500px;
|
||||
display: flex;
|
||||
}
|
||||
.tree_nav span {
|
||||
display: inline-block;
|
||||
padding-right: 10px;
|
||||
margin-right: 5px;
|
||||
max-width: 6em;
|
||||
color: #38adff;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
background: url(./assets/jiaojiao.png) no-repeat right center;
|
||||
}
|
||||
|
||||
.tree_nav span:last-of-type {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.person_tree {
|
||||
padding: 10px 12px 0 8px;
|
||||
width: 280px;
|
||||
height: 100%;
|
||||
border-right: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.l {
|
||||
float: left;
|
||||
}
|
||||
179
src/components/OrgSelector/employeesDialog.vue
Normal file
179
src/components/OrgSelector/employeesDialog.vue
Normal file
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<el-dialog :title="$t('orgSelecotr.select') + $t(`orgSelecotr.${props.type}`)" v-model="visibleDialog" :width="600" append-to-body class="promoter_person">
|
||||
<div class="person_body clear">
|
||||
<div class="person_tree l">
|
||||
<selectBox ref="selectBoxRef" :selectSelf="selectSelf" :list="list" :multiple="multiple"
|
||||
v-model:selectedList="selectedList" :type="type"/>
|
||||
</div>
|
||||
<selectResult :total="total" @del="delList" :list="resList"/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="$emit('update:visible', false)">{{ $t('common.cancelButtonText') }}</el-button>
|
||||
<el-button type="primary" @click="saveDialog">{{ $t('common.confirmButtonText') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import selectBox from './selectBox.vue';
|
||||
import selectResult from './selectResult.vue';
|
||||
import {computed, watch, ref, onMounted} from 'vue';
|
||||
import {departments, searchVal} from './common';
|
||||
import other from '/@/utils/other';
|
||||
import {useI18n} from "vue-i18n";
|
||||
|
||||
const selectBoxRef = ref();
|
||||
|
||||
let props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'user',
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
selectSelf: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
//已选择的集合
|
||||
let selectedList = ref([]);
|
||||
|
||||
let emits = defineEmits(['update:visible', 'change']);
|
||||
let visibleDialog = computed({
|
||||
get() {
|
||||
return props.visible;
|
||||
},
|
||||
set() {
|
||||
closeDialog();
|
||||
},
|
||||
});
|
||||
const isChecked = (id, type) => {
|
||||
return selectedList.value.filter((res) => res.id === id && res.type === type).length > 0;
|
||||
};
|
||||
|
||||
let list = computed(() => {
|
||||
let value = departments.value;
|
||||
return [
|
||||
{
|
||||
type: 'dept',
|
||||
data: value === undefined ? [] : value.childDepartments,
|
||||
},
|
||||
{
|
||||
type: 'role',
|
||||
data: value === undefined ? [] : value.roleList,
|
||||
},
|
||||
{
|
||||
type: 'user',
|
||||
data: value === undefined ? [] : value.employees,
|
||||
change: (item) => {
|
||||
if (!isChecked(item.id, item.type)) {
|
||||
if (!props.multiple) {
|
||||
//单选
|
||||
selectedList.value = [];
|
||||
}
|
||||
|
||||
selectedList.value.push(item);
|
||||
} else {
|
||||
selectedList.value = selectedList.value.filter((res) => !(res.id === item.id && res.type === item.type));
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
});
|
||||
let resList = computed(() => {
|
||||
let userData = selectedList.value.filter((res) => res.type === 'user');
|
||||
let deptData = selectedList.value.filter((res) => res.type === 'dept');
|
||||
let roleData = selectedList.value.filter((res) => res.type === 'role');
|
||||
|
||||
let data = [
|
||||
{
|
||||
type: 'user',
|
||||
data: userData,
|
||||
cancel: (item) => {
|
||||
item.selected = false;
|
||||
selectBoxRef.value.changeEvent(item);
|
||||
},
|
||||
},
|
||||
];
|
||||
if (props.type === 'org' || props.type === 'dept') {
|
||||
data.unshift({
|
||||
type: 'dept',
|
||||
data: deptData,
|
||||
cancel: (item) => {
|
||||
item.selected = false;
|
||||
selectBoxRef.value.changeEvent(item);
|
||||
},
|
||||
});
|
||||
}
|
||||
if (props.type === 'role') {
|
||||
data.unshift({
|
||||
type: 'role',
|
||||
data: roleData,
|
||||
cancel: (item) => {
|
||||
item.selected = false;
|
||||
selectBoxRef.value.changeEvent(item);
|
||||
},
|
||||
});
|
||||
}
|
||||
return data;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(val) => {
|
||||
if (val) {
|
||||
selectedList.value = props.data;
|
||||
searchVal.value = '';
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const closeDialog = () => {
|
||||
emits('update:visible', false);
|
||||
};
|
||||
|
||||
let total = computed(() => {
|
||||
let v = departments.value;
|
||||
if (!v) {
|
||||
return 0;
|
||||
}
|
||||
return selectedList.value.length;
|
||||
});
|
||||
|
||||
const {proxy} = getCurrentInstance();
|
||||
|
||||
let saveDialog = () => {
|
||||
const v = selectedList.value;
|
||||
|
||||
let checkedList = other.deepClone(v).map((item) => ({
|
||||
type: item.type,
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
avatar: item.avatar,
|
||||
}));
|
||||
emits('change', checkedList);
|
||||
//selectedList.value=[]
|
||||
};
|
||||
const delList = () => {
|
||||
for (const item of other.deepClone(selectedList.value)) {
|
||||
item.selected = false;
|
||||
selectBoxRef.value.changeEvent(item);
|
||||
}
|
||||
selectedList.value = [];
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
@import './dialog.css';
|
||||
</style>
|
||||
10
src/components/OrgSelector/i18n/en.ts
Normal file
10
src/components/OrgSelector/i18n/en.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export default {
|
||||
orgSelecotr: {
|
||||
org: 'org',
|
||||
user: 'user',
|
||||
dept: 'dept',
|
||||
role: 'role',
|
||||
select: 'select',
|
||||
search: 'search'
|
||||
},
|
||||
};
|
||||
10
src/components/OrgSelector/i18n/zh-cn.ts
Normal file
10
src/components/OrgSelector/i18n/zh-cn.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export default {
|
||||
orgSelecotr: {
|
||||
org: '组织',
|
||||
user: '用户',
|
||||
dept: '部门',
|
||||
role: '角色',
|
||||
select: '选择',
|
||||
search: '搜索'
|
||||
},
|
||||
};
|
||||
72
src/components/OrgSelector/index.vue
Normal file
72
src/components/OrgSelector/index.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<div>
|
||||
<div>
|
||||
<employees-dialog
|
||||
v-model:visible="selectUserDialogVisible"
|
||||
:data="modelData"
|
||||
:type="type"
|
||||
:multiple="multiple"
|
||||
:selectSelf="selectSelf"
|
||||
@change="afterSelectUser"
|
||||
/>
|
||||
</div>
|
||||
<el-button :disabled="disabled" icon="Plus" circle size="large" @click="selectUserDialogVisible = true"> </el-button>
|
||||
<div style="width: 100%; margin-top: 10px; text-align: left">
|
||||
<org-item v-model:data="modelData" :disabled="disabled" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import employeesDialog from './employeesDialog.vue';
|
||||
import orgItem from './orgItem.vue';
|
||||
import type { OrgItem } from './types';
|
||||
|
||||
const selectUserDialogVisible = ref(false);
|
||||
|
||||
const emits = defineEmits(['update:orgList', 'update:modelValue']);
|
||||
|
||||
const props = defineProps({
|
||||
orgList: {
|
||||
type: Array as PropType<OrgItem[]>,
|
||||
default: () => [],
|
||||
},
|
||||
modelValue: {
|
||||
type: Array as PropType<OrgItem[]>,
|
||||
default: () => [],
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'user',
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
selectSelf: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const modelData = computed({
|
||||
get: () => {
|
||||
return props.modelValue?.length ? props.modelValue : props.orgList || [];
|
||||
},
|
||||
set: (value: OrgItem[]) => {
|
||||
emits('update:modelValue', value);
|
||||
emits('update:orgList', value);
|
||||
},
|
||||
});
|
||||
|
||||
const afterSelectUser = (data: OrgItem[]) => {
|
||||
selectUserDialogVisible.value = false;
|
||||
emits('update:modelValue', data);
|
||||
emits('update:orgList', data);
|
||||
};
|
||||
</script>
|
||||
37
src/components/OrgSelector/orgItem.vue
Normal file
37
src/components/OrgSelector/orgItem.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-tag
|
||||
v-for="(item, index) in data"
|
||||
style="margin-right: 5px; margin-top: 5px"
|
||||
:key="item.id"
|
||||
:closable="!disabled"
|
||||
@close="removeItem(index, item.id, item.type)"
|
||||
:type="item.type === 'dept' ? 'primary' : item.type === 'user' ? 'warning' : 'success'"
|
||||
size="large"
|
||||
>
|
||||
{{ item.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
let emits = defineEmits(['update:data']);
|
||||
|
||||
let props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const removeItem = (index, id, type) => {
|
||||
emits(
|
||||
'update:data',
|
||||
props.data.filter((res) => !(res.id === id && res.type === type))
|
||||
);
|
||||
};
|
||||
</script>
|
||||
120
src/components/OrgSelector/roleDialog.vue
Normal file
120
src/components/OrgSelector/roleDialog.vue
Normal file
@@ -0,0 +1,120 @@
|
||||
<!--
|
||||
* @Date: 2022-08-25 14:05:59
|
||||
* * @LastEditors: StavinLi 495727881@qq.com
|
||||
* @LastEditTime: 2023-03-15 14:59:19
|
||||
* @FilePath: /Workflow-Vue3/src/components/dialog/roleDialog.vue
|
||||
-->
|
||||
<template>
|
||||
<el-dialog title="选择角色" v-model="visibleDialog" :width="600" append-to-body class="promoter_person">
|
||||
<div class="person_body clear">
|
||||
<div class="person_tree l">
|
||||
<input type="text" placeholder="搜索角色" v-model="searchVal" @input="getDebounceData($event, 2)"/>
|
||||
<selectBox :list="list"/>
|
||||
</div>
|
||||
<selectResult :total="total" @del="delList" :list="resList"/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button type="primary" @click="saveDialog">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import selectBox from './selectBox.vue';
|
||||
import selectResult from './selectResult.vue';
|
||||
import {computed, watch, ref} from 'vue';
|
||||
import {roles, getDebounceData, getRoleList, searchVal} from './common';
|
||||
|
||||
let props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
let checkedRoleList = ref([]);
|
||||
let emits = defineEmits(['update:visible', 'change']);
|
||||
let list = computed(() => {
|
||||
return [
|
||||
{
|
||||
type: 'role',
|
||||
not: true,
|
||||
data: roles.value,
|
||||
isActive: (item) => toggleClass(checkedRoleList.value, item, 'roleId'),
|
||||
change: (item) => {
|
||||
checkedRoleList.value = [item];
|
||||
},
|
||||
},
|
||||
];
|
||||
});
|
||||
let resList = computed(() => {
|
||||
return [
|
||||
{
|
||||
type: 'role',
|
||||
data: checkedRoleList.value,
|
||||
cancel: (item) => removeEle(checkedRoleList.value, item, 'roleId'),
|
||||
},
|
||||
];
|
||||
});
|
||||
let visibleDialog = computed({
|
||||
get() {
|
||||
return props.visible;
|
||||
},
|
||||
set(val) {
|
||||
closeDialog();
|
||||
},
|
||||
});
|
||||
watch(
|
||||
() => props.visible,
|
||||
(val) => {
|
||||
if (val) {
|
||||
getRoleList();
|
||||
searchVal.value = '';
|
||||
checkedRoleList.value = props.data.map(({name, targetId}) => ({
|
||||
roleName: name,
|
||||
roleId: targetId,
|
||||
}));
|
||||
}
|
||||
}
|
||||
);
|
||||
let total = computed(() => checkedRoleList.value.length);
|
||||
const saveDialog = () => {
|
||||
let checkedList = checkedRoleList.value.map((item) => ({
|
||||
type: 2,
|
||||
targetId: item.roleId,
|
||||
name: item.roleName,
|
||||
}));
|
||||
emits('change', checkedList);
|
||||
};
|
||||
const delList = () => {
|
||||
checkedRoleList.value = [];
|
||||
};
|
||||
|
||||
const closeDialog = () => {
|
||||
emits('update:visible', false);
|
||||
};
|
||||
|
||||
const toggleClass = (arr, elem, key = 'id') => {
|
||||
return arr.some((item) => {
|
||||
return item[key] === elem[key];
|
||||
});
|
||||
}
|
||||
|
||||
const removeEle = (arr, elem, key = 'id') => {
|
||||
let includesIndex;
|
||||
arr.map((item, index) => {
|
||||
if (item[key] === elem[key]) {
|
||||
includesIndex = index;
|
||||
}
|
||||
});
|
||||
arr.splice(includesIndex, 1);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import './dialog.css';
|
||||
</style>
|
||||
291
src/components/OrgSelector/selectBox.vue
Normal file
291
src/components/OrgSelector/selectBox.vue
Normal file
@@ -0,0 +1,291 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-input
|
||||
v-model="searchVal"
|
||||
class="w-50 m-2"
|
||||
style="width: 100%"
|
||||
v-if="type === 'user'"
|
||||
:placeholder="$t('orgSelecotr.search')"
|
||||
@input="getDebounceData($event)"
|
||||
:prefix-icon="Search"
|
||||
/>
|
||||
<p class="ellipsis tree_nav" v-if="!searchVal && type !== 'role'">
|
||||
<span @click="queryData(0)" class="ellipsis">根节点</span>
|
||||
<span v-for="(item, index) in departments.titleDepartments" class="ellipsis" :key="index + 'a'" @click="queryData(item.id)">{{
|
||||
item.name
|
||||
}}</span>
|
||||
</p>
|
||||
|
||||
<ul class="select-box">
|
||||
<template v-for="(elem, i) in dataList" :key="i">
|
||||
<template v-if="elem.type === 'role'">
|
||||
<li v-for="item in elem.data" :key="item.id">
|
||||
<el-checkbox v-model="item.selected" @change="changeEvent(item)" :disabled="item.status === 0">
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<div class="f11">
|
||||
<el-icon style="font-size: 20px">
|
||||
<Share />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="f12">{{ item.name }}</div>
|
||||
</div>
|
||||
</el-checkbox>
|
||||
</li>
|
||||
</template>
|
||||
<template v-if="elem.type === 'dept' && (type === 'org' || type === 'dept' || type === 'user')">
|
||||
<li v-for="item in elem.data" :key="item.id">
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<div class="d11">
|
||||
<el-checkbox v-model="item.selected" @change="changeEvent(item)" :disabled="!(type === 'org' || type === 'dept') || item.status == 0">
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<div class="f11">
|
||||
<el-icon style="font-size: 20px">
|
||||
<Grid />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="f12">{{ item.name }}</div>
|
||||
</div>
|
||||
</el-checkbox>
|
||||
</div>
|
||||
<div class="d22" @click="queryData(item.id)">下级</div>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
<template v-if="elem.type === 'user' && (type === 'org' || type === 'user')">
|
||||
<li v-for="item in elem.data" :key="item.id" class="check_box">
|
||||
<el-checkbox
|
||||
v-model="item.selected"
|
||||
:disabled="item.status === 0 || (!selectSelf && currentUserId === item.id)"
|
||||
@change="changeEvent(item)"
|
||||
>
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<div class="f11">
|
||||
<upload-img v-model:image-url="item.avatar" disabled width="20px" height="20px"/>
|
||||
</div>
|
||||
<div class="f12">{{ item.name }}</div>
|
||||
</div>
|
||||
</el-checkbox>
|
||||
</li>
|
||||
</template>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import {useUserInfo} from '/@/stores/userInfo';
|
||||
|
||||
import {departments, getDebounceData, getDepartmentList, searchVal} from './common';
|
||||
import other from '/@/utils/other';
|
||||
import UploadImg from "/@/components/Upload/Image.vue";
|
||||
import {Grid, Search, Share} from '@element-plus/icons-vue';
|
||||
|
||||
var props = defineProps({
|
||||
selectedList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'org',
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
selectSelf: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
const currentUserId = computed(() => {
|
||||
return useUserInfo().userInfos.user.userId;
|
||||
});
|
||||
|
||||
|
||||
const queryData = (pid) => {
|
||||
getDepartmentList(pid, props.type).then((res) => {
|
||||
let selectedList = props.selectedList;
|
||||
|
||||
for (const it of dataList.value) {
|
||||
for (const item of it.data) {
|
||||
item.selected = selectedList.filter((res) => res.id === item.id && res.type === item.type).length > 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let deptList = computed(() => {
|
||||
return departments.value.childDepartments;
|
||||
});
|
||||
|
||||
let userList = computed(() => {
|
||||
return departments.value.employees;
|
||||
});
|
||||
let roleList = computed(() => {
|
||||
return departments.value.roleList;
|
||||
});
|
||||
|
||||
const dataList = computed(() => {
|
||||
return [
|
||||
{
|
||||
type: 'dept',
|
||||
data: deptList.value,
|
||||
},
|
||||
{
|
||||
type: 'user',
|
||||
data: userList.value,
|
||||
},
|
||||
{
|
||||
type: 'role',
|
||||
data: roleList.value,
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
|
||||
let emits = defineEmits(['update:selectedList']);
|
||||
|
||||
onMounted(() => {
|
||||
queryData(0);
|
||||
});
|
||||
|
||||
const changeEvent = (e) => {
|
||||
let selectedList = other.deepClone(props.selectedList);
|
||||
|
||||
if (e.selected) {
|
||||
if (!props.multiple) {
|
||||
userList.value.forEach((res) => (res.selected = false));
|
||||
selectedList = [];
|
||||
}
|
||||
e.selected = true;
|
||||
selectedList.push(e);
|
||||
} else {
|
||||
for (const it of dataList.value) {
|
||||
let filter = it.data.filter((res) => res.id === e.id && res.type === e.type);
|
||||
if (filter.length > 0) {
|
||||
filter[0].selected = false;
|
||||
}
|
||||
}
|
||||
selectedList = selectedList.filter((res) => !(res.id === e.id && res.type === e.type));
|
||||
}
|
||||
emits('update:selectedList', selectedList);
|
||||
};
|
||||
|
||||
const refreshData = () => {
|
||||
let selectedList = props.selectedList;
|
||||
|
||||
for (var it of dataList.value) {
|
||||
for (var item of it.data) {
|
||||
var b = selectedList.filter((res) => res.id === item.id && res.type === item.type).length > 0;
|
||||
item.selected = b;
|
||||
}
|
||||
}
|
||||
};
|
||||
defineExpose({ queryData, changeEvent, refreshData });
|
||||
|
||||
watch(
|
||||
() => props.selectedList,
|
||||
(val) => {
|
||||
refreshData();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@import './dialog.css';
|
||||
|
||||
.select-box {
|
||||
height: 420px;
|
||||
overflow-y: auto;
|
||||
|
||||
li {
|
||||
padding: 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.radio_box a,
|
||||
.check_box a {
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
padding-left: 20px;
|
||||
margin-right: 30px;
|
||||
cursor: pointer;
|
||||
color: #333;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.check_box.not a:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.check_box.not a::before,
|
||||
.check_box.not a:hover::before {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.check_box.not.active {
|
||||
background: #f3f3f3;
|
||||
}
|
||||
|
||||
.radio_box a:hover::before,
|
||||
.check_box a:hover::before {
|
||||
border: 1px solid #46a6fe;
|
||||
}
|
||||
|
||||
.radio_box a::before,
|
||||
.check_box a::before {
|
||||
position: absolute;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 2px;
|
||||
left: 0;
|
||||
top: 1px;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.radio_box a::before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.check-dot.active::after,
|
||||
.radio_box a.active::after,
|
||||
.check_box a.active::after {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
top: 3px;
|
||||
left: 3px;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.radio_box a.active::after {
|
||||
background: #46a6fe;
|
||||
}
|
||||
|
||||
.check_box a.active::after {
|
||||
background: url(./assets/check_box.png) no-repeat center;
|
||||
}
|
||||
|
||||
.f11 {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.f12 {
|
||||
width: calc(100% - 30px);
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.d11 {
|
||||
width: calc(100% - 30px);
|
||||
}
|
||||
|
||||
.d22 {
|
||||
width: 30px;
|
||||
line-height: 41px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
136
src/components/OrgSelector/selectResult.vue
Normal file
136
src/components/OrgSelector/selectResult.vue
Normal file
@@ -0,0 +1,136 @@
|
||||
<!--
|
||||
* @Date: 2022-08-26 16:29:24
|
||||
* @LastEditors: StavinLi 495727881@qq.com
|
||||
* @LastEditTime: 2022-09-21 14:36:30
|
||||
* @FilePath: /Workflow-Vue3/src/components/selectResult.vue
|
||||
-->
|
||||
<template>
|
||||
<div class="select-result l">
|
||||
<p class="clear">
|
||||
已选({{ total }})
|
||||
<a @click="emits('del')">清空</a>
|
||||
</p>
|
||||
<ul>
|
||||
<template v-for="{ type, data, cancel } in list" :key="type">
|
||||
<template v-if="type === 'role'">
|
||||
<li v-for="item in data" :key="item.id">
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<div class="f11">
|
||||
<el-icon style="font-size: 20px">
|
||||
<Share />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="f12">{{ item.name }}</div>
|
||||
<div class="f13">
|
||||
<el-button size="small" text @click="cancel(item)" :icon="CircleClose"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
<template v-if="type === 'dept'">
|
||||
<li v-for="item in data" :key="item.id">
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<div class="f11">
|
||||
<el-icon style="font-size: 20px">
|
||||
<Grid />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="f12">{{ item.name }}</div>
|
||||
<div class="f13">
|
||||
<el-button size="small" text @click="cancel(item)" :icon="CircleClose"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
<template v-if="type === 'user'">
|
||||
<li v-for="item in data" :key="item.id">
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<div class="f11">
|
||||
<upload-img v-model:image-url="item.avatar" disabled width="20px" height="20px" />
|
||||
</div>
|
||||
<div class="f12">{{ item.name }}</div>
|
||||
<div class="f13">
|
||||
<el-button size="small" text @click="cancel(item)" :icon="CircleClose"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { CircleClose, Grid, Share } from '@element-plus/icons-vue';
|
||||
import UploadImg from '/@/components/Upload/Image.vue';
|
||||
|
||||
defineProps({
|
||||
total: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => [{ type: 'role', data, cancel }],
|
||||
},
|
||||
});
|
||||
let emits = defineEmits(['del']);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.select-result {
|
||||
width: 276px;
|
||||
height: 100%;
|
||||
font-size: 12px;
|
||||
|
||||
ul {
|
||||
height: 460px;
|
||||
overflow-y: auto;
|
||||
|
||||
li {
|
||||
margin: 11px 26px 13px 19px;
|
||||
line-height: 17px;
|
||||
|
||||
span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
img:first-of-type {
|
||||
width: 14px;
|
||||
vertical-align: middle;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
img:last-of-type {
|
||||
float: right;
|
||||
margin-top: 2px;
|
||||
width: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
padding-left: 19px;
|
||||
padding-right: 20px;
|
||||
line-height: 37px;
|
||||
border-bottom: 1px solid #f2f2f2;
|
||||
|
||||
a {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.f11 {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.f12 {
|
||||
width: calc(100% - 60px);
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.f13 {
|
||||
width: 30px;
|
||||
}
|
||||
</style>
|
||||
5
src/components/OrgSelector/types.ts
Normal file
5
src/components/OrgSelector/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface OrgItem {
|
||||
id: string | number;
|
||||
name: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
Reference in New Issue
Block a user