fix
This commit is contained in:
@@ -1,178 +1,169 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
:title="dialogTitle"
|
||||
width="80%"
|
||||
:show-close="false"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:before-close="handleBeforeClose"
|
||||
center
|
||||
>
|
||||
<el-form>
|
||||
<el-form-item class="role-form-item">
|
||||
<el-radio-group v-model="radio" class="role-radio-group" @change="handleChangeRole">
|
||||
<template v-for="(roles, groupName) in allRoleGroups" :key="groupName">
|
||||
<el-card class="role-group-card" shadow="hover">
|
||||
<template #header>
|
||||
<span class="group-name">{{ groupName }}</span>
|
||||
</template>
|
||||
<div class="role-group">
|
||||
<el-radio-button
|
||||
v-for="item in roles"
|
||||
:key="item.roleCode"
|
||||
:label="item.roleCode"
|
||||
size="small"
|
||||
>
|
||||
{{ item.roleName }}
|
||||
</el-radio-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
:title="dialogTitle"
|
||||
width="80%"
|
||||
:show-close="false"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:before-close="handleBeforeClose"
|
||||
center
|
||||
>
|
||||
<el-form>
|
||||
<el-form-item class="role-form-item">
|
||||
<el-radio-group v-model="radio" class="role-radio-group" @change="handleChangeRole">
|
||||
<template v-for="(roles, groupName) in allRoleGroups" :key="groupName">
|
||||
<el-card class="role-group-card" shadow="hover">
|
||||
<template #header>
|
||||
<span class="group-name">{{ groupName }}</span>
|
||||
</template>
|
||||
<div class="role-group">
|
||||
<el-radio-button v-for="item in roles" :key="item.roleCode" :label="item.roleCode" size="small">
|
||||
{{ item.roleName }}
|
||||
</el-radio-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-if="!requireSelectToClose" #footer>
|
||||
<el-button @click="handleFooterClose">关 闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<template v-if="!requireSelectToClose" #footer>
|
||||
<el-button @click="handleFooterClose">关 闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, toRef } from 'vue'
|
||||
import { listAllRole } from '/@/api/admin/role'
|
||||
import { Local, Session } from '/@/utils/storage'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { ref, computed, toRef } from 'vue';
|
||||
import { listAllRole } from '/@/api/admin/role';
|
||||
import { Local, Session } from '/@/utils/storage';
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
|
||||
/** 弹框标题,如「角色切换」「登录角色选择」 */
|
||||
const props = withDefaults(
|
||||
defineProps<{ title?: string; requireSelectToClose?: boolean }>(),
|
||||
{ title: '角色切换', requireSelectToClose: false }
|
||||
)
|
||||
const dialogTitle = computed(() => props.title)
|
||||
const props = withDefaults(defineProps<{ title?: string; requireSelectToClose?: boolean }>(), { title: '角色切换', requireSelectToClose: false });
|
||||
const dialogTitle = computed(() => props.title);
|
||||
|
||||
const visible = ref(false)
|
||||
const radio = ref('')
|
||||
const visible = ref(false);
|
||||
const radio = ref('');
|
||||
/** 按分组名分组的角色列表:{ "未分组": [{ roleId, roleName, roleCode, ... }], ... } */
|
||||
const allRoleGroups = ref<Record<string, any[]>>({})
|
||||
const requireSelectToClose = toRef(props, 'requireSelectToClose')
|
||||
const allRoleGroups = ref<Record<string, any[]>>({});
|
||||
const requireSelectToClose = toRef(props, 'requireSelectToClose');
|
||||
|
||||
const open = () => {
|
||||
if (visible.value) return
|
||||
visible.value = true
|
||||
listAllRole().then((res) => {
|
||||
allRoleGroups.value = res.data && typeof res.data === 'object' && !Array.isArray(res.data)
|
||||
? res.data
|
||||
: { '未分组': Array.isArray(res.data) ? res.data : [] }
|
||||
radio.value = Local.get('roleCode')
|
||||
})
|
||||
}
|
||||
if (visible.value) return;
|
||||
visible.value = true;
|
||||
listAllRole().then((res) => {
|
||||
allRoleGroups.value =
|
||||
res.data && typeof res.data === 'object' && !Array.isArray(res.data) ? res.data : { 未分组: Array.isArray(res.data) ? res.data : [] };
|
||||
radio.value = Local.get('roleCode');
|
||||
});
|
||||
};
|
||||
|
||||
/** 根据 roleCode 从分组数据中查找角色 */
|
||||
const findRoleByCode = (code: string) => {
|
||||
for (const roles of Object.values(allRoleGroups.value)) {
|
||||
if (!Array.isArray(roles)) continue
|
||||
const found = roles.find((r: any) => r.roleCode === code)
|
||||
if (found) return found
|
||||
}
|
||||
return null
|
||||
}
|
||||
for (const roles of Object.values(allRoleGroups.value)) {
|
||||
if (!Array.isArray(roles)) continue;
|
||||
const found = roles.find((r: any) => r.roleCode === code);
|
||||
if (found) return found;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const canClose = () => {
|
||||
if (!radio.value) {
|
||||
useMessage().warning('请选择一个角色')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (!radio.value) {
|
||||
useMessage().warning('请选择一个角色');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const handleBeforeClose = (done: () => void) => {
|
||||
if (requireSelectToClose.value) {
|
||||
useMessage().warning('请先选择登录角色')
|
||||
return
|
||||
}
|
||||
if (!canClose()) return
|
||||
done()
|
||||
}
|
||||
if (requireSelectToClose.value) {
|
||||
useMessage().warning('请先选择登录角色');
|
||||
return;
|
||||
}
|
||||
if (!canClose()) return;
|
||||
done();
|
||||
};
|
||||
|
||||
const handleFooterClose = () => {
|
||||
if (!canClose()) return
|
||||
visible.value = false
|
||||
}
|
||||
if (!canClose()) return;
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
const handleChangeRole = (label: string) => {
|
||||
const obj = findRoleByCode(label)
|
||||
if (!obj) return
|
||||
Local.set('roleCode', obj.roleCode)
|
||||
Local.set('roleName', obj.roleName)
|
||||
Local.set('roleId', obj.roleId)
|
||||
useMessage().success('操作成功')
|
||||
// 清掉 tags 缓存,重载后只保留首页 tag
|
||||
Session.remove('tagsViewList')
|
||||
// 清除 pinia 持久化的 tagsView 路由,避免重载后先恢复旧角色菜单再被新路由覆盖前就初始化出“不存在的 tag”
|
||||
try {
|
||||
window.localStorage.removeItem('tagsViewRoutes')
|
||||
} catch (_) {}
|
||||
setTimeout(() => {
|
||||
window.location.hash = '#/home'
|
||||
window.location.reload()
|
||||
}, 500)
|
||||
}
|
||||
const obj = findRoleByCode(label);
|
||||
if (!obj) return;
|
||||
Local.set('roleCode', obj.roleCode);
|
||||
Local.set('roleName', obj.roleName);
|
||||
Local.set('roleId', obj.roleId);
|
||||
useMessage().success('操作成功');
|
||||
// 清掉 tags 缓存,重载后只保留首页 tag
|
||||
Session.remove('tagsViewList');
|
||||
// 清除 pinia 持久化的 tagsView 路由,避免重载后先恢复旧角色菜单再被新路由覆盖前就初始化出“不存在的 tag”
|
||||
try {
|
||||
window.localStorage.removeItem('tagsViewRoutes');
|
||||
} catch (_) {}
|
||||
setTimeout(() => {
|
||||
window.location.hash = '#/home';
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
open
|
||||
})
|
||||
open,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.role-form-item {
|
||||
:deep(.el-form-item__content) {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
:deep(.el-form-item__content) {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
.role-radio-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
width: 100%;
|
||||
|
||||
:deep(.el-radio-button) {
|
||||
margin: 0;
|
||||
}
|
||||
:deep(.el-radio-button__inner) {
|
||||
border-radius: 6px !important;
|
||||
border: 1px solid var(--el-border-color) !important;
|
||||
margin-left: 0 !important;
|
||||
line-height: 1.3;
|
||||
}
|
||||
:deep(.el-radio-button.is-active .el-radio-button__inner) {
|
||||
border-color: var(--el-color-primary) !important;
|
||||
}
|
||||
:deep(.el-radio-button) {
|
||||
margin: 0;
|
||||
}
|
||||
:deep(.el-radio-button__inner) {
|
||||
border-radius: 6px !important;
|
||||
border: 1px solid var(--el-border-color) !important;
|
||||
margin-left: 0 !important;
|
||||
line-height: 1.3;
|
||||
}
|
||||
:deep(.el-radio-button.is-active .el-radio-button__inner) {
|
||||
border-color: var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
.role-group-card {
|
||||
width: 100%;
|
||||
flex: 0 0 auto;
|
||||
width: 100%;
|
||||
flex: 0 0 auto;
|
||||
|
||||
:deep(.el-card__header) {
|
||||
padding: 6px 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
:deep(.el-card__body) {
|
||||
padding: 6px 12px 8px;
|
||||
}
|
||||
:deep(.el-card__header) {
|
||||
padding: 6px 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
:deep(.el-card__body) {
|
||||
padding: 6px 12px 8px;
|
||||
}
|
||||
}
|
||||
.role-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 4px 8px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 4px 8px;
|
||||
}
|
||||
.group-name {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user