feat: 全局获取userinfo、数据持久化、store处理

This commit is contained in:
renxiaodong
2025-06-23 22:03:57 -04:00
parent 55198613a8
commit 59dac3bb13
10 changed files with 104 additions and 75 deletions

View File

@ -6,8 +6,26 @@
</template>
<script setup lang="ts">
import { useUserStore } from '@/stores';
import zhCN from '@arco-design/web-vue/es/locale/lang/zh-cn';
const store = useUserStore();
const redTheme = {
token: {
colorPrimary: '#6d4cfe', // 主色
colorLink: '#f5222d', // 链接色
},
};
const init = () => {
const { isLogin, fetchUserInfo } = store;
if (isLogin) {
fetchUserInfo();
}
};
onMounted(() => {
init();
// 监听全局未处理错误
window.addEventListener('unhandledrejection', (event) => {
event.preventDefault();
@ -15,10 +33,4 @@ onMounted(() => {
console.error(`发现catch报错${event.reason}`);
});
});
const redTheme = {
token: {
colorPrimary: '#6d4cfe', // 主色
colorLink: '#f5222d', // 链接色
},
};
</script>

View File

@ -77,30 +77,33 @@ export default defineComponent({
if (appStore.device === 'desktop') appStore.updateSettings({ menuCollapse: val });
};
const renderSubMenu = () => {
function travel(_route: RouteRecordRaw[], nodes = []) {
if (Array.isArray(_route)) {
function travel(_route: RouteRecordRaw[] = [], nodes: any[] = []) {
if (!Array.isArray(_route)) return nodes;
_route.forEach((element) => {
// This is demo, modify nodes as needed
const icon = element?.meta?.icon ? () => h(element?.meta?.icon as object) : null;
const node =
element?.children && element?.children.length !== 0 ? (
// 跳过没有 name 的菜单项,防止 key 报错
if (!element?.name) return;
const icon = element?.meta?.icon ? () => h(element.meta.icon as object) : null;
if (element.children && element.children.length > 0) {
nodes.push(
<a-sub-menu
key={element?.name}
key={String(element.name)}
v-slots={{
icon,
title: () => element?.meta?.locale || '',
title: () => element.meta?.locale || '',
}}
>
{travel(element?.children)}
</a-sub-menu>
) : (
<a-menu-item key={element?.name} v-slots={{ icon }} onClick={() => goto(element)}>
{element?.meta?.locale || ''}
</a-menu-item>
{travel(element.children)}
</a-sub-menu>,
);
} else {
nodes.push(
<a-menu-item key={String(element.name)} v-slots={{ icon }} onClick={() => goto(element)}>
{element.meta?.locale || ''}
</a-menu-item>,
);
nodes.push(node as never);
});
}
});
return nodes;
}
return travel(menuTree.value ?? []);

View File

@ -32,24 +32,6 @@ const router = createRouter({
requiresAuth: true,
},
},
{
path: '/',
name: 'Home',
redirect: '/dataEngine/hotTranslation',
children: [...appRoutes, REDIRECT_MAIN, NOT_FOUND_ROUTE],
meta: {
requiresAuth: true,
},
},
// {
// path: '/dataEngine',
// name: 'dataEngine',
// redirect: '/dataEngine/hotTranslation',
// children: [...appRoutes, REDIRECT_MAIN, NOT_FOUND_ROUTE],
// meta: {
// requiresAuth: 1,
// },
// },
{
path: '/permission',
name: 'permission',
@ -66,6 +48,15 @@ const router = createRouter({
requiresAuth: false,
},
},
{
path: '/',
name: 'Home',
redirect: '/dataEngine/hotTranslation',
children: [...appRoutes, REDIRECT_MAIN, NOT_FOUND_ROUTE],
meta: {
requiresAuth: true,
},
},
],
scrollBehavior() {
return { top: 0 };

View File

@ -15,12 +15,26 @@ interface EnterpriseState {
export const useEnterpriseStore = defineStore('enterprise', {
state: (): EnterpriseState => ({
enterpriseInfo: null,
enterpriseInfo: (() => {
const stored = localStorage.getItem('enterpriseInfo');
if (stored) {
try {
return JSON.parse(stored) as EnterpriseInfo;
} catch {
return null;
}
}
return null;
})(),
}),
actions: {
setEnterpriseInfo(enterpriseInfo: EnterpriseInfo) {
console.log('setEnterpriseInfo', enterpriseInfo);
this.enterpriseInfo = enterpriseInfo;
localStorage.setItem('enterpriseInfo', JSON.stringify(enterpriseInfo));
},
clearEnterpriseInfo() {
this.enterpriseInfo = null;
localStorage.removeItem('enterpriseInfo');
},
setEnterpriseName(name: string) {
if (this.enterpriseInfo) {

View File

@ -1,4 +1,5 @@
import { defineStore } from 'pinia';
import { fetchProfileInfo } from '@/api/all/login';
interface UserInfo {
id: number;
@ -19,7 +20,7 @@ interface UserState {
token: string;
userInfo: UserInfo | null;
companyInfo: CompanyInfo | null;
isLogin: boolean;
// isLogin: boolean;
}
interface UserInfo {
@ -33,7 +34,6 @@ export const useUserStore = defineStore('user', {
token: localStorage.getItem('accessToken') || '',
userInfo: null,
companyInfo: null,
isLogin: false,
}),
getters: {
isLogin(): boolean {
@ -46,6 +46,7 @@ export const useUserStore = defineStore('user', {
this.token = `Bearer ${token}`;
localStorage.setItem('accessToken', this.token);
},
deleteToken() {
this.token = '';
localStorage.removeItem('accessToken');
@ -62,18 +63,11 @@ export const useUserStore = defineStore('user', {
},
// 获取用户信息
getUserInfo(): UserInfo | null {
return this.userInfo;
},
// 设置公司信息
setCompanyInfo(companyInfo: CompanyInfo | null) {
this.companyInfo = companyInfo;
},
// 获取公司信息
getCompanyInfo(): CompanyInfo | null {
return this.companyInfo;
async fetchUserInfo() {
const { code, data } = await fetchProfileInfo();
if (code === 200) {
this.setUserInfo(data);
}
},
},
});

View File

@ -5,6 +5,7 @@
import router from '@/router';
import { useUserStore } from '@/stores';
import { useEnterpriseStore } from '@/stores/modules/enterprise';
// 登录
export function goUserLogin(query?: any) {
@ -23,7 +24,10 @@ export function handleUserHome() {
export function handleUserLogout() {
const userStore = useUserStore();
const store = useEnterpriseStore();
userStore.deleteToken();
store.clearEnterpriseInfo();
goUserLogin();
}

View File

@ -275,9 +275,9 @@ const getProfileInfo = async () => {
let enterprises = data['enterprises'];
mobileNumber.value = data['mobile'];
accounts.value = enterprises;
enterpriseStore.setEnterpriseInfo(data);
userStore.setUserInfo(data);
if (enterprises.length > 0) {
if (enterprises.length === 1) {
await enterpriseStore.updateEnterpriseInfo();

View File

@ -105,6 +105,8 @@ const okText = computed(() => {
});
const customerServiceVisible = ref(false);
const canAddAccount = computed(() => {
if (!enterpriseInfo) return false;
return enterpriseInfo.sub_account_quota > enterpriseInfo.used_sub_account_count;
});
@ -124,10 +126,12 @@ function handlePageSizeChange(pageSize: number) {
async function getSubAccount() {
const res = await fetchSubAccountPage(params);
const { data, total } = res.data;
const { data, total, code } = res.data;
if (code === 200) {
pagination.total = total;
data.value = data;
}
}
async function handleAddAccount() {
if (canAddAccount.value) {
const res = await getEnterpriseInviteCode();

View File

@ -1,6 +1,6 @@
<template>
<Container title="企业信息" class="container mt-24px">
<a-table :columns="columns" :data="data" :pagination="false" class="mt-16px">
<a-table :columns="columns" :data="dataSource" :pagination="false" class="mt-16px">
<template #info="{ record }">
{{ record.name }}
</template>
@ -11,7 +11,7 @@
<Modal v-model:visible="infoVisible" width="480px" title="修改企业名称" :okText="okText" @ok="handleOk">
<p class="tips">
企业名称只能修改2次请谨慎操作<span
>剩余{{ enterpriseInfo.update_name_quota - enterpriseInfo.used_update_name_count }}
>剩余{{ enterpriseInfo!.update_name_quota - enterpriseInfo!.used_update_name_count }}
</span>
</p>
<a-form
@ -54,12 +54,15 @@ const columns = [
slotName: 'action',
},
];
const data = ref([enterpriseInfo]);
const infoVisible = ref(false);
const customerServiceVisible = ref(false);
const dataSource = computed(() => {
return enterpriseInfo ? [enterpriseInfo] : [];
});
const canUpdate = computed(() => {
if (!enterpriseInfo) return false;
return enterpriseInfo.update_name_quota > enterpriseInfo.used_update_name_count;
});
@ -72,7 +75,7 @@ const okText = computed(() => {
function handleUpdate() {
if (!canUpdate.value) {
form.name = enterpriseInfo.name;
form.name = enterpriseInfo!.name;
}
infoVisible.value = true;
}

View File

@ -1,6 +1,6 @@
<template>
<Container title="个人信息" class="container mt-24px">
<a-table :columns="columns" :data="data" :pagination="false" class="mt-16px">
<a-table :columns="columns" :data="dataSource" :pagination="false" class="mt-16px">
<template #info="{ record }">
<div class="pt-3px pb-3px">
<a-avatar :image-url="record.head_image" :size="32" />
@ -85,7 +85,7 @@ import axios from 'axios';
import { useUserStore } from '@/stores';
const store = useUserStore();
const userInfo = store.getUserInfo();
const userInfo = store.userInfo;
const columns = [
{
@ -97,7 +97,7 @@ const columns = [
slotName: 'mobile',
},
];
const data = reactive([userInfo]);
const infoVisible = ref(false);
const imageVisible = ref(false);
const mobileVisible = ref(false);
@ -108,6 +108,10 @@ const formRef = ref();
const isSendCaptcha = ref(false);
const uploadInputRef = ref();
const dataSource = computed(() => {
return userInfo ? [userInfo] : [];
});
// 表单校验规则
const formRules = {
mobile: [