Commit 756474e0 authored by yanzhengyang's avatar yanzhengyang

新增选择用户公共组件

parent be4b2904
<template>
<el-dialog v-model="selectRole" title="选择用户" style="width: 720px;font-weight: 800" @close="closeDialog">
<div class="dialog-box">
<div class="dialog-box-left">
<el-form :inline="true" class="demo-form-inline" :model="allRole" style="width: 100%;padding-top: 15px;background-color: #f4f4f9">
<el-form-item>
<el-input v-model="allRole" placeholder="请输入机构或成员名称" clearable style="width: 180px;margin-left: 20px"/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="selectSearch" circle></el-button>
</el-form-item>
</el-form>
<div class="demo-collapse">
<el-collapse v-model="activeNames">
<el-collapse-item :title="item[deptKey]" :name="item.id" v-for="(item, index) in filteredDeptList" :key="index" style="margin-left: 20px">
<div v-for="it in (Array.isArray(item[nameKey]) ? item[nameKey] : [item[nameKey]])" :key="it[nameKey]">
<el-checkbox
v-model="checked1"
:label="it[nameKey]"
:disabled="props.selectionMode === 'single' && checked1.length >= 1"
size="large"/>
</div>
</el-collapse-item>
</el-collapse>
</div>
</div>
<div class="dialog-box-right">
<div class="box-right-header">
<P v-if="props.selectionMode === 'single'">单选</P>
<p v-if="props.selectionMode === 'multiple'">已选{{ selectedItems.length }} / {{ totalItems }}</p>
<el-button icon="Delete" @click="clearAllSelected">清空</el-button>
</div>
<div class="box-right-content">
<div class="content-item" v-for="(item, index) in selectedItems" :key="index">
<span style="font-size: 14px;font-weight: 400">{{ item }}</span>
<el-button icon="Delete" @click="removeItem(index)" type="primary" circle></el-button>
</div>
</div>
</div>
</div>
<div style="margin-top: 20px;margin-left: 78%">
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="submitSelection">确定</el-button>
</div>
</el-dialog>
</template>
<script setup>
import { ref, watch } from 'vue';
import { defineProps, defineEmits } from 'vue';
// 接收父组件传入的props
const props = defineProps({
flag: {
type: Boolean,
default: false
},
deptList: {
type: Array,
required: true
},
nameKey: { // 成员名称字段名(默认'name')
type: String,
default: 'name'
},
deptKey: { // 部门名称字段名(默认'dept')
type: String,
default: 'dept'
},
selectionMode: { // 单选/多选模式参数
type: String,
default: 'multiple', // 'single' | 'multiple'
validator: (v) => ['single', 'multiple'].includes(v)
}
});
// 事件传递到父组件
const emit = defineEmits(['close', 'submit']);
// 声明组件的状态
const selectRole = ref(props.flag);
const allRole = ref('');
const checked1 = ref([]);
const selectedItems = ref([]);
const filteredDeptList = ref(props.deptList);
const activeNames = ref([props.deptList[0].id]); // 新增展开项绑定
// 计算左侧总项数:遍历deptList并计算所有成员数量
const totalItems = computed(() => {
return props.deptList.reduce((total, dept) => total + dept.name.length, 0);
});
// 搜索功能:根据输入内容过滤部门列表
const selectSearch = () => {
if (!allRole.value) {
filteredDeptList.value = props.deptList; // 如果搜索框为空,恢复所有项
activeNames.value = [props.deptList[0].id];
checked1.value = [];// 清空展开项
} else {
const searchTerm = allRole.value.toLowerCase();
const matchedNames = [];
filteredDeptList.value = props.deptList.filter(item => {
const deptMatch = item[props.deptKey].toLowerCase().includes(searchTerm);
const nameMatch = item[props.nameKey].some(it => {
const name = it[props.nameKey] ? it[props.nameKey] : it;
const isMatch = name.toLowerCase().includes(searchTerm);
if(isMatch) matchedNames.push(name); // 收集匹配的成员名称
return isMatch;
});
return deptMatch || nameMatch;
});
// 自动添加匹配的成员到选中列表(去重)
checked1.value = [...new Set([...checked1.value, ...matchedNames])];
activeNames.value = filteredDeptList.value.map(item => item.id);
}
};
// watch监听props更新,保持同步
watch(() => props.flag, (newVal) => {
selectRole.value = newVal;
});
watch(checked1, (newVal) => {
if (props.selectionMode === 'single') {
selectedItems.value = newVal.slice(-1); // 单选模式只保留最后一个
} else {
selectedItems.value = [...newVal];
}
});
// 清空已选项
const clearAllSelected = () => {
selectedItems.value = [];
checked1.value = [];
};
// 删除单个已选项
const removeItem = (index) => {
const removedItem = selectedItems.value[index]; // 先获取要删除的项
selectedItems.value.splice(index, 1);
checked1.value = checked1.value.filter(item => item !== removedItem);
};
// 关闭对话框
const closeDialog = () => {
emit('close')// 更新父组件v-model
clearAllSelected(); // 清空已选项
allRole.value = ''; // 清空搜索框
filteredDeptList.value = props.deptList;
activeNames.value = [props.deptList[0].id] // 重置展开项绑定
};
// 提交选择
const submitSelection = () => {
if (selectedItems.value.length > 0) {
emit('submit', selectedItems.value); // 仅在选中项存在时向父组件提交
}
closeDialog(); // 关闭弹框
};
</script>
<style scoped>
.dialog-box{
display: flex;
justify-content: space-around;
align-items: center;
.dialog-box-left{
border: 1px solid #f4f4f9;
width: 320px;
height: 500px;
display: flex;
flex-direction: column;
align-items: center;
.demo-collapse{
width: 100%;
background-color: white;
overflow: auto;
}
}
.dialog-box-right{
border: 1px solid #f4f4f9;
width: 320px;
height: 500px;
display: flex;
flex-direction: column;
align-items: center;
.box-right-header{
width: 100%;
height: 65px;
background-color: #f4f4f9;
display: flex;
justify-content: space-around;
align-items: center;
font-size: 16px;
}
.box-right-content{
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
.content-item{
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
margin-top: 10px;
}
}
}
}
</style>
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
<div> <div>
<div class="tab-components"> <div class="tab-components">
<span class="components-span">编制详情</span> <span class="components-span">编制详情</span>
<el-button class="btn-A">查看变更履历</el-button> <el-button class="btn-A" @click="changeView">查看变更履历</el-button>
</div> </div>
<el-descriptions border :column="4" style="margin-top: 20px"> <el-descriptions border :column="4" style="margin-top: 20px">
<el-descriptions-item label="文件编号:" label-align="right">kooriookami</el-descriptions-item> <el-descriptions-item label="文件编号:" label-align="right">kooriookami</el-descriptions-item>
...@@ -133,6 +133,8 @@ ...@@ -133,6 +133,8 @@
<el-form-item> <el-form-item>
<el-button class="btn-A" icon="Search" @click="handleQuery">搜索</el-button> <el-button class="btn-A" icon="Search" @click="handleQuery">搜索</el-button>
<el-button class="btn-B" icon="Refresh" @click="resetQuery">重置</el-button> <el-button class="btn-B" icon="Refresh" @click="resetQuery">重置</el-button>
<el-button class="btn-A" @click="singleOpenDialog">选择用户(单选)</el-button>
<el-button class="btn-A" @click="openDialog">选择用户(多选)</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-table :data="tableData" style="width: 100%" border > <el-table :data="tableData" style="width: 100%" border >
...@@ -163,7 +165,7 @@ ...@@ -163,7 +165,7 @@
<div> <div>
<div class="tab-components"> <div class="tab-components">
<span class="components-span">编制详情</span> <span class="components-span">编制详情</span>
<el-button class="btn-A">查看变更履历</el-button> <el-button class="btn-A" @click="changeView">查看变更履历</el-button>
</div> </div>
<el-descriptions border :column="4" style="margin-top: 20px"> <el-descriptions border :column="4" style="margin-top: 20px">
<el-descriptions-item label="文件编号:" label-align="right">kooriookami</el-descriptions-item> <el-descriptions-item label="文件编号:" label-align="right">kooriookami</el-descriptions-item>
...@@ -255,7 +257,7 @@ ...@@ -255,7 +257,7 @@
<div> <div>
<div class="tab-components"> <div class="tab-components">
<span class="components-span">编制详情</span> <span class="components-span">编制详情</span>
<el-button class="btn-A">查看变更履历</el-button> <el-button class="btn-A" @click="changeView">查看变更履历</el-button>
</div> </div>
<el-descriptions border :column="4" style="margin-top: 20px"> <el-descriptions border :column="4" style="margin-top: 20px">
<el-descriptions-item label="文件编号:" label-align="right">kooriookami</el-descriptions-item> <el-descriptions-item label="文件编号:" label-align="right">kooriookami</el-descriptions-item>
...@@ -365,7 +367,7 @@ ...@@ -365,7 +367,7 @@
<div> <div>
<div class="tab-components"> <div class="tab-components">
<span class="components-span">编制详情</span> <span class="components-span">编制详情</span>
<el-button class="btn-A">查看变更履历</el-button> <el-button class="btn-A" @click="changeView">查看变更履历</el-button>
</div> </div>
<el-descriptions border :column="4" style="margin-top: 20px"> <el-descriptions border :column="4" style="margin-top: 20px">
<el-descriptions-item label="文件编号:" label-align="right">kooriookami</el-descriptions-item> <el-descriptions-item label="文件编号:" label-align="right">kooriookami</el-descriptions-item>
...@@ -459,14 +461,33 @@ ...@@ -459,14 +461,33 @@
</el-tabs> </el-tabs>
</div> </div>
</div> </div>
<!-- 测试 -->
<select-role
v-model="selectRole"
:dept-list="deptList"
name-key="name"
dept-key="dept"
:selection-mode="selectType"
@submit="handleSelectionSubmit"
@close="() => selectRole = false"
/>
</template> </template>
<script setup> <script setup>
import {useRoute} from "vue-router";
import SelectRole from "@/components/SelectRole/index.vue"
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
import { ref, getCurrentInstance } from 'vue' import { ref, getCurrentInstance } from 'vue'
const route = useRoute()
const total = ref(0) const total = ref(0)
const formList = ref([]) const formList = ref([])
const activeTab = ref('first') // 默认激活第一个标签页 const activeTab = ref('first') // 默认激活第一个标签页
if(route.query.tab){
activeTab.value = route.query.tab
}
const radio1 = ref('1') const radio1 = ref('1')
const templateDetailList = ref([]) const templateDetailList = ref([])
// 修改data定义方式 // 修改data定义方式
...@@ -474,7 +495,68 @@ const queryParams = ref({ ...@@ -474,7 +495,68 @@ const queryParams = ref({
pageNum: 1, pageNum: 1,
pageSize: 10 pageSize: 10
}) })
const selectRole = ref(false)
const selectType = ref('')
//多选
const openDialog = () => {
selectRole.value = true;// 打开对话框
selectType.value = 'multiple';
};
//单选
const singleOpenDialog = () => {
selectRole.value = true;// 打开对话框
selectType.value = 'single'
};
const handleSelectionSubmit = (selectedItems) => {
console.log('已选中的项:', selectedItems); // 处理已选择的用户
};
const deptList = [
{
id: 1,
dept: '前端',
name: [
{name:'北京'},
{name:'上海'},
{name:'天津'},
{name:'重庆'},
],
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 2,
dept: '后端',
name: [
{name:'杭州'},
{name:'西安'},
{name:'深圳'},
{name:'青岛'},
],
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 3,
dept: '测试',
name: [
{name:'北京'},
{name:'上海'},
{name:'天津'},
{name:'重庆'},
],
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 4,
dept: '运维',
name: [
{name:'北京'},
{name:'上海'},
{name:'天津'},
{name:'重庆'},
],
address: 'No. 189, Grove St, Los Angeles',
},
]
watch(activeTab, (newVal) => { watch(activeTab, (newVal) => {
queryParams.value.pageNum = 1 // 切换标签时重置页码 queryParams.value.pageNum = 1 // 切换标签时重置页码
...@@ -506,7 +588,10 @@ const handlePagination = ({ page, limit }) => { ...@@ -506,7 +588,10 @@ const handlePagination = ({ page, limit }) => {
// }) // })
// } // }
const handleBack = () => { const handleBack = () => {
proxy.$router.push({ path: '/control/CCAPControlPlan/CCAPControlPlanManagementIndex'}); proxy.$router.push({ path: '/control/CCAPControlPlan/index'});
}
const changeView = () => {
proxy.$router.push({ path: '/control/CCAPControlPlan/change',query: { tab: activeTab.value }})
} }
onMounted(() => { onMounted(() => {
// getFrom(); // getFrom();
...@@ -533,4 +618,51 @@ onMounted(() => { ...@@ -533,4 +618,51 @@ onMounted(() => {
} }
} }
} }
.dialog-box{
display: flex;
justify-content: space-around;
align-items: center;
.dialog-box-left{
border: 1px solid #f4f4f9;
width: 320px;
height: 500px;
display: flex;
flex-direction: column;
align-items: center;
.demo-collapse{
width: 100%;
background-color: white;
}
}
.dialog-box-right{
border: 1px solid #f4f4f9;
width: 320px;
height: 500px;
display: flex;
flex-direction: column;
align-items: center;
.box-right-header{
width: 100%;
height: 65px;
background-color: #f4f4f9;
display: flex;
justify-content: space-around;
align-items: center;
font-size: 18px;
}
.box-right-content{
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
.content-item{
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
margin-top: 10px;
}
}
}
}
</style> </style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment