Files
kaidi/frontend/src/pages/role-select/index.vue
T
2026-08-17 23:03:03 +08:00

182 lines
4.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<main class="role-page">
<section class="role-panel">
<div class="brand-mark">财务系统</div>
<p class="eyebrow">当前账号已登录</p>
<h1>选择工作身份</h1>
<p class="description">请选择本次要使用的身份,系统会按身份重新加载菜单和数据范围。</p>
<t-alert v-if="identityConfigurationError" theme="error" :close-btn="false">
{{ identityConfigurationError }}
</t-alert>
<t-alert v-else-if="userStore.roles.length === 0" theme="warning" :close-btn="false">
当前账号没有可用工作身份。
</t-alert>
<div v-else class="role-grid">
<t-card v-for="role in availableRoles" :key="role.code" class="role-card" :bordered="true" hover-shadow>
<t-icon :name="roleIcon(role.code)" size="28px" />
<span class="role-name">{{ role.name }}</span>
<span class="role-description">{{ role.description }}</span>
<t-button
class="role-action"
theme="primary"
variant="text"
:loading="loading"
:disabled="Boolean(identityConfigurationError)"
@click="choose(role.code)"
>
进入工作台
<template #icon><t-icon name="arrow-right" /></template>
</t-button>
</t-card>
</div>
<t-button variant="text" theme="default" @click="signOut">
<template #icon><t-icon name="poweroff" /></template>
退出登录
</t-button>
</section>
</main>
</template>
<script setup lang="ts">
import { MessagePlugin } from 'tdesign-vue-next';
import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
import type { RoleView } from '@/api/auth';
import { usePermissionStore, useUserStore } from '@/store';
defineOptions({ name: 'RoleSelectPage' });
const router = useRouter();
const userStore = useUserStore();
const permissionStore = usePermissionStore();
const loading = ref(false);
const availableRoles = computed(() => userStore.roles as RoleView[]);
const identityConfigurationError = computed(() => {
const hasSystemAdmin = userStore.roles.some((role) => role.code === 'SYSTEM_ADMIN');
const hasBusinessRole = userStore.roles.some((role) =>
['PROJECT_MANAGER', 'FINANCE_MANAGER', 'ARCHIVE_MANAGER'].includes(role.code),
);
return hasSystemAdmin && hasBusinessRole ? '账号身份配置冲突,请联系系统管理员处理。' : '';
});
const roleIcon = (code: string) =>
({
PROJECT_MANAGER: 'folder-open',
FINANCE_MANAGER: 'chart-bubble',
ARCHIVE_MANAGER: 'file-attachment',
SYSTEM_ADMIN: 'setting',
})[code] || 'user-circle';
const choose = async (roleCode: string) => {
if (identityConfigurationError.value) return;
loading.value = true;
try {
await userStore.selectRole(roleCode);
permissionStore.initRoutes();
await router.replace(userStore.workbenchRoute);
} catch (error) {
MessagePlugin.error((error as Error).message || '身份选择失败,请重试');
} finally {
loading.value = false;
}
};
const signOut = async () => {
await userStore.logout();
await router.replace('/login');
};
</script>
<style scoped>
.role-page {
min-height: 100vh;
display: grid;
place-items: center;
padding: 32px;
background: var(--td-bg-color-page);
}
.role-panel {
width: min(720px, 100%);
padding: 40px;
background: var(--td-bg-color-container);
border: 1px solid var(--td-component-border);
border-radius: var(--td-radius-large);
box-shadow: var(--td-shadow-1);
}
.brand-mark {
color: var(--td-brand-color);
font-size: 18px;
font-weight: 600;
}
.eyebrow {
margin: 32px 0 4px;
color: var(--td-text-color-secondary);
font-size: 13px;
}
h1 {
margin: 0;
font-size: 30px;
line-height: 40px;
}
.description {
margin: 8px 0 24px;
color: var(--td-text-color-secondary);
}
.role-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
margin: 24px 0;
}
.role-card {
min-height: 190px;
color: var(--td-text-color-primary);
text-align: left;
}
.role-card :deep(.t-card__body) {
display: flex;
min-height: 150px;
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.role-name {
font-size: 17px;
font-weight: 600;
}
.role-description {
min-height: 42px;
color: var(--td-text-color-secondary);
font-size: 13px;
line-height: 21px;
}
.role-action {
margin-top: auto;
padding: 0;
}
@media (width <= 720px) {
.role-page {
padding: 16px;
}
.role-panel {
padding: 24px;
}
.role-grid {
grid-template-columns: 1fr;
}
}
</style>