update RolePermissionAssign style
This commit is contained in:
@@ -50,6 +50,7 @@ import type { DropdownOption, DropdownValue } from "tdesign-mobile-vue";
|
|||||||
import { Toast } from "tdesign-mobile-vue";
|
import { Toast } from "tdesign-mobile-vue";
|
||||||
import { type Permission, useUserStore } from "timi-web";
|
import { type Permission, useUserStore } from "timi-web";
|
||||||
import { type Role, usePermissionSettingsStore } from "@/store/permissionSettingsStore";
|
import { type Role, usePermissionSettingsStore } from "@/store/permissionSettingsStore";
|
||||||
|
import { getErrorMessage } from "@/utils/error";
|
||||||
import { corePermissionCodes, coreRoleCodes } from "@/utils/permission";
|
import { corePermissionCodes, coreRoleCodes } from "@/utils/permission";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@@ -188,16 +189,6 @@ async function loadAuthorizationScope(): Promise<void> {
|
|||||||
candidateRoleList.value = roleList;
|
candidateRoleList.value = roleList;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getErrorMessage(error: unknown, fallback: string): string {
|
|
||||||
if (error instanceof Error && error.message) {
|
|
||||||
return error.message;
|
|
||||||
}
|
|
||||||
if (typeof error === "string" && error) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await permissionStore.loadAll();
|
await permissionStore.loadAll();
|
||||||
await loadAuthorizationScope();
|
await loadAuthorizationScope();
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ import {
|
|||||||
type RoleDraft,
|
type RoleDraft,
|
||||||
usePermissionSettingsStore
|
usePermissionSettingsStore
|
||||||
} from "@/store/permissionSettingsStore";
|
} from "@/store/permissionSettingsStore";
|
||||||
|
import { getErrorMessage } from "@/utils/error";
|
||||||
import { corePermissionCodes, coreRoleCodes } from "@/utils/permission";
|
import { corePermissionCodes, coreRoleCodes } from "@/utils/permission";
|
||||||
import PermissionCell from "@/pages/permission/component/PermissionCell.vue";
|
import PermissionCell from "@/pages/permission/component/PermissionCell.vue";
|
||||||
import PermissionLegend from "@/pages/permission/component/PermissionLegend.vue";
|
import PermissionLegend from "@/pages/permission/component/PermissionLegend.vue";
|
||||||
@@ -453,16 +454,6 @@ async function getCurrentStoreId(): Promise<string> {
|
|||||||
return storeId;
|
return storeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getErrorMessage(error: unknown, fallback: string): string {
|
|
||||||
if (error instanceof Error && error.message) {
|
|
||||||
return error.message;
|
|
||||||
}
|
|
||||||
if (typeof error === "string" && error) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(fillForm);
|
onMounted(fillForm);
|
||||||
|
|
||||||
function updateNavBar(): void {
|
function updateNavBar(): void {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import { useUserStore } from "timi-web";
|
|||||||
import type { Role } from "@/store/permissionSettingsStore";
|
import type { Role } from "@/store/permissionSettingsStore";
|
||||||
import { useNavBarStore } from "@/store/navBarStore";
|
import { useNavBarStore } from "@/store/navBarStore";
|
||||||
import { usePermissionSettingsStore } from "@/store/permissionSettingsStore";
|
import { usePermissionSettingsStore } from "@/store/permissionSettingsStore";
|
||||||
|
import { getErrorMessage } from "@/utils/error";
|
||||||
import { corePermissionCodes, coreRoleCodes } from "@/utils/permission";
|
import { corePermissionCodes, coreRoleCodes } from "@/utils/permission";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@@ -161,15 +162,6 @@ async function refreshAuthorizationScope(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getErrorMessage(error: unknown, fallback: string): string {
|
|
||||||
if (error instanceof Error && error.message) {
|
|
||||||
return error.message;
|
|
||||||
}
|
|
||||||
if (typeof error === "string" && error) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
@@ -198,4 +190,3 @@ function getErrorMessage(error: unknown, fallback: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -13,21 +13,23 @@
|
|||||||
@change="handleRoleChange"
|
@change="handleRoleChange"
|
||||||
/>
|
/>
|
||||||
</t-dropdown-menu>
|
</t-dropdown-menu>
|
||||||
|
<div class="show-child-permission">
|
||||||
|
<span>显示继承权限</span>
|
||||||
|
<t-switch v-model="showChildRolePermissions" />
|
||||||
</div>
|
</div>
|
||||||
<div class="inherit">
|
|
||||||
<span class="label">显示继承权限</span>
|
|
||||||
<t-switch class="switch" v-model="showChildRolePermissions" />
|
|
||||||
</div>
|
</div>
|
||||||
<t-cell-group v-if="activeRole && grantablePermissionList.length" title="可配置的直接权限 P" theme="card">
|
<t-cell-group
|
||||||
|
v-if="activeRole && grantablePermissionList.length"
|
||||||
|
class="list"
|
||||||
|
theme="card"
|
||||||
|
>
|
||||||
<t-cell
|
<t-cell
|
||||||
|
:class="{ inherited: isPermissionInherited(item.id) }"
|
||||||
v-for="item in grantablePermissionList"
|
v-for="item in grantablePermissionList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:title="item.name || item.code"
|
:title="item.name"
|
||||||
:class="{ inherited: isPermissionInherited(item.id) }"
|
:description="item.code"
|
||||||
>
|
>
|
||||||
<template #description>
|
|
||||||
<span class="code" v-text="item.code"></span>
|
|
||||||
</template>
|
|
||||||
<template #right-icon>
|
<template #right-icon>
|
||||||
<t-switch
|
<t-switch
|
||||||
:disabled="!canUpdateRolePermission || !canEditActiveRole || isPermissionInherited(item.id)"
|
:disabled="!canUpdateRolePermission || !canEditActiveRole || isPermissionInherited(item.id)"
|
||||||
@@ -38,15 +40,6 @@
|
|||||||
</t-cell>
|
</t-cell>
|
||||||
</t-cell-group>
|
</t-cell-group>
|
||||||
<t-empty v-else-if="!permissionStore.loading" description="暂无可配置的直接权限 P" />
|
<t-empty v-else-if="!permissionStore.loading" description="暂无可配置的直接权限 P" />
|
||||||
<t-button
|
|
||||||
v-if="canEditActiveRole"
|
|
||||||
v-can="rolePermissionWriteAccess"
|
|
||||||
class="save"
|
|
||||||
theme="primary"
|
|
||||||
@click="savePermissionList"
|
|
||||||
>
|
|
||||||
保存 P
|
|
||||||
</t-button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -54,7 +47,9 @@
|
|||||||
import type { DropdownOption, DropdownValue } from "tdesign-mobile-vue";
|
import type { DropdownOption, DropdownValue } from "tdesign-mobile-vue";
|
||||||
import { Toast } from "tdesign-mobile-vue";
|
import { Toast } from "tdesign-mobile-vue";
|
||||||
import { type Permission, useUserStore } from "timi-web";
|
import { type Permission, useUserStore } from "timi-web";
|
||||||
|
import { useNavBarStore } from "@/store/navBarStore";
|
||||||
import { type Role, usePermissionSettingsStore } from "@/store/permissionSettingsStore";
|
import { type Role, usePermissionSettingsStore } from "@/store/permissionSettingsStore";
|
||||||
|
import { getErrorMessage } from "@/utils/error";
|
||||||
import { corePermissionCodes, coreRoleCodes } from "@/utils/permission";
|
import { corePermissionCodes, coreRoleCodes } from "@/utils/permission";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@@ -62,16 +57,13 @@ defineOptions({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const permissionStore = usePermissionSettingsStore();
|
const permissionStore = usePermissionSettingsStore();
|
||||||
|
const navBarStore = useNavBarStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
// ---------- 角色选择 ----------
|
// ---------- 角色选择 ----------
|
||||||
|
|
||||||
const activeRoleId = ref(String(route.query.roleId || route.params.id || ""));
|
const activeRoleId = ref(String(route.query.roleId || route.params.id || ""));
|
||||||
const checkedPermissionIds = ref<string[]>([]);
|
|
||||||
const unmanagedPermissionIds = ref<string[]>([]);
|
|
||||||
const inheritedPermissionIds = ref<string[]>([]);
|
|
||||||
const grantablePermissionList = ref<Permission[]>([]);
|
|
||||||
const candidateRoleList = ref<Role[]>([]);
|
const candidateRoleList = ref<Role[]>([]);
|
||||||
const showChildRolePermissions = ref(false);
|
const showChildRolePermissions = ref(false);
|
||||||
let permissionSyncSeq = 0;
|
let permissionSyncSeq = 0;
|
||||||
@@ -94,16 +86,12 @@ const roleOptions = computed<DropdownOption[]>(() => candidateRoleList.value
|
|||||||
disabled: false
|
disabled: false
|
||||||
})));
|
})));
|
||||||
|
|
||||||
const rolePermissionWriteAccess = {
|
|
||||||
value: [
|
|
||||||
corePermissionCodes.rolePermission.create,
|
|
||||||
corePermissionCodes.rolePermission.delete
|
|
||||||
],
|
|
||||||
mode: "and"
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
// ---------- 权限状态 ----------
|
// ---------- 权限状态 ----------
|
||||||
|
|
||||||
|
const checkedPermissionIds = ref<string[]>([]);
|
||||||
|
const unmanagedPermissionIds = ref<string[]>([]);
|
||||||
|
const inheritedPermissionIds = ref<string[]>([]);
|
||||||
|
const grantablePermissionList = ref<Permission[]>([]);
|
||||||
const checkedPermissionIdSet = computed(() => new Set(checkedPermissionIds.value));
|
const checkedPermissionIdSet = computed(() => new Set(checkedPermissionIds.value));
|
||||||
const inheritedPermissionIdSet = computed(() => new Set(inheritedPermissionIds.value));
|
const inheritedPermissionIdSet = computed(() => new Set(inheritedPermissionIds.value));
|
||||||
|
|
||||||
@@ -152,7 +140,7 @@ async function savePermissionList(): Promise<void> {
|
|||||||
...checkedPermissionIds.value,
|
...checkedPermissionIds.value,
|
||||||
...unmanagedPermissionIds.value
|
...unmanagedPermissionIds.value
|
||||||
])));
|
])));
|
||||||
Toast.success("P 已保存");
|
Toast.success("已保存");
|
||||||
await loadActiveRolePermissions();
|
await loadActiveRolePermissions();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
clearPermissionState();
|
clearPermissionState();
|
||||||
@@ -160,11 +148,25 @@ async function savePermissionList(): Promise<void> {
|
|||||||
await loadAuthorizationScope();
|
await loadAuthorizationScope();
|
||||||
await loadActiveRolePermissions();
|
await loadActiveRolePermissions();
|
||||||
} finally {
|
} finally {
|
||||||
Toast.error(getErrorMessage(error, "P 保存失败"));
|
Toast.error(getErrorMessage(error, "保存失败"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateNavBar(): void {
|
||||||
|
navBarStore.clearRight();
|
||||||
|
if (canEditActiveRole.value && canUpdateRolePermission.value) {
|
||||||
|
navBarStore.setRightText("保存", "var(--td-brand-color)", savePermissionList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch([canEditActiveRole, canUpdateRolePermission], updateNavBar, { immediate: true });
|
||||||
|
|
||||||
|
onMounted(updateNavBar);
|
||||||
|
onUnmounted(() => {
|
||||||
|
navBarStore.clearRight();
|
||||||
|
});
|
||||||
|
|
||||||
// ---------- 权限勾选 ----------
|
// ---------- 权限勾选 ----------
|
||||||
|
|
||||||
function isPermissionChecked(permissionId: string): boolean {
|
function isPermissionChecked(permissionId: string): boolean {
|
||||||
@@ -204,18 +206,7 @@ function clearPermissionState(): void {
|
|||||||
// ---------- 授权范围 ----------
|
// ---------- 授权范围 ----------
|
||||||
|
|
||||||
async function loadAuthorizationScope(): Promise<void> {
|
async function loadAuthorizationScope(): Promise<void> {
|
||||||
const roleList = isSystemAdmin.value ? permissionStore.roleList : await permissionStore.loadManageableRoles();
|
candidateRoleList.value = isSystemAdmin.value ? permissionStore.roleList : await permissionStore.loadManageableRoles();
|
||||||
candidateRoleList.value = roleList;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getErrorMessage(error: unknown, fallback: string): string {
|
|
||||||
if (error instanceof Error && error.message) {
|
|
||||||
return error.message;
|
|
||||||
}
|
|
||||||
if (typeof error === "string" && error) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
@@ -232,7 +223,7 @@ onMounted(async () => {
|
|||||||
.role-permission-assign {
|
.role-permission-assign {
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: calc(var(--app-nav-height) + 4.5rem) 0 6rem 0;
|
padding: calc(var(--app-nav-height) + 4rem) 0 1rem 0;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
@@ -241,81 +232,42 @@ onMounted(async () => {
|
|||||||
right: 0;
|
right: 0;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
padding: 0 1rem;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: var(--td-shadow-1);
|
box-shadow: var(--td-shadow-1);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: space-between;
|
||||||
|
|
||||||
.role-selector::after {
|
.role-selector::after {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.inherit {
|
.show-child-permission {
|
||||||
gap: .75rem;
|
|
||||||
display: flex;
|
|
||||||
margin: 0 1rem;
|
|
||||||
padding: .75rem 1rem;
|
|
||||||
background: #fff;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: .75rem;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.label {
|
|
||||||
color: #334155;
|
|
||||||
font-size: .875rem;
|
|
||||||
line-height: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch {
|
|
||||||
--td-switch-checked-color: #14b8a6;
|
--td-switch-checked-color: #14b8a6;
|
||||||
|
|
||||||
|
gap: .5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.t-cell__title) {
|
.list {
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.t-cell__title-text) {
|
:deep(.t-cell) {
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.t-cell__description) {
|
&.inherited {
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.t-cell__right) {
|
.t-cell__title-text {
|
||||||
flex: 0 0 auto;
|
|
||||||
margin-left: .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code {
|
|
||||||
width: 100%;
|
|
||||||
display: block;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inherited {
|
|
||||||
:deep(.t-cell__title) {
|
|
||||||
color: #0f766e;
|
color: #0f766e;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.t-switch--checked.t-switch--disabled) {
|
.t-switch--checked.t-switch--disabled {
|
||||||
background: #14b8a6;
|
background: #14b8a6;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.save {
|
|
||||||
left: 1rem;
|
|
||||||
right: 1rem;
|
|
||||||
bottom: calc(.75rem + env(safe-area-inset-bottom, 0));
|
|
||||||
position: fixed;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ import ManagedUserAPI from "@/api/ManagedUserAPI";
|
|||||||
import { useCurrentStoreStore } from "@/store/currentStoreStore";
|
import { useCurrentStoreStore } from "@/store/currentStoreStore";
|
||||||
import type { Role } from "@/store/permissionSettingsStore";
|
import type { Role } from "@/store/permissionSettingsStore";
|
||||||
import type { ManagedUser } from "@/types/ManagedUser";
|
import type { ManagedUser } from "@/types/ManagedUser";
|
||||||
|
import { getErrorMessage } from "@/utils/error";
|
||||||
import { corePermissionCodes, gaoRoleCodes } from "@/utils/permission";
|
import { corePermissionCodes, gaoRoleCodes } from "@/utils/permission";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@@ -270,16 +271,6 @@ function getRoleId(role: UserRole | string): string {
|
|||||||
return fullRole?.id || "";
|
return fullRole?.id || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getErrorMessage(error: unknown, fallback: string): string {
|
|
||||||
if (error instanceof Error && error.message) {
|
|
||||||
return error.message;
|
|
||||||
}
|
|
||||||
if (typeof error === "string" && error) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setRoleChecked(roleId: string, value: boolean): void {
|
function setRoleChecked(roleId: string, value: boolean): void {
|
||||||
if (value && !checkedRoleIds.value.includes(roleId)) {
|
if (value && !checkedRoleIds.value.includes(roleId)) {
|
||||||
checkedRoleIds.value.push(roleId);
|
checkedRoleIds.value.push(roleId);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ const permissionRoutes: RouteRecordRaw[] = [
|
|||||||
depth: 6,
|
depth: 6,
|
||||||
navBarVisible: true,
|
navBarVisible: true,
|
||||||
navBarCanBack: true,
|
navBarCanBack: true,
|
||||||
navBarTitle: "角色直接权限 P",
|
navBarTitle: "角色直接授权权限 P",
|
||||||
tabBarVisible: false,
|
tabBarVisible: false,
|
||||||
bodyBackground: "#F5F5F8",
|
bodyBackground: "#F5F5F8",
|
||||||
darkBodyBackground: "#10161f"
|
darkBodyBackground: "#10161f"
|
||||||
@@ -147,7 +147,7 @@ const permissionRoutes: RouteRecordRaw[] = [
|
|||||||
depth: 4,
|
depth: 4,
|
||||||
navBarVisible: true,
|
navBarVisible: true,
|
||||||
navBarCanBack: true,
|
navBarCanBack: true,
|
||||||
navBarTitle: "角色直接权限 P",
|
navBarTitle: "角色直接授权权限 P",
|
||||||
tabBarVisible: false,
|
tabBarVisible: false,
|
||||||
bodyBackground: "#F5F5F8",
|
bodyBackground: "#F5F5F8",
|
||||||
darkBodyBackground: "#10161f"
|
darkBodyBackground: "#10161f"
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* 从未知错误值中提取可展示的错误文案。
|
||||||
|
*
|
||||||
|
* @param error 未知错误值
|
||||||
|
* @param fallback 无法提取错误文案时的备用文案
|
||||||
|
*/
|
||||||
|
export function getErrorMessage(error: unknown, fallback: string): string {
|
||||||
|
if (error instanceof Error && error.message) {
|
||||||
|
return error.message;
|
||||||
|
}
|
||||||
|
if (typeof error === "string" && error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user