feat: 全局获取userinfo、数据持久化、store处理
This commit is contained in:
24
src/App.vue
24
src/App.vue
@ -6,8 +6,26 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useUserStore } from '@/stores';
|
||||||
import zhCN from '@arco-design/web-vue/es/locale/lang/zh-cn';
|
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(() => {
|
onMounted(() => {
|
||||||
|
init();
|
||||||
// 监听全局未处理错误
|
// 监听全局未处理错误
|
||||||
window.addEventListener('unhandledrejection', (event) => {
|
window.addEventListener('unhandledrejection', (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -15,10 +33,4 @@ onMounted(() => {
|
|||||||
console.error(`发现catch报错:${event.reason}`);
|
console.error(`发现catch报错:${event.reason}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const redTheme = {
|
|
||||||
token: {
|
|
||||||
colorPrimary: '#6d4cfe', // 主色
|
|
||||||
colorLink: '#f5222d', // 链接色
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -77,30 +77,33 @@ export default defineComponent({
|
|||||||
if (appStore.device === 'desktop') appStore.updateSettings({ menuCollapse: val });
|
if (appStore.device === 'desktop') appStore.updateSettings({ menuCollapse: val });
|
||||||
};
|
};
|
||||||
const renderSubMenu = () => {
|
const renderSubMenu = () => {
|
||||||
function travel(_route: RouteRecordRaw[], nodes = []) {
|
function travel(_route: RouteRecordRaw[] = [], nodes: any[] = []) {
|
||||||
if (Array.isArray(_route)) {
|
if (!Array.isArray(_route)) return nodes;
|
||||||
_route.forEach((element) => {
|
_route.forEach((element) => {
|
||||||
// This is demo, modify nodes as needed
|
// 跳过没有 name 的菜单项,防止 key 报错
|
||||||
const icon = element?.meta?.icon ? () => h(element?.meta?.icon as object) : null;
|
if (!element?.name) return;
|
||||||
const node =
|
|
||||||
element?.children && element?.children.length !== 0 ? (
|
const icon = element?.meta?.icon ? () => h(element.meta.icon as object) : null;
|
||||||
<a-sub-menu
|
if (element.children && element.children.length > 0) {
|
||||||
key={element?.name}
|
nodes.push(
|
||||||
v-slots={{
|
<a-sub-menu
|
||||||
icon,
|
key={String(element.name)}
|
||||||
title: () => element?.meta?.locale || '',
|
v-slots={{
|
||||||
}}
|
icon,
|
||||||
>
|
title: () => element.meta?.locale || '',
|
||||||
{travel(element?.children)}
|
}}
|
||||||
</a-sub-menu>
|
>
|
||||||
) : (
|
{travel(element.children)}
|
||||||
<a-menu-item key={element?.name} v-slots={{ icon }} onClick={() => goto(element)}>
|
</a-sub-menu>,
|
||||||
{element?.meta?.locale || ''}
|
);
|
||||||
</a-menu-item>
|
} else {
|
||||||
);
|
nodes.push(
|
||||||
nodes.push(node as never);
|
<a-menu-item key={String(element.name)} v-slots={{ icon }} onClick={() => goto(element)}>
|
||||||
});
|
{element.meta?.locale || ''}
|
||||||
}
|
</a-menu-item>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
return travel(menuTree.value ?? []);
|
return travel(menuTree.value ?? []);
|
||||||
|
|||||||
@ -32,24 +32,6 @@ const router = createRouter({
|
|||||||
requiresAuth: true,
|
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',
|
path: '/permission',
|
||||||
name: 'permission',
|
name: 'permission',
|
||||||
@ -66,6 +48,15 @@ const router = createRouter({
|
|||||||
requiresAuth: false,
|
requiresAuth: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
name: 'Home',
|
||||||
|
redirect: '/dataEngine/hotTranslation',
|
||||||
|
children: [...appRoutes, REDIRECT_MAIN, NOT_FOUND_ROUTE],
|
||||||
|
meta: {
|
||||||
|
requiresAuth: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
scrollBehavior() {
|
scrollBehavior() {
|
||||||
return { top: 0 };
|
return { top: 0 };
|
||||||
|
|||||||
@ -15,12 +15,26 @@ interface EnterpriseState {
|
|||||||
|
|
||||||
export const useEnterpriseStore = defineStore('enterprise', {
|
export const useEnterpriseStore = defineStore('enterprise', {
|
||||||
state: (): EnterpriseState => ({
|
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: {
|
actions: {
|
||||||
setEnterpriseInfo(enterpriseInfo: EnterpriseInfo) {
|
setEnterpriseInfo(enterpriseInfo: EnterpriseInfo) {
|
||||||
console.log('setEnterpriseInfo', enterpriseInfo);
|
|
||||||
this.enterpriseInfo = enterpriseInfo;
|
this.enterpriseInfo = enterpriseInfo;
|
||||||
|
localStorage.setItem('enterpriseInfo', JSON.stringify(enterpriseInfo));
|
||||||
|
},
|
||||||
|
clearEnterpriseInfo() {
|
||||||
|
this.enterpriseInfo = null;
|
||||||
|
localStorage.removeItem('enterpriseInfo');
|
||||||
},
|
},
|
||||||
setEnterpriseName(name: string) {
|
setEnterpriseName(name: string) {
|
||||||
if (this.enterpriseInfo) {
|
if (this.enterpriseInfo) {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
import { fetchProfileInfo } from '@/api/all/login';
|
||||||
|
|
||||||
interface UserInfo {
|
interface UserInfo {
|
||||||
id: number;
|
id: number;
|
||||||
@ -19,7 +20,7 @@ interface UserState {
|
|||||||
token: string;
|
token: string;
|
||||||
userInfo: UserInfo | null;
|
userInfo: UserInfo | null;
|
||||||
companyInfo: CompanyInfo | null;
|
companyInfo: CompanyInfo | null;
|
||||||
isLogin: boolean;
|
// isLogin: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserInfo {
|
interface UserInfo {
|
||||||
@ -33,7 +34,6 @@ export const useUserStore = defineStore('user', {
|
|||||||
token: localStorage.getItem('accessToken') || '',
|
token: localStorage.getItem('accessToken') || '',
|
||||||
userInfo: null,
|
userInfo: null,
|
||||||
companyInfo: null,
|
companyInfo: null,
|
||||||
isLogin: false,
|
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
isLogin(): boolean {
|
isLogin(): boolean {
|
||||||
@ -46,6 +46,7 @@ export const useUserStore = defineStore('user', {
|
|||||||
this.token = `Bearer ${token}`;
|
this.token = `Bearer ${token}`;
|
||||||
localStorage.setItem('accessToken', this.token);
|
localStorage.setItem('accessToken', this.token);
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteToken() {
|
deleteToken() {
|
||||||
this.token = '';
|
this.token = '';
|
||||||
localStorage.removeItem('accessToken');
|
localStorage.removeItem('accessToken');
|
||||||
@ -62,18 +63,11 @@ export const useUserStore = defineStore('user', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
getUserInfo(): UserInfo | null {
|
async fetchUserInfo() {
|
||||||
return this.userInfo;
|
const { code, data } = await fetchProfileInfo();
|
||||||
},
|
if (code === 200) {
|
||||||
|
this.setUserInfo(data);
|
||||||
// 设置公司信息
|
}
|
||||||
setCompanyInfo(companyInfo: CompanyInfo | null) {
|
|
||||||
this.companyInfo = companyInfo;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取公司信息
|
|
||||||
getCompanyInfo(): CompanyInfo | null {
|
|
||||||
return this.companyInfo;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
|
|
||||||
import { useUserStore } from '@/stores';
|
import { useUserStore } from '@/stores';
|
||||||
|
import { useEnterpriseStore } from '@/stores/modules/enterprise';
|
||||||
|
|
||||||
// 登录
|
// 登录
|
||||||
export function goUserLogin(query?: any) {
|
export function goUserLogin(query?: any) {
|
||||||
@ -23,7 +24,10 @@ export function handleUserHome() {
|
|||||||
|
|
||||||
export function handleUserLogout() {
|
export function handleUserLogout() {
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
const store = useEnterpriseStore();
|
||||||
|
|
||||||
userStore.deleteToken();
|
userStore.deleteToken();
|
||||||
|
store.clearEnterpriseInfo();
|
||||||
|
|
||||||
goUserLogin();
|
goUserLogin();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -275,9 +275,9 @@ const getProfileInfo = async () => {
|
|||||||
let enterprises = data['enterprises'];
|
let enterprises = data['enterprises'];
|
||||||
mobileNumber.value = data['mobile'];
|
mobileNumber.value = data['mobile'];
|
||||||
accounts.value = enterprises;
|
accounts.value = enterprises;
|
||||||
|
|
||||||
enterpriseStore.setEnterpriseInfo(data);
|
enterpriseStore.setEnterpriseInfo(data);
|
||||||
userStore.setUserInfo(data);
|
userStore.setUserInfo(data);
|
||||||
|
|
||||||
if (enterprises.length > 0) {
|
if (enterprises.length > 0) {
|
||||||
if (enterprises.length === 1) {
|
if (enterprises.length === 1) {
|
||||||
await enterpriseStore.updateEnterpriseInfo();
|
await enterpriseStore.updateEnterpriseInfo();
|
||||||
|
|||||||
@ -105,6 +105,8 @@ const okText = computed(() => {
|
|||||||
});
|
});
|
||||||
const customerServiceVisible = ref(false);
|
const customerServiceVisible = ref(false);
|
||||||
const canAddAccount = computed(() => {
|
const canAddAccount = computed(() => {
|
||||||
|
if (!enterpriseInfo) return false;
|
||||||
|
|
||||||
return enterpriseInfo.sub_account_quota > enterpriseInfo.used_sub_account_count;
|
return enterpriseInfo.sub_account_quota > enterpriseInfo.used_sub_account_count;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -124,9 +126,11 @@ function handlePageSizeChange(pageSize: number) {
|
|||||||
|
|
||||||
async function getSubAccount() {
|
async function getSubAccount() {
|
||||||
const res = await fetchSubAccountPage(params);
|
const res = await fetchSubAccountPage(params);
|
||||||
const { data, total } = res.data;
|
const { data, total, code } = res.data;
|
||||||
pagination.total = total;
|
if (code === 200) {
|
||||||
data.value = data;
|
pagination.total = total;
|
||||||
|
data.value = data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async function handleAddAccount() {
|
async function handleAddAccount() {
|
||||||
if (canAddAccount.value) {
|
if (canAddAccount.value) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<Container title="企业信息" class="container mt-24px">
|
<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 }">
|
<template #info="{ record }">
|
||||||
{{ record.name }}
|
{{ record.name }}
|
||||||
</template>
|
</template>
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<Modal v-model:visible="infoVisible" width="480px" title="修改企业名称" :okText="okText" @ok="handleOk">
|
<Modal v-model:visible="infoVisible" width="480px" title="修改企业名称" :okText="okText" @ok="handleOk">
|
||||||
<p class="tips">
|
<p class="tips">
|
||||||
企业名称只能修改2次,请谨慎操作。<span
|
企业名称只能修改2次,请谨慎操作。<span
|
||||||
>(剩余{{ enterpriseInfo.update_name_quota - enterpriseInfo.used_update_name_count }}次)
|
>(剩余{{ enterpriseInfo!.update_name_quota - enterpriseInfo!.used_update_name_count }}次)
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<a-form
|
<a-form
|
||||||
@ -54,12 +54,15 @@ const columns = [
|
|||||||
slotName: 'action',
|
slotName: 'action',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const data = ref([enterpriseInfo]);
|
|
||||||
|
|
||||||
const infoVisible = ref(false);
|
const infoVisible = ref(false);
|
||||||
const customerServiceVisible = ref(false);
|
const customerServiceVisible = ref(false);
|
||||||
|
|
||||||
|
const dataSource = computed(() => {
|
||||||
|
return enterpriseInfo ? [enterpriseInfo] : [];
|
||||||
|
});
|
||||||
const canUpdate = computed(() => {
|
const canUpdate = computed(() => {
|
||||||
|
if (!enterpriseInfo) return false;
|
||||||
return enterpriseInfo.update_name_quota > enterpriseInfo.used_update_name_count;
|
return enterpriseInfo.update_name_quota > enterpriseInfo.used_update_name_count;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -72,7 +75,7 @@ const okText = computed(() => {
|
|||||||
|
|
||||||
function handleUpdate() {
|
function handleUpdate() {
|
||||||
if (!canUpdate.value) {
|
if (!canUpdate.value) {
|
||||||
form.name = enterpriseInfo.name;
|
form.name = enterpriseInfo!.name;
|
||||||
}
|
}
|
||||||
infoVisible.value = true;
|
infoVisible.value = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<Container title="个人信息" class="container mt-24px">
|
<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 }">
|
<template #info="{ record }">
|
||||||
<div class="pt-3px pb-3px">
|
<div class="pt-3px pb-3px">
|
||||||
<a-avatar :image-url="record.head_image" :size="32" />
|
<a-avatar :image-url="record.head_image" :size="32" />
|
||||||
@ -85,7 +85,7 @@ import axios from 'axios';
|
|||||||
import { useUserStore } from '@/stores';
|
import { useUserStore } from '@/stores';
|
||||||
|
|
||||||
const store = useUserStore();
|
const store = useUserStore();
|
||||||
const userInfo = store.getUserInfo();
|
const userInfo = store.userInfo;
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
@ -97,7 +97,7 @@ const columns = [
|
|||||||
slotName: 'mobile',
|
slotName: 'mobile',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const data = reactive([userInfo]);
|
|
||||||
const infoVisible = ref(false);
|
const infoVisible = ref(false);
|
||||||
const imageVisible = ref(false);
|
const imageVisible = ref(false);
|
||||||
const mobileVisible = ref(false);
|
const mobileVisible = ref(false);
|
||||||
@ -108,6 +108,10 @@ const formRef = ref();
|
|||||||
const isSendCaptcha = ref(false);
|
const isSendCaptcha = ref(false);
|
||||||
const uploadInputRef = ref();
|
const uploadInputRef = ref();
|
||||||
|
|
||||||
|
const dataSource = computed(() => {
|
||||||
|
return userInfo ? [userInfo] : [];
|
||||||
|
});
|
||||||
|
|
||||||
// 表单校验规则
|
// 表单校验规则
|
||||||
const formRules = {
|
const formRules = {
|
||||||
mobile: [
|
mobile: [
|
||||||
|
|||||||
Reference in New Issue
Block a user