| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- <template>
- <div class="User">
- <div class="left">
- <div class="filter-title">
- <el-input v-model="queryContent" placeholder="请输入搜索的内容" clearable>
- <template #prepend>
- <el-select v-model="selectType" class="select-type">
- <el-option v-for="item in searchOptions" :key="item.value" :value="item.value" :label="item.label" />
- </el-select>
- </template>
- </el-input>
- <el-button type="primary" @click="handleSearch">搜 索</el-button>
- </div>
- <div class="filter-result" v-loading="loading">
- <div class="empty" v-if="nodeData[0].children.length === 0">
- <img :src="empty" alt="" />
- <div>暂无数据</div>
- </div>
- <el-tree
- v-else
- ref="treeRef"
- :data="nodeData"
- show-checkbox
- node-key="id"
- :props="defaultProps"
- :default-expand-all="true"
- style="padding: 10px 0"
- @check-change="handleCheckChange"
- />
- </div>
- </div>
- <div class="right">
- <div class="head">
- <span>已选择:{{ selectedPersonList.length }}人</span>
- </div>
- <div class="selected">
- <el-tag
- v-for="person in selectedPersonList"
- :key="person.id"
- closable
- @close="handleRemoveSelectedPerson(person.id)"
- >
- {{ person.name }}
- </el-tag>
- </div>
- <div class="footer">
- <el-button @click="emit('cancel')">取消</el-button>
- <el-button type="primary" @click="handleSubmit">确定</el-button>
- </div>
- </div>
- </div>
- </template>
- <script lang="ts" setup>
- import { nextTick, ref, watch } from 'vue';
- import empty from 'assets/images/empty@1X.png';
- import { queryAvailableUserList } from '@/api/push-object';
- import type { TreeNodeData } from '@/views/disaster/types';
- import type { UserInfo } from '@/types/push-object';
- import type { ElTree } from 'element-plus';
- const props = defineProps<{
- customUserList: UserInfo[];
- }>();
- const loading = ref(false);
- const queryContent = ref('');
- const treeRef = ref<InstanceType<typeof ElTree>>();
- const nodeData = ref<TreeNodeData[]>([
- {
- id: -1,
- name: '全部',
- children: [],
- },
- ]);
- const searchResult = ref<TreeNodeData[]>([]);
- const selectedPersonList = ref<TreeNodeData[]>([]);
- const defaultProps = {
- children: 'children',
- label: 'name',
- };
- const searchOptions = ref([
- { value: 'realname', label: '姓名' },
- { value: 'username', label: '工号' },
- ]);
- const selectType = ref(searchOptions.value[0].value);
- const getUserList = async () => {
- loading.value = true;
- const res = await queryAvailableUserList();
- searchResult.value = res.map((user) => {
- return {
- id: user.id,
- name: `${user.username}-${user.realname}`,
- children: [],
- };
- });
- nodeData.value[0].children = searchResult.value;
- const selectedIds = selectedPersonList.value.map((item) => item.id);
- await nextTick();
- treeRef.value?.setCheckedKeys(selectedIds);
- loading.value = false;
- };
- const handleSearch = () => {
- getUserList();
- };
- const removeSelectedPerson = (id: number) => {
- const index = selectedPersonList.value.findIndex((item) => item.id === id);
- if (index !== -1) {
- selectedPersonList.value.splice(index, 1);
- }
- };
- const handleCheckChange = (node: TreeNodeData, checked: boolean) => {
- if (node.children.length) return;
- if (checked) {
- const exists = selectedPersonList.value.find((item) => item.id === node.id);
- if (exists) return;
- selectedPersonList.value.push(node);
- } else {
- removeSelectedPerson(node.id);
- }
- };
- const handleRemoveSelectedPerson = (id: number) => {
- removeSelectedPerson(id);
- if (!treeRef.value) return;
- treeRef.value.setChecked(id, false, true);
- };
- const emit = defineEmits(['cancel', 'submit']);
- const handleSubmit = () => {
- const userList = selectedPersonList.value.map((item) => {
- return {
- id: item.id,
- username: item.name.split('-')[0],
- realname: item.name.split('-')[1],
- };
- });
- emit('submit', userList);
- emit('cancel');
- };
- watch(
- () => props.customUserList,
- (newVal) => {
- selectedPersonList.value = newVal.map((item) => {
- return {
- id: item.id,
- name: `${item.username}-${item.realname}`,
- children: [],
- };
- });
- },
- {
- immediate: true,
- },
- );
- </script>
- <style lang="scss" scoped>
- .User {
- display: flex;
- width: 100%;
- height: 100%;
- .left {
- display: flex;
- flex-direction: column;
- width: 50%;
- height: 100%;
- padding: 0 5px;
- border-right: 1px solid rgba($text-color, 0.1);
- }
- .filter-title {
- @include flex-center;
- gap: 10px;
- justify-content: space-between;
- }
- .filter-result {
- flex: 1;
- overflow-y: auto;
- .empty,
- img {
- width: 100%;
- }
- .empty {
- @include flex-center;
- flex-direction: column;
- height: 100%;
- gap: 5px;
- }
- }
- .select-type {
- width: 75px;
- }
- .right {
- display: flex;
- flex-direction: column;
- flex: 1;
- height: 100%;
- position: relative;
- margin-left: 16px;
- gap: 20px;
- .head {
- display: flex;
- align-items: center;
- font-weight: 400;
- font-size: 16px;
- color: rgba($text-color, 0.88);
- line-height: 22px;
- margin: 6px 0 6px;
- }
- .selected {
- display: flex;
- flex-wrap: wrap;
- gap: 8px;
- overflow-y: auto;
- max-height: calc(100% - 120px);
- }
- .footer {
- display: flex;
- gap: 6px;
- position: absolute;
- right: 24px;
- bottom: 20px;
- }
- }
- }
- </style>
|