feat: 管理中心路由调整、选择公司逻辑调整
This commit is contained in:
@ -1,3 +1,7 @@
|
||||
/*
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-23 03:56:22
|
||||
*/
|
||||
import Http from '@/api';
|
||||
|
||||
// 导出一个函数,用于获取登录验证码
|
||||
@ -38,3 +42,8 @@ export const fetchEditPhoneCaptcha = (params = {}) => {
|
||||
export const fetchBindPhone = (params = {}) => {
|
||||
return Http.put('/v1/me/mobile', params);
|
||||
};
|
||||
|
||||
// 根据id获取企业信息
|
||||
export const fetchEnterpriseInfo = (id: number) => {
|
||||
return Http.get(`/v1/enterprises/${id}`);
|
||||
};
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
* @Author: 田鑫
|
||||
* @Date: 2023-02-17 11:58:44
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @LastEditTime: 2025-06-23 03:16:47
|
||||
* @LastEditTime: 2025-06-23 05:51:32
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
@ -23,8 +23,6 @@ const HttpStatusCode = {
|
||||
|
||||
import { useEnterpriseStore } from '@/stores/modules/enterprise';
|
||||
import pinia from '@/stores';
|
||||
const store = useEnterpriseStore(pinia);
|
||||
const enterprise = store.getEnterpriseInfo();
|
||||
|
||||
//* 导出Request类,可以用来自定义传递配置来创建实例
|
||||
export class Request {
|
||||
@ -44,12 +42,16 @@ export class Request {
|
||||
|
||||
this.instance.interceptors.request.use(
|
||||
(config: AxiosRequestConfig) => {
|
||||
const store = useEnterpriseStore(pinia);
|
||||
const enterprise = store.getEnterpriseInfo();
|
||||
|
||||
const token = localStorage.getItem('accessToken') as string;
|
||||
config.headers!.Authorization = token;
|
||||
|
||||
if (enterprise) {
|
||||
config.headers!['enterprise-id'] = enterprise.id;
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
(err: any) => {
|
||||
|
||||
@ -78,7 +78,7 @@ export default defineComponent({
|
||||
};
|
||||
const renderSubMenu = () => {
|
||||
function travel(_route: RouteRecordRaw[], nodes = []) {
|
||||
if (_route) {
|
||||
if (Array.isArray(_route)) {
|
||||
_route.forEach((element) => {
|
||||
// This is demo, modify nodes as needed
|
||||
const icon = element?.meta?.icon ? () => h(element?.meta?.icon as object) : null;
|
||||
@ -103,7 +103,7 @@ export default defineComponent({
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
return travel(menuTree.value);
|
||||
return travel(menuTree.value ?? []);
|
||||
};
|
||||
return () => (
|
||||
<a-menu
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
/*
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-19 01:45:53
|
||||
*/
|
||||
import type { RouteRecordRaw, RouteRecordNormalized } from 'vue-router';
|
||||
|
||||
import { useAppStore } from '@/stores';
|
||||
|
||||
@ -24,14 +24,14 @@ onMounted(() => {
|
||||
});
|
||||
const appStore = useAppStore();
|
||||
|
||||
function setServerMenu() {
|
||||
console.log('setServerMenu');
|
||||
}
|
||||
const setServerMenu = () => {
|
||||
router.push('/management/person');
|
||||
};
|
||||
const handleSelect = (index: any) => {
|
||||
if (index === 0) {
|
||||
router.push('/workplace');
|
||||
} else {
|
||||
router.push('/dataEngine/dataEngine/hotTranslation');
|
||||
router.push('/dataEngine/hotTranslation');
|
||||
}
|
||||
};
|
||||
|
||||
@ -39,17 +39,17 @@ const handleDopdownClick = (index: any, ind: any) => {
|
||||
let children = lists.value[index].children;
|
||||
let indPath = children[ind];
|
||||
if (indPath.name == '行业热门话题洞察') {
|
||||
router.push('/dataEngine/dataEngine/hotTranslation');
|
||||
router.push('/dataEngine/hotTranslation');
|
||||
} else if (indPath.name == '行业词云') {
|
||||
router.push('/dataEngine/dataEngine/hotCloud');
|
||||
router.push('/dataEngine/hotCloud');
|
||||
} else if (indPath.name == '行业关键词动向') {
|
||||
router.push('/dataEngine/dataEngine/keyWord');
|
||||
router.push('/dataEngine/keyWord');
|
||||
} else if (indPath.name == '用户痛点观察') {
|
||||
router.push('/dataEngine/dataEngine/userPainPoints');
|
||||
router.push('/dataEngine/userPainPoints');
|
||||
} else if (indPath.name == '重点品牌动向') {
|
||||
router.push('/dataEngine/dataEngine/keyBrandMovement');
|
||||
router.push('/dataEngine/keyBrandMovement');
|
||||
} else if (indPath.name == '用户画像') {
|
||||
router.push('/dataEngine/dataEngine/userPersona');
|
||||
router.push('/dataEngine/userPersona');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -13,10 +13,10 @@ export default function setupUserLoginInfoGuard(router: Router) {
|
||||
NProgress.start();
|
||||
const userStore = useUserStore();
|
||||
|
||||
const requireLogin = to?.meta?.requireLogin || 0;
|
||||
const requiresAuth = to?.meta?.requiresAuth || false;
|
||||
const isLogin = !!userStore.isLogin;
|
||||
|
||||
if (requireLogin === 1 && !isLogin) {
|
||||
if (requiresAuth && !isLogin) {
|
||||
goUserLogin();
|
||||
next();
|
||||
return;
|
||||
|
||||
@ -11,7 +11,7 @@ import 'nprogress/nprogress.css';
|
||||
import createRouteGuard from './guard';
|
||||
|
||||
NProgress.configure({ showSpinner: false }); // NProgress Configuration
|
||||
|
||||
// console.log({ appRoutes });
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: [
|
||||
@ -20,7 +20,7 @@ const router = createRouter({
|
||||
name: 'UserLogin',
|
||||
component: () => import('@/views/components/login'),
|
||||
meta: {
|
||||
requireLogin: 0,
|
||||
requiresAuth: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -29,33 +29,33 @@ const router = createRouter({
|
||||
component: () => import('@/views/components/workplace'),
|
||||
meta: {
|
||||
hideSidebar: true,
|
||||
requireLogin: 1,
|
||||
requiresAuth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
redirect: '/dataEngine/dataEngine/hotTranslation',
|
||||
redirect: '/dataEngine/hotTranslation',
|
||||
children: [...appRoutes, REDIRECT_MAIN, NOT_FOUND_ROUTE],
|
||||
meta: {
|
||||
requireLogin: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/dataEngine',
|
||||
name: 'dataEngine',
|
||||
redirect: '/dataEngine/dataEngine/hotTranslation',
|
||||
children: [...appRoutes, REDIRECT_MAIN, NOT_FOUND_ROUTE],
|
||||
meta: {
|
||||
requireLogin: 1,
|
||||
requiresAuth: true,
|
||||
},
|
||||
},
|
||||
// {
|
||||
// path: '/dataEngine',
|
||||
// name: 'dataEngine',
|
||||
// redirect: '/dataEngine/hotTranslation',
|
||||
// children: [...appRoutes, REDIRECT_MAIN, NOT_FOUND_ROUTE],
|
||||
// meta: {
|
||||
// requiresAuth: 1,
|
||||
// },
|
||||
// },
|
||||
{
|
||||
path: '/permission',
|
||||
name: 'permission',
|
||||
component: () => import('@/views/components/permission/choose-enterprise.vue'),
|
||||
meta: {
|
||||
requireLogin: 1,
|
||||
requiresAuth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -63,31 +63,7 @@ const router = createRouter({
|
||||
name: 'auth',
|
||||
component: () => import('@/views/components/permission/auth.vue'),
|
||||
meta: {
|
||||
requireLogin: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/management/person',
|
||||
name: 'person',
|
||||
component: () => import('@/views/components/management/person'),
|
||||
meta: {
|
||||
requireLogin: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/management/enterprise',
|
||||
name: 'enterprise',
|
||||
component: () => import('@/views/components/management/enterprise'),
|
||||
meta: {
|
||||
requireLogin: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/management/account',
|
||||
name: 'account',
|
||||
component: () => import('@/views/components/management/account'),
|
||||
meta: {
|
||||
requireLogin: 1,
|
||||
requiresAuth: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
52
src/router/routes/modules/management.ts
Normal file
52
src/router/routes/modules/management.ts
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-23 04:29:03
|
||||
*/
|
||||
import { IconBookmark } from '@arco-design/web-vue/es/icon';
|
||||
import type { AppRouteRecordRaw } from '../types';
|
||||
|
||||
const COMPONENTS: AppRouteRecordRaw = {
|
||||
path: 'management',
|
||||
name: 'management',
|
||||
meta: {
|
||||
locale: '管理中心',
|
||||
icon: IconBookmark,
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
requiresSidebar: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'person',
|
||||
name: '个人信息',
|
||||
component: () => import('@/views/components/management/person'),
|
||||
meta: {
|
||||
locale: '个人信息',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'enterprise',
|
||||
name: '企业信息',
|
||||
component: () => import('@/views/components/management/enterprise'),
|
||||
meta: {
|
||||
locale: '企业信息',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'account',
|
||||
name: '账号管理',
|
||||
component: () => import('@/views/components/management/account'),
|
||||
meta: {
|
||||
locale: '账号管理',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default COMPONENTS;
|
||||
@ -1,3 +1,5 @@
|
||||
import { fetchEnterpriseInfo } from '@/api/all/login';
|
||||
|
||||
interface EnterpriseInfo {
|
||||
id: number;
|
||||
name: string;
|
||||
@ -13,18 +15,11 @@ interface EnterpriseState {
|
||||
|
||||
export const useEnterpriseStore = defineStore('enterprise', {
|
||||
state: (): EnterpriseState => ({
|
||||
// todo 暂时写死,登录功能完成后记得重置为null哦
|
||||
enterpriseInfo: {
|
||||
id: 1,
|
||||
name: '企业1',
|
||||
update_name_quota: 2,
|
||||
used_update_name_count: 1,
|
||||
sub_account_quota: 2,
|
||||
used_sub_account_count: 0,
|
||||
},
|
||||
enterpriseInfo: null,
|
||||
}),
|
||||
actions: {
|
||||
setEnterpriseInfo(enterpriseInfo: EnterpriseInfo) {
|
||||
console.log('setEnterpriseInfo', enterpriseInfo);
|
||||
this.enterpriseInfo = enterpriseInfo;
|
||||
},
|
||||
setEnterpriseName(name: string) {
|
||||
@ -45,5 +40,12 @@ export const useEnterpriseStore = defineStore('enterprise', {
|
||||
getEnterpriseInfo(): EnterpriseInfo | null {
|
||||
return this.enterpriseInfo;
|
||||
},
|
||||
async updateEnterpriseInfo() {
|
||||
const res = await fetchEnterpriseInfo(this.enterpriseInfo!.id);
|
||||
const { code, data } = res;
|
||||
if (code === 200) {
|
||||
this.setEnterpriseInfo(data);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -101,14 +101,14 @@
|
||||
v-for="(account, index) in accounts"
|
||||
:key="index"
|
||||
class="account-item"
|
||||
:class="{ selected: selectedAccount === index }"
|
||||
@click="selectAccount(index)"
|
||||
:class="{ selected: selectedAccountIndex === index }"
|
||||
@click="selectAccount(account, index)"
|
||||
>
|
||||
<a-list-item-meta>
|
||||
<template #title>
|
||||
<div style="display: flex; align-items: center; gap: 12px">
|
||||
<a-checkbox :model-value="selectedAccount === index" />
|
||||
<a-typography-text>{{ account.name }}</a-typography-text>
|
||||
<a-checkbox :model-value="selectedAccountIndex === index" />
|
||||
<a-typography-text>{{ account.name || '-' }}</a-typography-text>
|
||||
</div>
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
@ -124,11 +124,13 @@ import PuzzleVerification from './components/PuzzleVerification.vue';
|
||||
import { fetchLoginCaptCha, fetchAuthorizationsCaptcha, fetchProfileInfo } from '@/api/all/login';
|
||||
import { ref, reactive, onUnmounted, computed } from 'vue';
|
||||
import { useUserStore } from '@/stores';
|
||||
import { useEnterpriseStore } from '@/stores/modules/enterprise';
|
||||
import { handleUserLogin } from '@/utils/user';
|
||||
import router from '@/router';
|
||||
|
||||
const formRef = ref();
|
||||
const userStore = useUserStore();
|
||||
const enterpriseStore = useEnterpriseStore();
|
||||
const countdown = ref(0);
|
||||
let timer = ref();
|
||||
const isLogin = ref(true);
|
||||
@ -138,7 +140,7 @@ const hasGetCode = ref(false);
|
||||
const submitting = ref(false);
|
||||
const hasCheck = ref(false);
|
||||
const mobileNumber = ref('');
|
||||
const selectedAccount = ref(0);
|
||||
const selectedAccountIndex = ref(0);
|
||||
|
||||
const accounts = ref([]);
|
||||
|
||||
@ -199,8 +201,9 @@ const disabledSubmitBtn = computed(() => {
|
||||
return !isFormValid.value;
|
||||
});
|
||||
|
||||
const selectAccount = (index: any) => {
|
||||
selectedAccount.value = index;
|
||||
const selectAccount = (account: any, index: any) => {
|
||||
enterpriseStore.setEnterpriseInfo(account);
|
||||
selectedAccountIndex.value = index;
|
||||
};
|
||||
|
||||
const validateField = (field: string) => {
|
||||
@ -211,8 +214,10 @@ const clearError = (field: string) => {
|
||||
formRef.value.clearValidate(field);
|
||||
};
|
||||
|
||||
const handleOk = () => {
|
||||
const handleOk = async () => {
|
||||
visible.value = false;
|
||||
|
||||
await enterpriseStore.updateEnterpriseInfo();
|
||||
handleUserLogin();
|
||||
};
|
||||
|
||||
@ -259,15 +264,14 @@ const handleVerificationSubmit = async () => {
|
||||
const getProfileInfo = async () => {
|
||||
const { code, data } = await fetchProfileInfo();
|
||||
if (code === 200) {
|
||||
enterpriseStore.setEnterpriseInfo(data);
|
||||
userStore.setUserInfo(data);
|
||||
let enterprises = data['enterprises'];
|
||||
mobileNumber.value = data['mobile'];
|
||||
accounts.value = enterprises;
|
||||
if (enterprises.length > 0) {
|
||||
if (enterprises.length == 1) {
|
||||
|
||||
// let enterprise = enterprises[0];
|
||||
// userStore.setCompanyInfo(enterprise);
|
||||
if (enterprises.length === 1) {
|
||||
await enterpriseStore.updateEnterpriseInfo();
|
||||
handleUserLogin();
|
||||
} else {
|
||||
// 多个企业时候需要弹窗让用户选择企业
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<template #info="{ record }">
|
||||
<div class="pt-3px pb-3px">
|
||||
<a-avatar :image-url="record.head_image" :size="32" />
|
||||
{{ record.name }}
|
||||
{{ record.name || '-' }}
|
||||
<icon-edit size="13" class="ml-8px" @click="openEditInfoModal" />
|
||||
</div>
|
||||
</template>
|
||||
@ -170,15 +170,17 @@ async function handleFileChange(event: Event) {
|
||||
const file = target.files?.[0];
|
||||
if (file) {
|
||||
const fileExtension = getFileExtension(file.name);
|
||||
const res = await fetchImageUploadFile({
|
||||
const { data } = await fetchImageUploadFile({
|
||||
suffix: fileExtension,
|
||||
});
|
||||
const { upload_url, file_name, file_url } = data;
|
||||
|
||||
const blob = new Blob([file], { type: file.type });
|
||||
await axios.put(res.upload_url, blob, {
|
||||
await axios.put(upload_url, blob, {
|
||||
headers: { 'Content-Type': file.type },
|
||||
});
|
||||
userInfoForm.head_image = res.file_name;
|
||||
userInfoForm.file_url = res.file_url;
|
||||
userInfoForm.head_image = file_name;
|
||||
userInfoForm.file_url = file_url;
|
||||
}
|
||||
}
|
||||
function openEditImageModal() {
|
||||
@ -191,8 +193,6 @@ function openEditMobileModal() {
|
||||
|
||||
async function handleSubmitUserInfo() {
|
||||
await updateMyInfo(userInfoForm);
|
||||
store.setUserName(userInfoForm.name);
|
||||
store.setUserHeadImage(userInfoForm.file_url);
|
||||
AMessage.success('修改成功!');
|
||||
}
|
||||
|
||||
@ -235,7 +235,6 @@ async function handleUpdateMobile() {
|
||||
const res = await formRef.value.validate();
|
||||
if (res === true || res === undefined) {
|
||||
await updateMobile(form);
|
||||
store.setUserMobile(form.mobile);
|
||||
AMessage.success('修改成功!');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user