<script setup>
|
import {Search} from "@element-plus/icons-vue";
|
import {reactive} from "vue";
|
import {useRouter} from "vue-router"
|
import { useI18n } from 'vue-i18n'
|
const { t } = useI18n()
|
let language = ref(localStorage.getItem('lang') || 'zh')
|
const router = useRouter()
|
const add = ref(false)
|
const adda = ref(false)
|
import request from "@/utils/request"
|
import { ref, onMounted } from "vue";
|
// import { ref } from 'vue'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
// import LanguageMixin from './lang/LanguageMixin'
|
const selectedProjectNoa = ref(null); // 当前选中的角色
|
// const options = ref<any[]>([]); // 下拉选项列表
|
const name = ref('');
|
const tableData = ref([])
|
const options = ref([])
|
const selectedOptions = ref([])
|
// 定义级联选择器的属性
|
const cascaderProps = {
|
value: 'id',
|
label: 'menuName',
|
multiple: true
|
};
|
const slot = ref('')
|
|
const titleSelectJsona = ref({
|
processType: [],
|
|
})
|
onMounted(() => {
|
fetchOptionsa('');
|
});
|
// 角色下拉选
|
const fetchOptionsa = async () => {
|
try {
|
const response = await request.post('/loadGlass/sys/role/queryRole',{
|
key: ''
|
});
|
if (response.code == 200) {
|
tableData.value = response.data
|
// titleSelectJsona.value.processTypea = response.data.menuList;
|
// options.value = response.data.menuList
|
console.log(response.data);
|
|
} else {
|
ElMessage.warning(response.data);
|
}
|
} catch (error) {
|
console.error('Error fetching options:', error);
|
}
|
};
|
// 添加
|
const getTableRow = async () => {
|
try {
|
let menuList = [];
|
let parentIdMap = {}; // 用于存储已经添加的父项
|
selectedOptions.value.forEach(array => {
|
if (array.length >= 2) {
|
let id = array[0];
|
let parentId = array[1];
|
// 如果id还未作为父项添加,则添加它
|
if (!parentIdMap[id]) {
|
menuList.push({
|
id: id,
|
parentId: 0, // 通常,顶级项的parentId可能是null或特定的根ID,这里设为0可能是个特殊用途
|
children: []
|
});
|
parentIdMap[id] = menuList[menuList.length - 1]; // 更新映射
|
}
|
// 向对应的父项添加子项
|
if (!parentIdMap[id].children.some(child => child.id === parentId)) {
|
// 检查是否已存在相同的子项(基于id),避免重复添加
|
parentIdMap[id].children.push({
|
id: parentId,
|
parentId: id
|
});
|
}
|
}
|
});
|
const dataToSend = {
|
name: name.value,
|
menuList: menuList
|
};
|
const response = await request.post('/loadGlass/sys/role/saveRole', dataToSend);
|
if (response.code == 200) {
|
ElMessage.success(response.message);
|
add.value = false;
|
name.value = '';
|
selectedOptions.value = '';
|
fetchOptionsa();
|
} else {
|
ElMessage.error(response.message);
|
}
|
} catch (error) {
|
console.error(error);
|
}
|
};
|
|
// function buildCascaderOptions(menuList) {
|
// // 创建一个映射来快速查找父项
|
// const parentIdMap = {};
|
// // 初始化最终的级联选项数组
|
// const options = [];
|
// // 遍历所有菜单项,将它们添加到映射中,并构建顶级菜单项
|
// menuList.forEach(item => {
|
// // 如果parentId为0,则为顶级菜单项
|
// if (item.parentId === 0) {
|
// // 初始化children数组
|
// item.children = [];
|
// // 添加到最终的选项中
|
// options.push({
|
// value: item.id,
|
// label: item.menuName,
|
// children: item.children
|
// });
|
// // 将顶级菜单项添加到映射中(虽然在这个特定场景中可能不是必需的,但可以用于其他目的)
|
// parentIdMap[item.id] = item;
|
// } else {
|
// // 如果parentId不是0,则查找父项并添加到其children数组中
|
// // 注意:这里假设parentIdMap在之前已经填充了所有顶级菜单项
|
// if (!parentIdMap[item.parentId]) {
|
// // 如果父项不存在,则可能是数据不完整或错误,需要处理这种情况
|
// console.error(`Parent item with ID ${item.parentId} not found for child item with ID ${item.id}`);
|
// } else {
|
// parentIdMap[item.parentId].children.push({
|
// value: item.id,
|
// label: item.menuName
|
// // 这里不需要嵌套的children,除非你的菜单有多于两级的结构
|
// });
|
// }
|
// }
|
// });
|
// return options;
|
// }
|
function handleEdit(row) {
|
name.value = row.name;
|
const parentIdMap = {};
|
const menuItems = row.menuList.map(item => {
|
let parentId = item.parentId || null; // 或者使用 0,如果你的系统是这样设计的
|
if (!parentIdMap[parentId]) {
|
parentIdMap[parentId] = [];
|
}
|
parentIdMap[parentId].push({
|
id: item.id,
|
menuName: item.menuName,
|
children: [] // 初始为空,稍后会填充子项
|
});
|
return { id: item.id, menuName: item.menuName, parentId: parentId };
|
});
|
|
// 现在,我们遍历所有项,并将它们分配给它们的父项(如果有的话)
|
menuItems.forEach(item => {
|
if (item.parentId !== null && parentIdMap[item.parentId]) {
|
// 将当前项添加到其父项的 children 数组中
|
parentIdMap[item.parentId].push({
|
...item, // 复制除了 parentId 之外的所有属性
|
children: [] // 这里我们不需要再次添加 children,因为它已经在 parentIdMap 中被初始化了
|
});
|
// 注意:这里实际上是一个错误,因为我们不应该向 parentIdMap[item.parentId] 数组中添加整个项,
|
// 而应该只更新它的 children 数组。但上面的代码示例了如何访问父项。
|
// 正确的做法是在构建 parentIdMap 时就设置好 children 数组,并在后面不再修改 parentIdMap[item.parentId] 数组。
|
}
|
// 注意:上面的代码逻辑有误,因为我们在构建 parentIdMap 时已经为每个项设置了 children 数组。
|
// 我们应该直接修改这些 children 数组,而不是向 parentIdMap[item.parentId] 数组添加新项。
|
});
|
|
// 但是,由于我们在构建 parentIdMap 时已经为每个项(包括其父项)设置了 children 数组,
|
// 我们实际上不需要上面的循环来重新分配子项。
|
// 我们只需要找到顶级项(parentId 为 null 或 0 的项),并将它们设置为 selectedOptions.value
|
|
// 假设顶级项的 parentId 为 null(或 0,根据你的系统)
|
const topLevelItems = parentIdMap[null] || parentIdMap[0] || [];
|
|
// selectedOptions.value 应该是顶级项的数组,但首先我们需要将它们从 parentIdMap 的值中提取出来
|
// 由于我们在构建 parentIdMap 时已经为每个顶级项设置了 children,所以我们可以直接使用这些项
|
selectedOptions.value = topLevelItems;
|
|
// 注意:selectedOptions.value 的具体格式应该与你的级联选择器组件所期望的格式相匹配
|
// 如果你的级联选择器组件期望的是一个包含 value 和 label 的数组数组,你可能还需要进一步转换 topLevelItems
|
adda.value = true; // 显示对话框
|
|
}
|
|
// 注意:上面的代码可能仍然需要根据你的具体数据结构进行调整
|
// 特别是关于 parentId 的处理,以及如何将菜单项正确地分配给它们的父项
|
// 处理编辑按钮点击
|
// function handleEdit(row) {
|
// name.value = row.name;
|
// let cascaderOptions = buildCascaderOptions(row.menuList);
|
// selectedOptions.value = cascaderOptions; // 假设selectedOptions是v-model绑定的级联选择器的值
|
// console.log(cascaderOptions); // 查看构建后的级联选项
|
// // let transformedMenuList = row.menuList.map(item => ({
|
// // id: item.id, // 假设每个项都有一个id作为唯一标识
|
// // menuName: item.menuName, // 显示给用户的文本
|
// // // children: item.children ? item.children.map(child => ({ value: child.id, label: child.name })) : []
|
// // }));
|
// // selectedOptions.value = transformedMenuList
|
// console.log(transformedMenuList);
|
// adda.value = true; // 显示对话框
|
// window.localStorage.setItem('id', row.id)
|
// }
|
// 编辑
|
const getTableRowa = async () => {
|
let id = window.localStorage.getItem('id')
|
try {
|
let menuList = [];
|
let parentIdMap = {}; // 用于存储已经添加的父项
|
selectedOptions.value.forEach(array => {
|
if (array.length >= 2) {
|
let id = array[0];
|
let parentId = array[1];
|
// 如果id还未作为父项添加,则添加它
|
if (!parentIdMap[id]) {
|
menuList.push({
|
id: id,
|
parentId: 0, // 通常,顶级项的parentId可能是null或特定的根ID,这里设为0可能是个特殊用途
|
children: []
|
});
|
parentIdMap[id] = menuList[menuList.length - 1]; // 更新映射
|
}
|
// 向对应的父项添加子项
|
if (!parentIdMap[id].children.some(child => child.id === parentId)) {
|
// 检查是否已存在相同的子项(基于id),避免重复添加
|
parentIdMap[id].children.push({
|
id: parentId,
|
parentId: id
|
});
|
}
|
}
|
});
|
const dataToSend = {
|
id:id,
|
name: name.value,
|
menuList: menuList
|
};
|
const response = await request.post('/loadGlass/sys/role/updateRole', dataToSend);
|
if (response.code == 200) {
|
ElMessage.success(response.message);
|
adda.value = false;
|
name.value = '';
|
selectedOptions.value = '';
|
fetchOptionsa();
|
} else {
|
ElMessage.error(response.message);
|
}
|
} catch (error) {
|
console.error(error);
|
}
|
};
|
// 删除
|
const opena = async(row) => {
|
try {
|
const confirmResult = await ElMessageBox.confirm(
|
t('delivery.derole'),
|
t('delivery.prompt'),
|
{
|
confirmButtonText: t('delivery.yes'),
|
cancelButtonText: t('delivery.cancel'),
|
type: 'warning',
|
}
|
);
|
if (confirmResult === 'confirm') {
|
// 用户点击了“是”,现在调用删除接口
|
const response = await request.post("/loadGlass/sys/role/delete",[row.id])
|
if (response.code === 200) {
|
ElMessage.success(response.message);
|
fetchOptionsa()
|
} else {
|
// 删除失败,您可以处理错误或显示错误信息给用户
|
ElMessage.error(response.message);
|
// alert('删除失败:' + deleteResponse.message);
|
}
|
}
|
} catch (error) {
|
// 处理可能出现的错误,比如 ElMessageBox 抛出的异常等
|
console.error('发生错误:', error);
|
}
|
};
|
request.get("/loadGlass/sys/menu/nav").then((res) => {
|
if (res.code == 200) {
|
console.log(res.data);
|
options.value = res.data.tree
|
console.log( options.value);
|
} else {
|
ElMessage.warning(res.msg)
|
}
|
});
|
</script>
|
|
<template>
|
<div>
|
<el-button type="primary" style="margin-top: 10px;margin-left: 10px;" size="mini" id="searchButton" @click="add = true">{{ $t('delivery.addrole') }}</el-button>
|
<el-card style="flex: 1;margin-left: 10px;margin-top: 20px;" v-loading="loading">
|
<div style="width: 98%; height: calc(100% - 35px); overflow-y: auto;">
|
<el-table height="240" ref="table"
|
@selection-change="handleSelectionChange"
|
:data="tableData" :header-cell-style="{background:'#F2F3F5 ',color:'#1D2129'}">
|
<el-table-column prop="name" align="center" :label="$t('delivery.role')" min-width="180" />
|
<el-table-column fixed="right" :label="$t('delivery.operate')" align="center" width="200">
|
<template #default="scope">
|
<el-button size="mini" type="text" plain @click="handleEdit(scope.row)">{{ $t('delivery.edit') }}</el-button>
|
<el-button size="mini" type="text" plain @click="opena(scope.row)">{{ $t('delivery.delete') }}</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</el-card>
|
</div>
|
<el-dialog v-model="add" top="23vh" width="37%" :title="$t('productStock.addusername')" >
|
<div style="margin-left: -50px;margin-top: 10px;margin-bottom: 10px;">
|
<el-form ref="formRef" size="mini" label-width="150px">
|
<el-form label-width="100px" label-position="right">
|
<el-row style="margin-top: -15px;margin-bottom: -2px;">
|
<el-col :span="6">
|
<div id="dt" style="font-size: 15px;">
|
<div>
|
<el-form-item :label="$t('delivery.rolea')" :required="true" style="width: 25vw">
|
<el-input :placeholder="$t('delivery.inrole')" v-model="name" autocomplete="off" />
|
</el-form-item></div></div>
|
</el-col>
|
</el-row>
|
<el-row style="margin-top: 10px;">
|
<el-col :span="6">
|
<div id="dt" style="font-size: 15px;">
|
<div>
|
<el-form-item :label="$t('delivery.choice')" :required="true" style="width: 25vw;">
|
<el-cascader
|
v-model="selectedOptions"
|
:placeholder="$t('delivery.inchoice')"
|
:props="cascaderProps"
|
:options="options"
|
style="width: 330px"
|
clearable />
|
</el-form-item></div></div>
|
</el-col>
|
</el-row>
|
</el-form>
|
</el-form>
|
</div>
|
<template #footer>
|
<div id="dialog-footer">
|
<el-button type="primary" @click="getTableRow">
|
{{ $t('delivery.sure') }}
|
</el-button>
|
<el-button @click="add = false"> {{ $t('delivery.cancel') }}</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
<el-dialog v-model="adda" top="23vh" width="37%" :title="$t('delivery.editrole')">
|
<div style="margin-left: -50px;margin-top: 10px;margin-bottom: 10px;">
|
<el-form ref="formRef" size="mini" label-width="150px">
|
<el-form label-width="100px" label-position="right">
|
<el-row style="margin-top: -15px;margin-bottom: -2px;">
|
<el-col :span="6">
|
<div id="dt" style="font-size: 15px;">
|
<div>
|
<el-form-item :label="$t('delivery.rolea')" :required="true" style="width: 25vw">
|
<el-input :placeholder="$t('delivery.inrole')" v-model="name" autocomplete="off" />
|
</el-form-item></div></div>
|
</el-col>
|
</el-row>
|
<el-row style="margin-top: 10px;">
|
<el-col :span="6">
|
<div id="dt" style="font-size: 15px;">
|
<div>
|
<el-form-item :label="$t('delivery.choice')" :required="true" style="width: 25vw;">
|
<el-cascader
|
v-model="selectedOptions"
|
:placeholder="$t('delivery.inchoice')"
|
:props="cascaderProps"
|
:options="options"
|
style="width: 330px"
|
clearable />
|
</el-form-item></div></div>
|
</el-col>
|
</el-row>
|
</el-form>
|
</el-form>
|
</div>
|
<template #footer>
|
<div id="dialog-footer">
|
<el-button type="primary" @click="getTableRowa">
|
{{ $t('delivery.sure') }}
|
</el-button>
|
<el-button @click="adda = false">{{ $t('delivery.cancel') }}</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</template>
|
|
<style scoped>
|
|
#dt { display:block; float:left;line-height: 20px;margin-left: 100px;}
|
#dta { display:block; float:left;line-height: 20px;margin-left: 80%;}
|
#dialog-footer{
|
text-align: center;
|
margin-top: -15px;
|
}
|
#message{
|
text-align: center;
|
align-items: center;
|
color: black;
|
width: 200px;
|
height: 100px;
|
background-color: #337ecc;
|
margin-left: 28%;
|
}
|
#awatch{
|
height: 460px;
|
/* margin-top: -60px; */
|
}
|
</style>
|