You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

597 lines
18 KiB

7 months ago
<!-- eslint-disable vue/v-on-event-hyphenation -->
<template>
<div>
<div class="search-input">
<a-input
v-model:value="searchValue"
:placeholder="placeholder"
@pressEnter="onSearch"
:bordered="false" />
<ns-icon class="iconfont" style="margin: auto" name="search" />
</div>
<div class="checkbox-content">
<p class="selectLevel">
<span
v-for="(item, index) in selectLevel"
:key="index"
@click="checkSelectLevel(item, index)">
<span v-if="index != 0">></span>
<span
:class="index == selectLevel.length - 1 ? 'selectLevel-last-span' : 'selectLevel-span'"
>{{ item.name }}</span
>
</span>
</p>
<div class="candidate-content" v-if="candidateValues.length > 0">
<div style="padding: 4px 0px" v-if="filterMultiple">
<a-checkbox
:indeterminate="state.indeterminate"
v-model:checked="state.checkAll"
@change="onCheckAllChange">
全选
</a-checkbox>
</div>
<div v-for="(item, index) in candidateValues" :key="index" class="checkbox">
<a-checkbox
v-if="filterMultiple"
v-model:checked="item.checked"
@change="onCheckChange($event, item)"
>{{ item.name }}</a-checkbox
>
<a-radio v-else v-model:checked="item.checked" @click="onCheckChangeRadio(item)">{{
item.name
}}</a-radio>
<span
v-if="searchType == 'dept'"
@click="checkSubordinate(item)"
:class="
item.subordinateDisable ? 'checkbox-subordinate-disable' : 'checkbox-subordinate'
">
<ns-icon
class="iconfont"
style="margin: auto; width: 12px; height: 12px"
:name="item.subordinateDisable ? 'subordinate-dis' : 'subordinate'" />
下级</span
>
</div>
</div>
<div v-if="candidateValues.length <= 0 && ifLoading">
<a-result title="暂无相关部门/人员">
<template #icon>
<ns-icon
class="iconfont"
style="margin: auto; width: 120px; height: 120px"
name="noSearchData" />
</template>
</a-result>
</div>
</div>
</div>
</template>
<script lang="ts">
import { computed, inject, reactive } from 'vue';
import { watch } from 'vue';
import { defineComponent, ref, onMounted } from 'vue';
import { http } from '../../util/http';
import { remove } from 'lodash-es';
import { unref } from 'vue';
import { compareArrays } from './util';
import { Emitter } from 'mitt';
//单独部门/人员 只区分单选或多选
export default defineComponent({
name: 'NsShuttleFrameDeptOrMember',
props: {
//是否多选
filterMultiple: {
type: Boolean,
default: false,
},
placeholder: String,
searchType: {
type: String,
default: 'account',
},
// componentRef: String,
api: {
type: Object,
// eslint-disable-next-line vue/require-valid-default-prop
default: {
account: '/api/passport/passport/objs/DepartmentAccounts',
dept: '/api/passport/passport/objs/Department',
},
},
},
emits: ['selected'],
setup(props, ctx) {
const lmEmitter = inject('lmEmitter') as Emitter<emitEvents>;
// function initData() {
// if (props.searchType == 'dept') {
// organizationGet();
// } else {
// accountGet();
// }
// }
// initData();
lmEmitter.on('deleteAllSelected', (data) => {
deleteAllSelected();
});
lmEmitter.on('deleteSelected', (data) => {
deleteSelected(data);
});
//全部的值
const departmentAllData = ref([]);
const accountAllData = ref([]);
const ifLoading = ref(false);
//展示的候选值
const candidateValues = ref([]);
//选中的层级
const selectLevel = ref<any>([]);
//选中的值
const selectedValue = ref<any>([]);
//获取部门的值
async function organizationGet() {
let data = await http.get(
props.api.dept,
{ pageSize: 9999, levelID: 0 },
{ timeout: 120 * 1000 },
);
return data;
}
//获取人员的值
async function accountGet() {
await http.get(props.api.account, { pageSize: 9999 }, { timeout: 120 * 1000 });
}
const state = reactive({
indeterminate: false,
checkAll: false,
checkedList: [],
});
const onCheckAllChange = (e: any) => {
Object.assign(state, {
indeterminate: false,
checkAll: e.target.checked,
});
//全选
if (e.target.checked) {
//selectedValue.value 需要不影响之前的选中
state.checkedList = [];
candidateValues.value.map((item) => {
state.checkedList.push(item.ID);
const ret = selectedValue.value.find((ev: { id: any }) => {
return ev.id === item.ID;
});
if (ret == undefined) {
selectedValue.value.push({
type: props.searchType,
id: item.ID,
name: item.name,
});
}
item.subordinateDisable = true;
item.checked = e.target.checked;
});
} else {
state.checkedList = [];
candidateValues.value.map((item) => {
remove(unref(selectedValue.value), (elem: object) => {
return elem.id === item.ID;
});
item.subordinateDisable = false;
item.checked = e.target.checked;
});
}
};
watch(
() => state.checkedList,
(val) => {
state.indeterminate = !!val.length && val.length < candidateValues.value.length;
state.checkAll =
val.length === candidateValues.value.length && candidateValues.value.length > 0;
},
{ deep: true },
);
// watch(
// () => selectedValue.value,
// (val) => {
// val.map((elem) => {
// elem.componentRef = props.componentRef;
// });
// },
// { immediate: true, deep: true },
// );
const selectedValueCopy = computed(() => JSON.parse(JSON.stringify(selectedValue.value)));
watch(
() => selectedValueCopy.value,
(newData, old) => {
let val = [];
let delVal = [];
if (props.filterMultiple) {
//新增
if (!old || newData.length > old.length) {
val = compareArrays(newData, old);
ctx.emit('selected', val, 'add');
}
//删除
else {
delVal = compareArrays(old, newData);
ctx.emit('selected', delVal, 'del');
}
} else {
//取消选择
if (newData.length == 0 && old) {
ctx.emit('selected', old, 'del');
}
//切换选择
else if (old) {
ctx.emit('selected', newData, 'add');
ctx.emit('selected', old, 'del');
}
}
},
{ immediate: true, deep: true },
);
const onCheckChange = (e: any, item: object) => {
if (e.target.checked) {
state.checkedList.push(item.ID);
selectedValue.value.push({
type: props.searchType,
id: item.ID,
name: item.name,
});
candidateValues.value.map((elem) => {
if (item.ID === elem.ID) {
elem.subordinateDisable = true;
}
});
} else {
remove(unref(state.checkedList), (elem: object) => {
return elem === item.ID;
});
remove(unref(selectedValue.value), (elem: object) => {
return elem.id === item.ID;
});
candidateValues.value.map((elem) => {
if (item.ID === elem.ID) {
elem.checked = false;
elem.subordinateDisable = false;
}
});
}
};
function checkSubordinate(item: { subordinateDisable: any; ID: any; name: any }) {
if (item.subordinateDisable) return;
state.checkedList = [];
selectLevel.value.push({
id: item.ID,
name: item.name,
});
candidateValues.value = departmentAllData.value.filter(function (elem) {
return elem.levelID == item.ID;
});
}
function checkSelectLevel(item: { id: any }, index: number) {
if (index == selectLevel.value.length - 1) return;
selectLevel.value.forEach((elem: { id: any }, index: number) => {
if (elem.id == item.id) {
selectLevel.value.splice(index + 1, selectLevel.value.length - 1);
}
});
candidateValues.value = departmentAllData.value.filter(function (elem) {
return elem.levelID == item.id;
});
if (!props.filterMultiple) {
let ifSelected = candidateValues.value.filter(function (elem) {
return elem.checked == true;
});
//说明选中了,之前的选中要删除
if (ifSelected.length > 0 && ifSelected[0].ID !== selectedValue.value[0].id) {
candidateValues.value.map((elem) => {
elem.checked = false;
elem.subordinateDisable = false;
});
}
}
}
function getSelectedValue() {
// selectedValue.value.map((elem) => {
// elem.componentRef = props.componentRef;
// });
return selectedValue.value;
}
//单选场景
const onCheckChangeRadio = (item: object) => {
console.log(item.checked);
if (!item.checked) {
selectedValue.value = [
{
type: props.searchType,
id: item.ID,
name: item.name,
},
];
candidateValues.value.map((elem) => {
elem.checked = item.ID === elem.ID;
elem.subordinateDisable = item.ID === elem.ID;
});
} else {
remove(unref(selectedValue.value), (elem: object) => {
return elem.id === item.ID;
});
candidateValues.value.map((elem) => {
if (item.ID === elem.ID) {
elem.checked = false;
elem.subordinateDisable = false;
}
});
}
console.log('selectedValue', selectedValue.value);
};
//删除已选择
function deleteSelected(item: { type: string; id: object }) {
console.log('deleteSelected', item);
if (item.type == 'dept') {
candidateValues.value.map((elem) => {
if (elem.ID == item.id) {
elem.subordinateDisable = false;
elem.checked = false;
}
});
remove(unref(state.checkedList), (elem: object) => {
return elem.deptID === item.id && elem.type == item.type;
});
} else {
candidateValues.value.map((elem) => {
if (elem.ID == item.id) {
elem.checked = false;
}
});
remove(unref(state.checkedList), (elem: object) => {
return elem === item.id;
});
}
remove(unref(selectedValue.value), (elem: object) => {
return elem.id === item.id && elem.type == item.type;
});
}
//清空已选择
function deleteAllSelected() {
state.checkedList = [];
selectedValue.value = [];
candidateValues.value.map((elem) => {
elem.checked = false;
});
}
const searchValue = ref();
function onSearch() {
if (selectLevel.value.length > 1) {
selectLevel.value = selectLevel.value.splice(0, selectLevel.value.length - 1);
}
if (props.searchType == 'account') {
candidateValues.value = accountAllData.value.filter(function (item) {
return item.name.includes(searchValue.value);
});
} else {
candidateValues.value = departmentAllData.value.filter(function (item) {
return item.name.includes(searchValue.value);
});
}
}
function formatOrganizationData(data: { data: string | any[] }) {
if (data.data.length > 0) {
selectLevel.value.push({
id: 0,
name: data.data[0].tenant,
});
let selectedList: any[] = [];
selectedValue.value.map((item: { id: any }) => {
selectedList.push(item.id);
});
departmentAllData.value = data.data;
initSelectedOrgan();
}
}
function initSelectedOrgan() {
let selectedList: any[] = [];
selectedValue.value.map((item: { id: any }) => {
selectedList.push(item.id);
});
departmentAllData.value.map((item) => {
item.subordinateDisable = selectedList.includes(item.ID);
item.checked = selectedList.includes(item.ID);
});
candidateValues.value = departmentAllData.value.filter(function (item: {
checked: boolean;
ID: any;
levelID: number;
}) {
return item.levelID == 0;
});
}
function formatAccountData(data: { data: { tenant: any }[] }) {
if (data.data.length > 0) {
selectLevel.value.push({
id: 0,
name: data.data[0].tenant,
});
let selectedList: any[] = [];
selectedValue.value.map((item: { id: any }) => {
selectedList.push(item.id);
});
data.data.map((item: { subordinateDisable: boolean; ID: any; checked: boolean }) => {
item.subordinateDisable = selectedList.includes(item.ID);
item.checked = selectedList.includes(item.ID);
});
accountAllData.value = data.data;
candidateValues.value = data.data.filter(function (item: {
checked: boolean;
levelID: number;
}) {
return item.levelID == 0;
});
candidateValues.value = data.data;
}
}
//初始化值
lmEmitter.on('setDefaultDataMOD', (data: any) => {
if (props.searchType == 'account') {
accountGet().then((res) => {
formatAccountData(res);
if (data.length <= 0) {
return;
}
setTimeout(() => {
//单选
initSelectedValue(accountAllData.value, data, 'account');
}, 100);
});
} else {
organizationGet().then((res) => {
formatOrganizationData(res);
if (data.length <= 0) {
return;
}
setTimeout(() => {
initSelectedValue(departmentAllData.value, data, 'dept');
}, 100);
});
}
});
function initSelectedValue(list: any[], data: any[], type: string) {
//单选
if (!props.filterMultiple) {
let item = list.filter(function (elem: { name: any }) {
return elem.name == data[0].name;
});
data[0].id = item[0].ID;
}
//多选
else {
let nameList: any[] = [];
data.map((item: { name: any }) => {
nameList.push(item.name);
});
let dataList = list.filter(function (elem: { name: any }) {
return nameList.includes(elem.name);
});
for (let index = 0; index < data.length; index++) {
try {
dataList.map((dl: { name: any }) => {
if (dl.name == data[index].name) {
throw dl;
}
});
} catch (error) {
data[index].id = error.ID;
}
}
}
selectedValue.value = data;
ifLoading.value = true;
if (type == 'dept') {
initSelectedOrgan();
}
}
return {
candidateValues,
onCheckAllChange,
searchValue,
onSearch,
onCheckChange,
state,
checkSubordinate,
selectLevel,
checkSelectLevel,
selectedValue,
getSelectedValue,
onCheckChangeRadio,
deleteSelected,
deleteAllSelected,
ifLoading,
};
},
});
</script>
<style lang="less" scoped>
.search-input {
display: flex;
border: 1px solid #dcdfe2;
border-radius: 8px;
padding-right: 8px;
margin-bottom: 8px;
}
.checkbox {
padding: 4px 0;
&-subordinate {
float: right;
color: @primary-color;
cursor: pointer;
}
&-subordinate-disable {
float: right;
color: #9b9b9b;
cursor: default;
}
}
.selectLevel {
margin-bottom: 2px;
&-last-span {
color: #9b9b9b;
padding: 0px 4px;
cursor: pointer;
}
&-span {
padding: 0px 4px;
cursor: pointer;
}
}
.checkbox-content {
//overflow-y: auto;
// min-height: 250px;
// max-height: 350px;
// height: 250px;
}
.candidate-content {
height: 250px;
overflow-y: auto;
}
:deep(.ant-result) {
padding: 24px;
}
:deep(.ant-result-icon) {
margin-bottom: 0px;
}
:deep(.ant-result-title) {
color: #747677;
text-align: center;
font-size: 18px;
}
</style>