mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-09-26 21:26:42 +08:00
feat(projects): ceshitijiao
This commit is contained in:
parent
e89b86ce56
commit
e55a822add
44
.env
44
.env
@ -1,60 +1,60 @@
|
|||||||
# the base url of the application, the default is "/"
|
# 应用的基础路径,默认为 "/"
|
||||||
# if use a sub directory, it must be end with "/", like "/admin/" but not "/admin"
|
# 如果使用子目录,必须以 "/" 结尾,如 "/admin/" 而不是 "/admin"
|
||||||
VITE_BASE_URL=/
|
VITE_BASE_URL=/
|
||||||
|
|
||||||
VITE_APP_TITLE=SoybeanAdmin
|
VITE_APP_TITLE=SoybeanAdmin
|
||||||
|
|
||||||
VITE_APP_DESC=SoybeanAdmin is a fresh and elegant admin template
|
VITE_APP_DESC=SoybeanAdmin 是一个清新优雅的管理后台模板
|
||||||
|
|
||||||
# the prefix of the icon name
|
# 图标名称的前缀
|
||||||
VITE_ICON_PREFIX=icon
|
VITE_ICON_PREFIX=icon
|
||||||
|
|
||||||
# the prefix of the local svg icon component, must include VITE_ICON_PREFIX
|
# 本地 svg 图标组件的前缀,必须包含 VITE_ICON_PREFIX
|
||||||
# format {VITE_ICON_PREFIX}-{local icon name}
|
# 格式为 {VITE_ICON_PREFIX}-{本地图标名}
|
||||||
VITE_ICON_LOCAL_PREFIX=icon-local
|
VITE_ICON_LOCAL_PREFIX=icon-local
|
||||||
|
|
||||||
# auth route mode: static | dynamic
|
# 权限路由模式:static | dynamic
|
||||||
VITE_AUTH_ROUTE_MODE=static
|
VITE_AUTH_ROUTE_MODE=static
|
||||||
|
|
||||||
# static auth route home
|
# static 权限路由的首页
|
||||||
VITE_ROUTE_HOME=home
|
VITE_ROUTE_HOME=home
|
||||||
|
|
||||||
# default menu icon
|
# 默认菜单图标
|
||||||
VITE_MENU_ICON=mdi:menu
|
VITE_MENU_ICON=mdi:menu
|
||||||
|
|
||||||
# whether to enable http proxy when is dev mode
|
# 是否在开发模式下启用 http 代理
|
||||||
VITE_HTTP_PROXY=Y
|
VITE_HTTP_PROXY=Y
|
||||||
|
|
||||||
# vue-router mode: hash | history | memory
|
# vue-router 模式:hash | history | memory
|
||||||
VITE_ROUTER_HISTORY_MODE=history
|
VITE_ROUTER_HISTORY_MODE=history
|
||||||
|
|
||||||
# success code of backend service, when the code is received, the request is successful
|
# 后端服务的成功状态码,收到该状态码时请求成功
|
||||||
VITE_SERVICE_SUCCESS_CODE=0000
|
VITE_SERVICE_SUCCESS_CODE=0000
|
||||||
|
|
||||||
# logout codes of backend service, when the code is received, the user will be logged out and redirected to login page
|
# 后端服务登出状态码,收到该状态码时用户会被登出并跳转到登录页
|
||||||
VITE_SERVICE_LOGOUT_CODES=8888,8889
|
VITE_SERVICE_LOGOUT_CODES=8888,8889
|
||||||
|
|
||||||
# modal logout codes of backend service, when the code is received, the user will be logged out by displaying a modal
|
# 后端服务弹窗登出状态码,收到该状态码时会弹窗提示并登出
|
||||||
VITE_SERVICE_MODAL_LOGOUT_CODES=7777,7778
|
VITE_SERVICE_MODAL_LOGOUT_CODES=7777,7778
|
||||||
|
|
||||||
# token expired codes of backend service, when the code is received, it will refresh the token and resend the request
|
# 后端服务 token 过期状态码,收到该状态码时会刷新 token 并重新发送请求
|
||||||
VITE_SERVICE_EXPIRED_TOKEN_CODES=9999,9998,3333
|
VITE_SERVICE_EXPIRED_TOKEN_CODES=9999,9998,3333
|
||||||
|
|
||||||
# when the route mode is static, the defined super role
|
# 路由模式为 static 时定义的超级角色
|
||||||
VITE_STATIC_SUPER_ROLE=R_SUPER
|
VITE_STATIC_SUPER_ROLE=R_SUPER
|
||||||
|
|
||||||
# sourcemap
|
# 是否生成 sourcemap
|
||||||
VITE_SOURCE_MAP=N
|
VITE_SOURCE_MAP=N
|
||||||
|
|
||||||
# Used to differentiate storage across different domains
|
# 用于区分不同域名下的存储
|
||||||
VITE_STORAGE_PREFIX=SOY_
|
VITE_STORAGE_PREFIX=SOY_
|
||||||
|
|
||||||
# used to control whether the program automatically detects updates
|
# 控制程序打包后是否自动检测更新
|
||||||
VITE_AUTOMATICALLY_DETECT_UPDATE=Y
|
VITE_AUTOMATICALLY_DETECT_UPDATE=Y
|
||||||
|
|
||||||
# show proxy url log in terminal
|
# 是否在终端显示代理地址日志
|
||||||
VITE_PROXY_LOG=Y
|
VITE_PROXY_LOG=Y
|
||||||
|
|
||||||
# used to control whether to launch editor
|
# 控制是否启动编辑器
|
||||||
# by the way, this plugin is only available in dev mode, not in build mode
|
# 此插件仅在开发模式下可用,构建模式下不可用
|
||||||
VITE_DEVTOOLS_LAUNCH_EDITOR=code
|
VITE_DEVTOOLS_LAUNCH_EDITOR=code
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# backend service base url, prod environment
|
# # 后端服务基础地址,生产环境
|
||||||
VITE_SERVICE_BASE_URL=https://mock.apifox.cn/m1/3109515-0-default
|
VITE_SERVICE_BASE_URL=https://mock.apifox.cn/m1/3109515-0-default
|
||||||
|
|
||||||
# other backend service base url, prod environment
|
# 其他后端服务基础地址,生产环境
|
||||||
VITE_OTHER_SERVICE_BASE_URL= `{
|
VITE_OTHER_SERVICE_BASE_URL= `{
|
||||||
"demo": "http://localhost:9529"
|
"demo": "http://localhost:9529"
|
||||||
}`
|
}`
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# backend service base url, test environment
|
# 后端服务基础地址,测试环境
|
||||||
VITE_SERVICE_BASE_URL=https://mock.apifox.cn/m1/3109515-0-default
|
VITE_SERVICE_BASE_URL=https://mock.apifox.cn/m1/3109515-0-default
|
||||||
|
|
||||||
# other backend service base url, test environment
|
# 其他后端服务基础地址,测试环境
|
||||||
VITE_OTHER_SERVICE_BASE_URL= `{
|
VITE_OTHER_SERVICE_BASE_URL= `{
|
||||||
"demo": "http://localhost:9528"
|
"demo": "http://localhost:9528"
|
||||||
}`
|
}`
|
||||||
|
@ -4,10 +4,10 @@ import { consola } from 'consola';
|
|||||||
import { createServiceConfig } from '../../src/utils/service';
|
import { createServiceConfig } from '../../src/utils/service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set http proxy
|
* 设置 http 代理
|
||||||
*
|
*
|
||||||
* @param env - The current env
|
* @param env - 当前环境变量
|
||||||
* @param enable - If enable http proxy
|
* @param enable - 是否启用 http 代理
|
||||||
*/
|
*/
|
||||||
export function createViteProxy(env: Env.ImportMeta, enable: boolean) {
|
export function createViteProxy(env: Env.ImportMeta, enable: boolean) {
|
||||||
const isEnableHttpProxy = enable && env.VITE_HTTP_PROXY === 'Y';
|
const isEnableHttpProxy = enable && env.VITE_HTTP_PROXY === 'Y';
|
||||||
@ -27,6 +27,12 @@ export function createViteProxy(env: Env.ImportMeta, enable: boolean) {
|
|||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建单个代理项
|
||||||
|
*
|
||||||
|
* @param item 代理配置项
|
||||||
|
* @param enableLog 是否启用日志
|
||||||
|
*/
|
||||||
function createProxyItem(item: App.Service.ServiceConfigItem, enableLog: boolean) {
|
function createProxyItem(item: App.Service.ServiceConfigItem, enableLog: boolean) {
|
||||||
const proxy: Record<string, ProxyOptions> = {};
|
const proxy: Record<string, ProxyOptions> = {};
|
||||||
|
|
||||||
|
@ -12,22 +12,22 @@ type CommandAction<A extends object> = (args?: A) => Promise<void> | void;
|
|||||||
type CommandWithAction<A extends object = object> = Record<Command, { desc: string; action: CommandAction<A> }>;
|
type CommandWithAction<A extends object = object> = Record<Command, { desc: string; action: CommandAction<A> }>;
|
||||||
|
|
||||||
interface CommandArg {
|
interface CommandArg {
|
||||||
/** Execute additional command after bumping and before git commit. Defaults to 'pnpm sa changelog' */
|
/** bump 版本并 git commit 之前执行的额外命令,默认为 'pnpm sa changelog' */
|
||||||
execute?: string;
|
execute?: string;
|
||||||
/** Indicates whether to push the git commit and tag. Defaults to true */
|
/** 是否推送 git commit 和 tag,默认为 true */
|
||||||
push?: boolean;
|
push?: boolean;
|
||||||
/** Generate changelog by total tags */
|
/** 是否根据所有 tag 生成 changelog */
|
||||||
total?: boolean;
|
total?: boolean;
|
||||||
/**
|
/**
|
||||||
* The glob pattern of dirs to clean up
|
* 需要清理的目录的 glob 模式
|
||||||
*
|
*
|
||||||
* If not set, it will use the default value
|
* 如果未设置,则使用默认值
|
||||||
*
|
*
|
||||||
* Multiple values use "," to separate them
|
* 多个值用 "," 分隔
|
||||||
*/
|
*/
|
||||||
cleanupDir?: string;
|
cleanupDir?: string;
|
||||||
/**
|
/**
|
||||||
* display lang of cli
|
* CLI 显示语言
|
||||||
*
|
*
|
||||||
* @default 'en-us'
|
* @default 'en-us'
|
||||||
*/
|
*/
|
||||||
@ -41,58 +41,52 @@ export async function setupCli() {
|
|||||||
|
|
||||||
cli
|
cli
|
||||||
.version(lightGreen(version))
|
.version(lightGreen(version))
|
||||||
.option(
|
.option('-e, --execute [command]', "bump 版本并 git commit 之前执行的额外命令,默认为 'npx soy changelog'")
|
||||||
'-e, --execute [command]',
|
.option('-p, --push', '是否推送 git commit 和 tag')
|
||||||
"Execute additional command after bumping and before git commit. Defaults to 'npx soy changelog'"
|
.option('-t, --total', '是否根据所有 tag 生成 changelog')
|
||||||
)
|
.option('-c, --cleanupDir <dir>', '需要清理的目录的 glob 模式,未设置则使用默认值,多个值用 "," 分隔')
|
||||||
.option('-p, --push', 'Indicates whether to push the git commit and tag')
|
.option('-l, --lang <lang>', 'CLI 显示语言', { default: 'en-us', type: [String] })
|
||||||
.option('-t, --total', 'Generate changelog by total tags')
|
|
||||||
.option(
|
|
||||||
'-c, --cleanupDir <dir>',
|
|
||||||
'The glob pattern of dirs to cleanup, If not set, it will use the default value, Multiple values use "," to separate them'
|
|
||||||
)
|
|
||||||
.option('-l, --lang <lang>', 'display lang of cli', { default: 'en-us', type: [String] })
|
|
||||||
.help();
|
.help();
|
||||||
|
|
||||||
const commands: CommandWithAction<CommandArg> = {
|
const commands: CommandWithAction<CommandArg> = {
|
||||||
cleanup: {
|
cleanup: {
|
||||||
desc: 'delete dirs: node_modules, dist, etc.',
|
desc: '删除 node_modules、dist 等目录',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
await cleanup(cliOptions.cleanupDirs);
|
await cleanup(cliOptions.cleanupDirs);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'update-pkg': {
|
'update-pkg': {
|
||||||
desc: 'update package.json dependencies versions',
|
desc: '更新 package.json 依赖版本',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
await updatePkg(cliOptions.ncuCommandArgs);
|
await updatePkg(cliOptions.ncuCommandArgs);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'git-commit': {
|
'git-commit': {
|
||||||
desc: 'git commit, generate commit message which match Conventional Commits standard',
|
desc: 'git commit,生成符合 Conventional Commits 规范的提交信息',
|
||||||
action: async args => {
|
action: async args => {
|
||||||
await gitCommit(args?.lang);
|
await gitCommit(args?.lang);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'git-commit-verify': {
|
'git-commit-verify': {
|
||||||
desc: 'verify git commit message, make sure it match Conventional Commits standard',
|
desc: '校验 git commit 信息,确保符合 Conventional Commits 规范',
|
||||||
action: async args => {
|
action: async args => {
|
||||||
await gitCommitVerify(args?.lang, cliOptions.gitCommitVerifyIgnores);
|
await gitCommitVerify(args?.lang, cliOptions.gitCommitVerifyIgnores);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changelog: {
|
changelog: {
|
||||||
desc: 'generate changelog',
|
desc: '生成 changelog',
|
||||||
action: async args => {
|
action: async args => {
|
||||||
await genChangelog(cliOptions.changelogOptions, args?.total);
|
await genChangelog(cliOptions.changelogOptions, args?.total);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
release: {
|
release: {
|
||||||
desc: 'release: update version, generate changelog, commit code',
|
desc: '发布:更新版本、生成 changelog、提交代码',
|
||||||
action: async args => {
|
action: async args => {
|
||||||
await release(args?.execute, args?.push);
|
await release(args?.execute, args?.push);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'gen-route': {
|
'gen-route': {
|
||||||
desc: 'generate route',
|
desc: '生成路由',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
await generateRoute();
|
await generateRoute();
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,8 @@ const local: App.I18n.Schema = {
|
|||||||
404: 'Page Not Found',
|
404: 'Page Not Found',
|
||||||
500: 'Server Error',
|
500: 'Server Error',
|
||||||
'iframe-page': 'Iframe',
|
'iframe-page': 'Iframe',
|
||||||
home: 'Home'
|
home: 'Home',
|
||||||
|
cesium: 'Cesium'
|
||||||
},
|
},
|
||||||
page: {
|
page: {
|
||||||
login: {
|
login: {
|
||||||
|
@ -166,7 +166,8 @@ const local: App.I18n.Schema = {
|
|||||||
404: '页面不存在',
|
404: '页面不存在',
|
||||||
500: '服务器错误',
|
500: '服务器错误',
|
||||||
'iframe-page': '外链页面',
|
'iframe-page': '外链页面',
|
||||||
home: '首页'
|
home: '首页',
|
||||||
|
cesium: '三维地球'
|
||||||
},
|
},
|
||||||
page: {
|
page: {
|
||||||
login: {
|
login: {
|
||||||
|
@ -20,5 +20,6 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
|||||||
500: () => import("@/views/_builtin/500/index.vue"),
|
500: () => import("@/views/_builtin/500/index.vue"),
|
||||||
"iframe-page": () => import("@/views/_builtin/iframe-page/[url].vue"),
|
"iframe-page": () => import("@/views/_builtin/iframe-page/[url].vue"),
|
||||||
login: () => import("@/views/_builtin/login/index.vue"),
|
login: () => import("@/views/_builtin/login/index.vue"),
|
||||||
|
cesium: () => import("@/views/cesium/index.vue"),
|
||||||
home: () => import("@/views/home/index.vue"),
|
home: () => import("@/views/home/index.vue"),
|
||||||
};
|
};
|
||||||
|
@ -39,6 +39,16 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
hideInMenu: true
|
hideInMenu: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'cesium',
|
||||||
|
path: '/cesium',
|
||||||
|
component: 'layout.base$view.cesium',
|
||||||
|
meta: {
|
||||||
|
title: 'cesium',
|
||||||
|
i18nKey: 'route.cesium',
|
||||||
|
order: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'home',
|
name: 'home',
|
||||||
path: '/home',
|
path: '/home',
|
||||||
@ -47,7 +57,7 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
title: 'home',
|
title: 'home',
|
||||||
i18nKey: 'route.home',
|
i18nKey: 'route.home',
|
||||||
icon: 'mdi:monitor-dashboard',
|
icon: 'mdi:monitor-dashboard',
|
||||||
order: 1
|
order: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -166,6 +166,7 @@ const routeMap: RouteMap = {
|
|||||||
"403": "/403",
|
"403": "/403",
|
||||||
"404": "/404",
|
"404": "/404",
|
||||||
"500": "/500",
|
"500": "/500",
|
||||||
|
"cesium": "/cesium",
|
||||||
"home": "/home",
|
"home": "/home",
|
||||||
"iframe-page": "/iframe-page/:url",
|
"iframe-page": "/iframe-page/:url",
|
||||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?"
|
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?"
|
||||||
|
@ -12,9 +12,9 @@ import { localStg } from '@/utils/storage';
|
|||||||
import { getRouteName } from '@/router/elegant/transform';
|
import { getRouteName } from '@/router/elegant/transform';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create route guard
|
* 创建路由守卫
|
||||||
*
|
*
|
||||||
* @param router router instance
|
* @param router 路由实例
|
||||||
*/
|
*/
|
||||||
export function createRouteGuard(router: Router) {
|
export function createRouteGuard(router: Router) {
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
@ -38,39 +38,39 @@ export function createRouteGuard(router: Router) {
|
|||||||
const hasRole = authStore.userInfo.roles.some(role => routeRoles.includes(role));
|
const hasRole = authStore.userInfo.roles.some(role => routeRoles.includes(role));
|
||||||
const hasAuth = authStore.isStaticSuper || !routeRoles.length || hasRole;
|
const hasAuth = authStore.isStaticSuper || !routeRoles.length || hasRole;
|
||||||
|
|
||||||
// if it is login route when logged in, then switch to the root page
|
// 已登录时访问登录页,跳转到首页
|
||||||
if (to.name === loginRoute && isLogin) {
|
if (to.name === loginRoute && isLogin) {
|
||||||
next({ name: rootRoute });
|
next({ name: rootRoute });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the route does not need login, then it is allowed to access directly
|
// 路由不需要登录,直接放行
|
||||||
if (!needLogin) {
|
if (!needLogin) {
|
||||||
handleRouteSwitch(to, from, next);
|
handleRouteSwitch(to, from, next);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the route need login but the user is not logged in, then switch to the login page
|
// 路由需要登录但用户未登录,跳转到登录页
|
||||||
if (!isLogin) {
|
if (!isLogin) {
|
||||||
next({ name: loginRoute, query: { redirect: to.fullPath } });
|
next({ name: loginRoute, query: { redirect: to.fullPath } });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the user is logged in but does not have authorization, then switch to the 403 page
|
// 已登录但无权限,跳转到 403 页面
|
||||||
if (!hasAuth) {
|
if (!hasAuth) {
|
||||||
next({ name: noAuthorizationRoute });
|
next({ name: noAuthorizationRoute });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch route normally
|
// 正常切换路由
|
||||||
handleRouteSwitch(to, from, next);
|
handleRouteSwitch(to, from, next);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initialize route
|
* 初始化路由
|
||||||
*
|
*
|
||||||
* @param to to route
|
* @param to 目标路由
|
||||||
*/
|
*/
|
||||||
async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw | null> {
|
async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw | null> {
|
||||||
const routeStore = useRouteStore();
|
const routeStore = useRouteStore();
|
||||||
@ -78,12 +78,12 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
const notFoundRoute: RouteKey = 'not-found';
|
const notFoundRoute: RouteKey = 'not-found';
|
||||||
const isNotFoundRoute = to.name === notFoundRoute;
|
const isNotFoundRoute = to.name === notFoundRoute;
|
||||||
|
|
||||||
// if the constant route is not initialized, then initialize the constant route
|
// 如果常量路由未初始化,则初始化常量路由
|
||||||
if (!routeStore.isInitConstantRoute) {
|
if (!routeStore.isInitConstantRoute) {
|
||||||
await routeStore.initConstantRoute();
|
await routeStore.initConstantRoute();
|
||||||
|
|
||||||
// the route is captured by the "not-found" route because the constant route is not initialized
|
// 因为常量路由未初始化,被 not-found 路由捕获
|
||||||
// after the constant route is initialized, redirect to the original route
|
// 常量路由初始化后,重定向到原始路由
|
||||||
const path = to.fullPath;
|
const path = to.fullPath;
|
||||||
const location: RouteLocationRaw = {
|
const location: RouteLocationRaw = {
|
||||||
path,
|
path,
|
||||||
@ -98,14 +98,14 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
const isLogin = Boolean(localStg.get('token'));
|
const isLogin = Boolean(localStg.get('token'));
|
||||||
|
|
||||||
if (!isLogin) {
|
if (!isLogin) {
|
||||||
// if the user is not logged in and the route is a constant route but not the "not-found" route, then it is allowed to access.
|
// 未登录且为常量路由但不是 not-found 路由,允许访问
|
||||||
if (to.meta.constant && !isNotFoundRoute) {
|
if (to.meta.constant && !isNotFoundRoute) {
|
||||||
routeStore.onRouteSwitchWhenNotLoggedIn();
|
routeStore.onRouteSwitchWhenNotLoggedIn();
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the user is not logged in, then switch to the login page
|
// 未登录,跳转到登录页
|
||||||
const loginRoute: RouteKey = 'login';
|
const loginRoute: RouteKey = 'login';
|
||||||
const query = getRouteQueryOfLoginRoute(to, routeStore.routeHome);
|
const query = getRouteQueryOfLoginRoute(to, routeStore.routeHome);
|
||||||
|
|
||||||
@ -118,11 +118,11 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!routeStore.isInitAuthRoute) {
|
if (!routeStore.isInitAuthRoute) {
|
||||||
// initialize the auth route
|
// 初始化权限路由
|
||||||
await routeStore.initAuthRoute();
|
await routeStore.initAuthRoute();
|
||||||
|
|
||||||
// the route is captured by the "not-found" route because the auth route is not initialized
|
// 因为权限路由未初始化,被 not-found 路由捕获
|
||||||
// after the auth route is initialized, redirect to the original route
|
// 权限路由初始化后,重定向到原始路由
|
||||||
if (isNotFoundRoute) {
|
if (isNotFoundRoute) {
|
||||||
const rootRoute: RouteKey = 'root';
|
const rootRoute: RouteKey = 'root';
|
||||||
const path = to.redirectedFrom?.name === rootRoute ? '/' : to.fullPath;
|
const path = to.redirectedFrom?.name === rootRoute ? '/' : to.fullPath;
|
||||||
@ -140,13 +140,12 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
|
|
||||||
routeStore.onRouteSwitchWhenLoggedIn();
|
routeStore.onRouteSwitchWhenLoggedIn();
|
||||||
|
|
||||||
// the auth route is initialized
|
// 权限路由已初始化,且不是 not-found 路由,允许访问
|
||||||
// it is not the "not-found" route, then it is allowed to access
|
|
||||||
if (!isNotFoundRoute) {
|
if (!isNotFoundRoute) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// it is captured by the "not-found" route, then check whether the route exists
|
// 被 not-found 路由捕获,判断路由是否存在
|
||||||
const exist = await routeStore.getIsAuthRouteExist(to.path as RoutePath);
|
const exist = await routeStore.getIsAuthRouteExist(to.path as RoutePath);
|
||||||
const noPermissionRoute: RouteKey = '403';
|
const noPermissionRoute: RouteKey = '403';
|
||||||
|
|
||||||
@ -161,8 +160,11 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理路由切换
|
||||||
|
*/
|
||||||
function handleRouteSwitch(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) {
|
function handleRouteSwitch(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) {
|
||||||
// route with href
|
// 带 href 的路由
|
||||||
if (to.meta.href) {
|
if (to.meta.href) {
|
||||||
window.open(to.meta.href, '_blank');
|
window.open(to.meta.href, '_blank');
|
||||||
|
|
||||||
@ -174,6 +176,9 @@ function handleRouteSwitch(to: RouteLocationNormalized, from: RouteLocationNorma
|
|||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取登录路由的 query
|
||||||
|
*/
|
||||||
function getRouteQueryOfLoginRoute(to: RouteLocationNormalized, routeHome: RouteKey) {
|
function getRouteQueryOfLoginRoute(to: RouteLocationNormalized, routeHome: RouteKey) {
|
||||||
const loginRoute: RouteKey = 'login';
|
const loginRoute: RouteKey = 'login';
|
||||||
const redirect = to.fullPath;
|
const redirect = to.fullPath;
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
import { request } from '../request';
|
import { request } from '../request';
|
||||||
|
|
||||||
/** get constant routes */
|
/** 获取常量路由 */
|
||||||
export function fetchGetConstantRoutes() {
|
export function fetchGetConstantRoutes() {
|
||||||
return request<Api.Route.MenuRoute[]>({ url: '/route/getConstantRoutes' });
|
return request<Api.Route.MenuRoute[]>({ url: '/route/getConstantRoutes' });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** get user routes */
|
/** 获取用户路由 */
|
||||||
export function fetchGetUserRoutes() {
|
export function fetchGetUserRoutes() {
|
||||||
return request<Api.Route.UserRoute>({ url: '/route/getUserRoutes' });
|
return request<Api.Route.UserRoute>({ url: '/route/getUserRoutes' });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* whether the route is exist
|
* 判断路由是否存在
|
||||||
*
|
*
|
||||||
* @param routeName route name
|
* @param routeName 路由名称
|
||||||
*/
|
*/
|
||||||
export function fetchIsRouteExist(routeName: string) {
|
export function fetchIsRouteExist(routeName: string) {
|
||||||
return request<boolean>({ url: '/route/isRouteExist', params: { routeName } });
|
return request<boolean>({ url: '/route/isRouteExist', params: { routeName } });
|
||||||
|
49
src/typings/api.d.ts
vendored
49
src/typings/api.d.ts
vendored
@ -1,64 +1,67 @@
|
|||||||
/**
|
/**
|
||||||
* Namespace Api
|
* 命名空间 Api
|
||||||
*
|
*
|
||||||
* All backend api type
|
* 所有后端 API 类型
|
||||||
*/
|
*/
|
||||||
declare namespace Api {
|
declare namespace Api {
|
||||||
namespace Common {
|
namespace Common {
|
||||||
/** common params of paginating */
|
/** 分页通用参数 */
|
||||||
interface PaginatingCommonParams {
|
interface PaginatingCommonParams {
|
||||||
/** current page number */
|
/** 当前页码 */
|
||||||
current: number;
|
current: number;
|
||||||
/** page size */
|
/** 每页数量 */
|
||||||
size: number;
|
size: number;
|
||||||
/** total count */
|
/** 总条数 */
|
||||||
total: number;
|
total: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** common params of paginating query list data */
|
/** 分页查询列表数据的通用参数 */
|
||||||
interface PaginatingQueryRecord<T = any> extends PaginatingCommonParams {
|
interface PaginatingQueryRecord<T = any> extends PaginatingCommonParams {
|
||||||
|
/** 数据列表 */
|
||||||
records: T[];
|
records: T[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** common search params of table */
|
/** 表格通用搜索参数 */
|
||||||
type CommonSearchParams = Pick<Common.PaginatingCommonParams, 'current' | 'size'>;
|
type CommonSearchParams = Pick<Common.PaginatingCommonParams, 'current' | 'size'>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enable status
|
* 启用状态
|
||||||
*
|
*
|
||||||
* - "1": enabled
|
* - "1": 启用
|
||||||
* - "2": disabled
|
* - "2": 禁用
|
||||||
*/
|
*/
|
||||||
type EnableStatus = '1' | '2';
|
type EnableStatus = '1' | '2';
|
||||||
|
|
||||||
/** common record */
|
/** 通用记录 */
|
||||||
type CommonRecord<T = any> = {
|
type CommonRecord<T = any> = {
|
||||||
/** record id */
|
/** 记录ID */
|
||||||
id: number;
|
id: number;
|
||||||
/** record creator */
|
/** 创建人 */
|
||||||
createBy: string;
|
createBy: string;
|
||||||
/** record create time */
|
/** 创建时间 */
|
||||||
createTime: string;
|
createTime: string;
|
||||||
/** record updater */
|
/** 更新人 */
|
||||||
updateBy: string;
|
updateBy: string;
|
||||||
/** record update time */
|
/** 更新时间 */
|
||||||
updateTime: string;
|
updateTime: string;
|
||||||
/** record status */
|
/** 状态 */
|
||||||
status: EnableStatus | null;
|
status: EnableStatus | null;
|
||||||
} & T;
|
} & T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* namespace Auth
|
* 命名空间 Auth
|
||||||
*
|
*
|
||||||
* backend api module: "auth"
|
* 后端 API 模块:"auth"
|
||||||
*/
|
*/
|
||||||
namespace Auth {
|
namespace Auth {
|
||||||
|
/** 登录令牌 */
|
||||||
interface LoginToken {
|
interface LoginToken {
|
||||||
token: string;
|
token: string;
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 用户信息 */
|
||||||
interface UserInfo {
|
interface UserInfo {
|
||||||
userId: string;
|
userId: string;
|
||||||
userName: string;
|
userName: string;
|
||||||
@ -68,17 +71,19 @@ declare namespace Api {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* namespace Route
|
* 命名空间 Route
|
||||||
*
|
*
|
||||||
* backend api module: "route"
|
* 后端 API 模块:"route"
|
||||||
*/
|
*/
|
||||||
namespace Route {
|
namespace Route {
|
||||||
type ElegantConstRoute = import('@elegant-router/types').ElegantConstRoute;
|
type ElegantConstRoute = import('@elegant-router/types').ElegantConstRoute;
|
||||||
|
|
||||||
|
/** 菜单路由 */
|
||||||
interface MenuRoute extends ElegantConstRoute {
|
interface MenuRoute extends ElegantConstRoute {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 用户路由 */
|
||||||
interface UserRoute {
|
interface UserRoute {
|
||||||
routes: MenuRoute[];
|
routes: MenuRoute[];
|
||||||
home: import('@elegant-router/types').LastLevelRouteKey;
|
home: import('@elegant-router/types').LastLevelRouteKey;
|
||||||
|
204
src/typings/app.d.ts
vendored
204
src/typings/app.d.ts
vendored
@ -1,121 +1,121 @@
|
|||||||
/** The global namespace for the app */
|
/** 应用全局命名空间 */
|
||||||
declare namespace App {
|
declare namespace App {
|
||||||
/** Theme namespace */
|
/** 主题命名空间 */
|
||||||
namespace Theme {
|
namespace Theme {
|
||||||
type ColorPaletteNumber = import('@sa/color').ColorPaletteNumber;
|
type ColorPaletteNumber = import('@sa/color').ColorPaletteNumber;
|
||||||
|
|
||||||
/** Theme setting */
|
/** 主题设置 */
|
||||||
interface ThemeSetting {
|
interface ThemeSetting {
|
||||||
/** Theme scheme */
|
/** 主题方案 */
|
||||||
themeScheme: UnionKey.ThemeScheme;
|
themeScheme: UnionKey.ThemeScheme;
|
||||||
/** grayscale mode */
|
/** 灰度模式 */
|
||||||
grayscale: boolean;
|
grayscale: boolean;
|
||||||
/** colour weakness mode */
|
/** 色弱模式 */
|
||||||
colourWeakness: boolean;
|
colourWeakness: boolean;
|
||||||
/** Whether to recommend color */
|
/** 是否推荐配色 */
|
||||||
recommendColor: boolean;
|
recommendColor: boolean;
|
||||||
/** Theme color */
|
/** 主题色 */
|
||||||
themeColor: string;
|
themeColor: string;
|
||||||
/** Other color */
|
/** 其他颜色 */
|
||||||
otherColor: OtherColor;
|
otherColor: OtherColor;
|
||||||
/** Whether info color is followed by the primary color */
|
/** info颜色是否跟随主色 */
|
||||||
isInfoFollowPrimary: boolean;
|
isInfoFollowPrimary: boolean;
|
||||||
/** Reset cache strategy */
|
/** 重置缓存策略 */
|
||||||
resetCacheStrategy: UnionKey.ResetCacheStrategy;
|
resetCacheStrategy: UnionKey.ResetCacheStrategy;
|
||||||
/** Layout */
|
/** 布局 */
|
||||||
layout: {
|
layout: {
|
||||||
/** Layout mode */
|
/** 布局模式 */
|
||||||
mode: UnionKey.ThemeLayoutMode;
|
mode: UnionKey.ThemeLayoutMode;
|
||||||
/** Scroll mode */
|
/** 滚动模式 */
|
||||||
scrollMode: UnionKey.ThemeScrollMode;
|
scrollMode: UnionKey.ThemeScrollMode;
|
||||||
/**
|
/**
|
||||||
* Whether to reverse the horizontal mix
|
* 是否反转横向混合
|
||||||
*
|
*
|
||||||
* if true, the vertical child level menus in left and horizontal first level menus in top
|
* 如果为 true,左侧为垂直子菜单,顶部为横向一级菜单
|
||||||
*/
|
*/
|
||||||
reverseHorizontalMix: boolean;
|
reverseHorizontalMix: boolean;
|
||||||
};
|
};
|
||||||
/** Page */
|
/** 页面 */
|
||||||
page: {
|
page: {
|
||||||
/** Whether to show the page transition */
|
/** 是否显示页面切换动画 */
|
||||||
animate: boolean;
|
animate: boolean;
|
||||||
/** Page animate mode */
|
/** 页面动画模式 */
|
||||||
animateMode: UnionKey.ThemePageAnimateMode;
|
animateMode: UnionKey.ThemePageAnimateMode;
|
||||||
};
|
};
|
||||||
/** Header */
|
/** 顶栏 */
|
||||||
header: {
|
header: {
|
||||||
/** Header height */
|
/** 顶栏高度 */
|
||||||
height: number;
|
height: number;
|
||||||
/** Header breadcrumb */
|
/** 顶栏面包屑 */
|
||||||
breadcrumb: {
|
breadcrumb: {
|
||||||
/** Whether to show the breadcrumb */
|
/** 是否显示面包屑 */
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
/** Whether to show the breadcrumb icon */
|
/** 是否显示面包屑图标 */
|
||||||
showIcon: boolean;
|
showIcon: boolean;
|
||||||
};
|
};
|
||||||
/** Multilingual */
|
/** 多语言 */
|
||||||
multilingual: {
|
multilingual: {
|
||||||
/** Whether to show the multilingual */
|
/** 是否显示多语言 */
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
};
|
};
|
||||||
globalSearch: {
|
globalSearch: {
|
||||||
/** Whether to show the GlobalSearch */
|
/** 是否显示全局搜索 */
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
/** Tab */
|
/** 标签栏 */
|
||||||
tab: {
|
tab: {
|
||||||
/** Whether to show the tab */
|
/** 是否显示标签栏 */
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
/**
|
/**
|
||||||
* Whether to cache the tab
|
* 是否缓存标签页
|
||||||
*
|
*
|
||||||
* If cache, the tabs will get from the local storage when the page is refreshed
|
* 如果缓存,刷新页面时标签页会从本地存储中获取
|
||||||
*/
|
*/
|
||||||
cache: boolean;
|
cache: boolean;
|
||||||
/** Tab height */
|
/** 标签栏高度 */
|
||||||
height: number;
|
height: number;
|
||||||
/** Tab mode */
|
/** 标签栏模式 */
|
||||||
mode: UnionKey.ThemeTabMode;
|
mode: UnionKey.ThemeTabMode;
|
||||||
};
|
};
|
||||||
/** Fixed header and tab */
|
/** 固定头部和标签栏 */
|
||||||
fixedHeaderAndTab: boolean;
|
fixedHeaderAndTab: boolean;
|
||||||
/** Sider */
|
/** 侧边栏 */
|
||||||
sider: {
|
sider: {
|
||||||
/** Inverted sider */
|
/** 侧边栏反色 */
|
||||||
inverted: boolean;
|
inverted: boolean;
|
||||||
/** Sider width */
|
/** 侧边栏宽度 */
|
||||||
width: number;
|
width: number;
|
||||||
/** Collapsed sider width */
|
/** 侧边栏收起宽度 */
|
||||||
collapsedWidth: number;
|
collapsedWidth: number;
|
||||||
/** Sider width when the layout is 'vertical-mix' or 'horizontal-mix' */
|
/** 混合布局下侧边栏宽度 */
|
||||||
mixWidth: number;
|
mixWidth: number;
|
||||||
/** Collapsed sider width when the layout is 'vertical-mix' or 'horizontal-mix' */
|
/** 混合布局下收起宽度 */
|
||||||
mixCollapsedWidth: number;
|
mixCollapsedWidth: number;
|
||||||
/** Child menu width when the layout is 'vertical-mix' or 'horizontal-mix' */
|
/** 混合布局下子菜单宽度 */
|
||||||
mixChildMenuWidth: number;
|
mixChildMenuWidth: number;
|
||||||
};
|
};
|
||||||
/** Footer */
|
/** 页脚 */
|
||||||
footer: {
|
footer: {
|
||||||
/** Whether to show the footer */
|
/** 是否显示页脚 */
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
/** Whether fixed the footer */
|
/** 是否固定页脚 */
|
||||||
fixed: boolean;
|
fixed: boolean;
|
||||||
/** Footer height */
|
/** 页脚高度 */
|
||||||
height: number;
|
height: number;
|
||||||
/** Whether float the footer to the right when the layout is 'horizontal-mix' */
|
/** 混合布局下页脚是否右浮动 */
|
||||||
right: boolean;
|
right: boolean;
|
||||||
};
|
};
|
||||||
/** Watermark */
|
/** 水印 */
|
||||||
watermark: {
|
watermark: {
|
||||||
/** Whether to show the watermark */
|
/** 是否显示水印 */
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
/** Watermark text */
|
/** 水印文本 */
|
||||||
text: string;
|
text: string;
|
||||||
/** Whether to use user name as watermark text */
|
/** 是否使用用户名作为水印文本 */
|
||||||
enableUserName: boolean;
|
enableUserName: boolean;
|
||||||
};
|
};
|
||||||
/** define some theme settings tokens, will transform to css variables */
|
/** 定义部分主题 token,会转换为 css 变量 */
|
||||||
tokens: {
|
tokens: {
|
||||||
light: ThemeSettingToken;
|
light: ThemeSettingToken;
|
||||||
dark?: {
|
dark?: {
|
||||||
@ -144,7 +144,7 @@ declare namespace App {
|
|||||||
type BaseToken = Record<string, Record<string, string>>;
|
type BaseToken = Record<string, Record<string, string>>;
|
||||||
|
|
||||||
interface ThemeSettingTokenColor {
|
interface ThemeSettingTokenColor {
|
||||||
/** the progress bar color, if not set, will use the primary color */
|
/** 进度条颜色,未设置时使用主色 */
|
||||||
nprogress?: string;
|
nprogress?: string;
|
||||||
container: string;
|
container: string;
|
||||||
layout: string;
|
layout: string;
|
||||||
@ -165,14 +165,14 @@ declare namespace App {
|
|||||||
|
|
||||||
type ThemeTokenColor = ThemePaletteColor & ThemeSettingTokenColor;
|
type ThemeTokenColor = ThemePaletteColor & ThemeSettingTokenColor;
|
||||||
|
|
||||||
/** Theme token CSS variables */
|
/** 主题 token CSS 变量 */
|
||||||
type ThemeTokenCSSVars = {
|
type ThemeTokenCSSVars = {
|
||||||
colors: ThemeTokenColor & { [key: string]: string };
|
colors: ThemeTokenColor & { [key: string]: string };
|
||||||
boxShadow: ThemeSettingTokenBoxShadow & { [key: string]: string };
|
boxShadow: ThemeSettingTokenBoxShadow & { [key: string]: string };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Global namespace */
|
/** 全局命名空间 */
|
||||||
namespace Global {
|
namespace Global {
|
||||||
type VNode = import('vue').VNode;
|
type VNode = import('vue').VNode;
|
||||||
type RouteLocationNormalizedLoaded = import('vue-router').RouteLocationNormalizedLoaded;
|
type RouteLocationNormalizedLoaded = import('vue-router').RouteLocationNormalizedLoaded;
|
||||||
@ -181,41 +181,41 @@ declare namespace App {
|
|||||||
type RoutePath = import('@elegant-router/types').RoutePath;
|
type RoutePath = import('@elegant-router/types').RoutePath;
|
||||||
type LastLevelRouteKey = import('@elegant-router/types').LastLevelRouteKey;
|
type LastLevelRouteKey = import('@elegant-router/types').LastLevelRouteKey;
|
||||||
|
|
||||||
/** The router push options */
|
/** 路由跳转参数 */
|
||||||
type RouterPushOptions = {
|
type RouterPushOptions = {
|
||||||
query?: Record<string, string>;
|
query?: Record<string, string>;
|
||||||
params?: Record<string, string>;
|
params?: Record<string, string>;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The global header props */
|
/** 全局头部属性 */
|
||||||
interface HeaderProps {
|
interface HeaderProps {
|
||||||
/** Whether to show the logo */
|
/** 是否显示 logo */
|
||||||
showLogo?: boolean;
|
showLogo?: boolean;
|
||||||
/** Whether to show the menu toggler */
|
/** 是否显示菜单切换按钮 */
|
||||||
showMenuToggler?: boolean;
|
showMenuToggler?: boolean;
|
||||||
/** Whether to show the menu */
|
/** 是否显示菜单 */
|
||||||
showMenu?: boolean;
|
showMenu?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The global menu */
|
/** 全局菜单 */
|
||||||
type Menu = {
|
type Menu = {
|
||||||
/**
|
/**
|
||||||
* The menu key
|
* 菜单 key
|
||||||
*
|
*
|
||||||
* Equal to the route key
|
* 等同于路由 key
|
||||||
*/
|
*/
|
||||||
key: string;
|
key: string;
|
||||||
/** The menu label */
|
/** 菜单名称 */
|
||||||
label: string;
|
label: string;
|
||||||
/** The menu i18n key */
|
/** 菜单 i18n key */
|
||||||
i18nKey?: I18n.I18nKey | null;
|
i18nKey?: I18n.I18nKey | null;
|
||||||
/** The route key */
|
/** 路由 key */
|
||||||
routeKey: RouteKey;
|
routeKey: RouteKey;
|
||||||
/** The route path */
|
/** 路由 path */
|
||||||
routePath: RoutePath;
|
routePath: RoutePath;
|
||||||
/** The menu icon */
|
/** 菜单图标 */
|
||||||
icon?: () => VNode;
|
icon?: () => VNode;
|
||||||
/** The menu children */
|
/** 子菜单 */
|
||||||
children?: Menu[];
|
children?: Menu[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -223,63 +223,63 @@ declare namespace App {
|
|||||||
options?: Breadcrumb[];
|
options?: Breadcrumb[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Tab route */
|
/** 标签页路由 */
|
||||||
type TabRoute = Pick<RouteLocationNormalizedLoaded, 'name' | 'path' | 'meta'> &
|
type TabRoute = Pick<RouteLocationNormalizedLoaded, 'name' | 'path' | 'meta'> &
|
||||||
Partial<Pick<RouteLocationNormalizedLoaded, 'fullPath' | 'query' | 'matched'>>;
|
Partial<Pick<RouteLocationNormalizedLoaded, 'fullPath' | 'query' | 'matched'>>;
|
||||||
|
|
||||||
/** The global tab */
|
/** 全局标签页 */
|
||||||
type Tab = {
|
type Tab = {
|
||||||
/** The tab id */
|
/** 标签页 id */
|
||||||
id: string;
|
id: string;
|
||||||
/** The tab label */
|
/** 标签页名称 */
|
||||||
label: string;
|
label: string;
|
||||||
/**
|
/**
|
||||||
* The new tab label
|
* 新标签页名称
|
||||||
*
|
*
|
||||||
* If set, the tab label will be replaced by this value
|
* 设置后标签页名称会被替换为该值
|
||||||
*/
|
*/
|
||||||
newLabel?: string;
|
newLabel?: string;
|
||||||
/**
|
/**
|
||||||
* The old tab label
|
* 旧标签页名称
|
||||||
*
|
*
|
||||||
* when reset the tab label, the tab label will be replaced by this value
|
* 重置标签页名称时会被替换为该值
|
||||||
*/
|
*/
|
||||||
oldLabel?: string;
|
oldLabel?: string;
|
||||||
/** The tab route key */
|
/** 标签页路由 key */
|
||||||
routeKey: LastLevelRouteKey;
|
routeKey: LastLevelRouteKey;
|
||||||
/** The tab route path */
|
/** 标签页路由 path */
|
||||||
routePath: RouteMap[LastLevelRouteKey];
|
routePath: RouteMap[LastLevelRouteKey];
|
||||||
/** The tab route full path */
|
/** 标签页完整路径 */
|
||||||
fullPath: string;
|
fullPath: string;
|
||||||
/** The tab fixed index */
|
/** 固定标签页索引 */
|
||||||
fixedIndex?: number | null;
|
fixedIndex?: number | null;
|
||||||
/**
|
/**
|
||||||
* Tab icon
|
* 标签页图标
|
||||||
*
|
*
|
||||||
* Iconify icon
|
* Iconify 图标
|
||||||
*/
|
*/
|
||||||
icon?: string;
|
icon?: string;
|
||||||
/**
|
/**
|
||||||
* Tab local icon
|
* 标签页本地图标
|
||||||
*
|
*
|
||||||
* Local icon
|
* 本地图标
|
||||||
*/
|
*/
|
||||||
localIcon?: string;
|
localIcon?: string;
|
||||||
/** I18n key */
|
/** I18n key */
|
||||||
i18nKey?: I18n.I18nKey | null;
|
i18nKey?: I18n.I18nKey | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Form rule */
|
/** 表单校验规则 */
|
||||||
type FormRule = import('naive-ui').FormItemRule;
|
type FormRule = import('naive-ui').FormItemRule;
|
||||||
|
|
||||||
/** The global dropdown key */
|
/** 全局下拉菜单 key */
|
||||||
type DropdownKey = 'closeCurrent' | 'closeOther' | 'closeLeft' | 'closeRight' | 'closeAll';
|
type DropdownKey = 'closeCurrent' | 'closeOther' | 'closeLeft' | 'closeRight' | 'closeAll';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* I18n namespace
|
* I18n 命名空间
|
||||||
*
|
*
|
||||||
* Locales type
|
* 多语言类型
|
||||||
*/
|
*/
|
||||||
namespace I18n {
|
namespace I18n {
|
||||||
type RouteKey = import('@elegant-router/types').RouteKey;
|
type RouteKey = import('@elegant-router/types').RouteKey;
|
||||||
@ -549,15 +549,15 @@ declare namespace App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Service namespace */
|
/** 服务命名空间 */
|
||||||
namespace Service {
|
namespace Service {
|
||||||
/** Other baseURL key */
|
/** 其他 baseURL key */
|
||||||
type OtherBaseURLKey = 'demo';
|
type OtherBaseURLKey = 'demo';
|
||||||
|
|
||||||
interface ServiceConfigItem {
|
interface ServiceConfigItem {
|
||||||
/** The backend service base url */
|
/** 后端服务基础地址 */
|
||||||
baseURL: string;
|
baseURL: string;
|
||||||
/** The proxy pattern of the backend service base url */
|
/** 后端服务基础地址的代理前缀 */
|
||||||
proxyPattern: string;
|
proxyPattern: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,9 +565,9 @@ declare namespace App {
|
|||||||
key: OtherBaseURLKey;
|
key: OtherBaseURLKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The backend service config */
|
/** 后端服务配置 */
|
||||||
interface ServiceConfig extends ServiceConfigItem {
|
interface ServiceConfig extends ServiceConfigItem {
|
||||||
/** Other backend service config */
|
/** 其他后端服务配置 */
|
||||||
other: OtherServiceConfigItem[];
|
other: OtherServiceConfigItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,23 +575,23 @@ declare namespace App {
|
|||||||
other: Record<OtherBaseURLKey, string>;
|
other: Record<OtherBaseURLKey, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The backend service response data */
|
/** 后端服务响应数据 */
|
||||||
type Response<T = unknown> = {
|
type Response<T = unknown> = {
|
||||||
/** The backend service response code */
|
/** 响应码 */
|
||||||
code: string;
|
code: string;
|
||||||
/** The backend service response message */
|
/** 响应信息 */
|
||||||
msg: string;
|
msg: string;
|
||||||
/** The backend service response data */
|
/** 响应数据 */
|
||||||
data: T;
|
data: T;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The demo backend service response data */
|
/** demo 后端服务响应数据 */
|
||||||
type DemoResponse<T = unknown> = {
|
type DemoResponse<T = unknown> = {
|
||||||
/** The backend service response code */
|
/** 响应码 */
|
||||||
status: string;
|
status: string;
|
||||||
/** The backend service response message */
|
/** 响应信息 */
|
||||||
message: string;
|
message: string;
|
||||||
/** The backend service response data */
|
/** 响应数据 */
|
||||||
result: T;
|
result: T;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
3
src/typings/elegant-router.d.ts
vendored
3
src/typings/elegant-router.d.ts
vendored
@ -20,6 +20,7 @@ declare module "@elegant-router/types" {
|
|||||||
"403": "/403";
|
"403": "/403";
|
||||||
"404": "/404";
|
"404": "/404";
|
||||||
"500": "/500";
|
"500": "/500";
|
||||||
|
"cesium": "/cesium";
|
||||||
"home": "/home";
|
"home": "/home";
|
||||||
"iframe-page": "/iframe-page/:url";
|
"iframe-page": "/iframe-page/:url";
|
||||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
|
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
|
||||||
@ -57,6 +58,7 @@ declare module "@elegant-router/types" {
|
|||||||
| "403"
|
| "403"
|
||||||
| "404"
|
| "404"
|
||||||
| "500"
|
| "500"
|
||||||
|
| "cesium"
|
||||||
| "home"
|
| "home"
|
||||||
| "iframe-page"
|
| "iframe-page"
|
||||||
| "login"
|
| "login"
|
||||||
@ -81,6 +83,7 @@ declare module "@elegant-router/types" {
|
|||||||
| "500"
|
| "500"
|
||||||
| "iframe-page"
|
| "iframe-page"
|
||||||
| "login"
|
| "login"
|
||||||
|
| "cesium"
|
||||||
| "home"
|
| "home"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
85
src/typings/vite-env.d.ts
vendored
85
src/typings/vite-env.d.ts
vendored
@ -1,114 +1,113 @@
|
|||||||
/**
|
/**
|
||||||
* Namespace Env
|
* 命名空间 Env
|
||||||
*
|
*
|
||||||
* It is used to declare the type of the import.meta object
|
* 用于声明 import.meta 对象的类型
|
||||||
*/
|
*/
|
||||||
declare namespace Env {
|
declare namespace Env {
|
||||||
/** The router history mode */
|
/** 路由历史模式 */
|
||||||
type RouterHistoryMode = 'hash' | 'history' | 'memory';
|
type RouterHistoryMode = 'hash' | 'history' | 'memory';
|
||||||
|
|
||||||
/** Interface for import.meta */
|
/** import.meta 的接口 */
|
||||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||||
interface ImportMeta extends ImportMetaEnv {
|
interface ImportMeta extends ImportMetaEnv {
|
||||||
/** The base url of the application */
|
/** 应用的基础路径 */
|
||||||
readonly VITE_BASE_URL: string;
|
readonly VITE_BASE_URL: string;
|
||||||
/** The title of the application */
|
/** 应用标题 */
|
||||||
readonly VITE_APP_TITLE: string;
|
readonly VITE_APP_TITLE: string;
|
||||||
/** The description of the application */
|
/** 应用描述 */
|
||||||
readonly VITE_APP_DESC: string;
|
readonly VITE_APP_DESC: string;
|
||||||
/** The router history mode */
|
/** 路由历史模式 */
|
||||||
readonly VITE_ROUTER_HISTORY_MODE?: RouterHistoryMode;
|
readonly VITE_ROUTER_HISTORY_MODE?: RouterHistoryMode;
|
||||||
/** The prefix of the iconify icon */
|
/** iconify 图标前缀 */
|
||||||
readonly VITE_ICON_PREFIX: 'icon';
|
readonly VITE_ICON_PREFIX: 'icon';
|
||||||
/**
|
/**
|
||||||
* The prefix of the local icon
|
* 本地图标前缀
|
||||||
*
|
*
|
||||||
* This prefix is start with the icon prefix
|
* 该前缀以 icon 前缀开头
|
||||||
*/
|
*/
|
||||||
readonly VITE_ICON_LOCAL_PREFIX: 'icon-local';
|
readonly VITE_ICON_LOCAL_PREFIX: 'icon-local';
|
||||||
/** backend service base url */
|
/** 后端服务基础地址 */
|
||||||
readonly VITE_SERVICE_BASE_URL: string;
|
readonly VITE_SERVICE_BASE_URL: string;
|
||||||
/**
|
/**
|
||||||
* success code of backend service
|
* 后端服务成功状态码
|
||||||
*
|
*
|
||||||
* when the code is received, the request is successful
|
* 收到该状态码时,请求成功
|
||||||
*/
|
*/
|
||||||
readonly VITE_SERVICE_SUCCESS_CODE: string;
|
readonly VITE_SERVICE_SUCCESS_CODE: string;
|
||||||
/**
|
/**
|
||||||
* logout codes of backend service
|
* 后端服务登出状态码
|
||||||
*
|
*
|
||||||
* when the code is received, the user will be logged out and redirected to login page
|
* 收到该状态码时,用户会被登出并跳转到登录页
|
||||||
*
|
*
|
||||||
* use "," to separate multiple codes
|
* 多个状态码用 "," 分隔
|
||||||
*/
|
*/
|
||||||
readonly VITE_SERVICE_LOGOUT_CODES: string;
|
readonly VITE_SERVICE_LOGOUT_CODES: string;
|
||||||
/**
|
/**
|
||||||
* modal logout codes of backend service
|
* 后端服务弹窗登出状态码
|
||||||
*
|
*
|
||||||
* when the code is received, the user will be logged out by displaying a modal
|
* 收到该状态码时,会弹窗提示并登出
|
||||||
*
|
*
|
||||||
* use "," to separate multiple codes
|
* 多个状态码用 "," 分隔
|
||||||
*/
|
*/
|
||||||
readonly VITE_SERVICE_MODAL_LOGOUT_CODES: string;
|
readonly VITE_SERVICE_MODAL_LOGOUT_CODES: string;
|
||||||
/**
|
/**
|
||||||
* token expired codes of backend service
|
* 后端服务 token 过期状态码
|
||||||
*
|
*
|
||||||
* when the code is received, it will refresh the token and resend the request
|
* 收到该状态码时,会刷新 token 并重新发送请求
|
||||||
*
|
*
|
||||||
* use "," to separate multiple codes
|
* 多个状态码用 "," 分隔
|
||||||
*/
|
*/
|
||||||
readonly VITE_SERVICE_EXPIRED_TOKEN_CODES: string;
|
readonly VITE_SERVICE_EXPIRED_TOKEN_CODES: string;
|
||||||
/** when the route mode is static, the defined super role */
|
/** 路由模式为 static 时定义的超级角色 */
|
||||||
readonly VITE_STATIC_SUPER_ROLE: string;
|
readonly VITE_STATIC_SUPER_ROLE: string;
|
||||||
/**
|
/**
|
||||||
* other backend service base url
|
* 其他后端服务基础地址
|
||||||
*
|
*
|
||||||
* the value is a json
|
* 值为 json 格式
|
||||||
*/
|
*/
|
||||||
readonly VITE_OTHER_SERVICE_BASE_URL: string;
|
readonly VITE_OTHER_SERVICE_BASE_URL: string;
|
||||||
/**
|
/**
|
||||||
* Whether to enable the http proxy
|
* 是否启用 http 代理
|
||||||
*
|
*
|
||||||
* Only valid in the development environment
|
* 仅在开发环境下有效
|
||||||
*/
|
*/
|
||||||
readonly VITE_HTTP_PROXY?: CommonType.YesOrNo;
|
readonly VITE_HTTP_PROXY?: CommonType.YesOrNo;
|
||||||
/**
|
/**
|
||||||
* The auth route mode
|
* 权限路由模式
|
||||||
*
|
*
|
||||||
* - Static: the auth routes is generated in front-end
|
* - static:前端生成权限路由
|
||||||
* - Dynamic: the auth routes is generated in back-end
|
* - dynamic:后端生成权限路由
|
||||||
*/
|
*/
|
||||||
readonly VITE_AUTH_ROUTE_MODE: 'static' | 'dynamic';
|
readonly VITE_AUTH_ROUTE_MODE: 'static' | 'dynamic';
|
||||||
/**
|
/**
|
||||||
* The home route key
|
* 首页路由 key
|
||||||
*
|
*
|
||||||
* It only has effect when the auth route mode is static, if the route mode is dynamic, the home route key is
|
* 仅在权限路由模式为 static 时生效,dynamic 时由后端定义
|
||||||
* defined in the back-end
|
|
||||||
*/
|
*/
|
||||||
readonly VITE_ROUTE_HOME: import('@elegant-router/types').LastLevelRouteKey;
|
readonly VITE_ROUTE_HOME: import('@elegant-router/types').LastLevelRouteKey;
|
||||||
/**
|
/**
|
||||||
* Default menu icon if menu icon is not set
|
* 默认菜单图标(未设置菜单图标时使用)
|
||||||
*
|
*
|
||||||
* Iconify icon name
|
* Iconify 图标名
|
||||||
*/
|
*/
|
||||||
readonly VITE_MENU_ICON: string;
|
readonly VITE_MENU_ICON: string;
|
||||||
/** Whether to build with sourcemap */
|
/** 是否构建 sourcemap */
|
||||||
readonly VITE_SOURCE_MAP?: CommonType.YesOrNo;
|
readonly VITE_SOURCE_MAP?: CommonType.YesOrNo;
|
||||||
/**
|
/**
|
||||||
* Iconify api provider url
|
* Iconify API 提供者地址
|
||||||
*
|
*
|
||||||
* If the project is deployed in intranet, you can set the api provider url to the local iconify server
|
* 如果项目部署在内网,可设置为本地 iconify 服务地址
|
||||||
*
|
*
|
||||||
* @link https://docs.iconify.design/api/providers.html
|
* @link https://docs.iconify.design/api/providers.html
|
||||||
*/
|
*/
|
||||||
readonly VITE_ICONIFY_URL?: string;
|
readonly VITE_ICONIFY_URL?: string;
|
||||||
/** Used to differentiate storage across different domains */
|
/** 用于区分不同域名下的存储 */
|
||||||
readonly VITE_STORAGE_PREFIX?: string;
|
readonly VITE_STORAGE_PREFIX?: string;
|
||||||
/** Whether to automatically detect updates after configuring application packaging */
|
/** 配置应用打包后是否自动检测更新 */
|
||||||
readonly VITE_AUTOMATICALLY_DETECT_UPDATE?: CommonType.YesOrNo;
|
readonly VITE_AUTOMATICALLY_DETECT_UPDATE?: CommonType.YesOrNo;
|
||||||
/** show proxy url log in terminal */
|
/** 是否在终端显示代理地址日志 */
|
||||||
readonly VITE_PROXY_LOG?: CommonType.YesOrNo;
|
readonly VITE_PROXY_LOG?: CommonType.YesOrNo;
|
||||||
/** The launch editor */
|
/** 启动的编辑器 */
|
||||||
readonly VITE_DEVTOOLS_LAUNCH_EDITOR?: import('vite-plugin-vue-devtools').VitePluginVueDevToolsOptions['launchEditor'];
|
readonly VITE_DEVTOOLS_LAUNCH_EDITOR?: import('vite-plugin-vue-devtools').VitePluginVueDevToolsOptions['launchEditor'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import json5 from 'json5';
|
import json5 from 'json5';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create service config by current env
|
* 根据当前环境创建服务配置
|
||||||
*
|
*
|
||||||
* @param env The current env
|
* @param env 当前环境变量
|
||||||
*/
|
*/
|
||||||
export function createServiceConfig(env: Env.ImportMeta) {
|
export function createServiceConfig(env: Env.ImportMeta) {
|
||||||
const { VITE_SERVICE_BASE_URL, VITE_OTHER_SERVICE_BASE_URL } = env;
|
const { VITE_SERVICE_BASE_URL, VITE_OTHER_SERVICE_BASE_URL } = env;
|
||||||
@ -13,7 +13,7 @@ export function createServiceConfig(env: Env.ImportMeta) {
|
|||||||
other = json5.parse(VITE_OTHER_SERVICE_BASE_URL);
|
other = json5.parse(VITE_OTHER_SERVICE_BASE_URL);
|
||||||
} catch {
|
} catch {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error('VITE_OTHER_SERVICE_BASE_URL is not a valid json5 string');
|
console.error('VITE_OTHER_SERVICE_BASE_URL 不是有效的 json5 字符串');
|
||||||
}
|
}
|
||||||
|
|
||||||
const httpConfig: App.Service.SimpleServiceConfig = {
|
const httpConfig: App.Service.SimpleServiceConfig = {
|
||||||
@ -41,10 +41,10 @@ export function createServiceConfig(env: Env.ImportMeta) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get backend service base url
|
* 获取后端服务基础地址
|
||||||
*
|
*
|
||||||
* @param env - the current env
|
* @param env 当前环境变量
|
||||||
* @param isProxy - if use proxy
|
* @param isProxy 是否使用代理
|
||||||
*/
|
*/
|
||||||
export function getServiceBaseURL(env: Env.ImportMeta, isProxy: boolean) {
|
export function getServiceBaseURL(env: Env.ImportMeta, isProxy: boolean) {
|
||||||
const { baseURL, other } = createServiceConfig(env);
|
const { baseURL, other } = createServiceConfig(env);
|
||||||
@ -62,9 +62,9 @@ export function getServiceBaseURL(env: Env.ImportMeta, isProxy: boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get proxy pattern of backend service base url
|
* 获取后端服务基础地址的代理前缀
|
||||||
*
|
*
|
||||||
* @param key If not set, will use the default key
|
* @param key 如果未设置,则使用默认 key
|
||||||
*/
|
*/
|
||||||
function createProxyPattern(key?: App.Service.OtherBaseURLKey) {
|
function createProxyPattern(key?: App.Service.OtherBaseURLKey) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
|
19
src/views/cesium/index.vue
Normal file
19
src/views/cesium/index.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
这是cesium页面
|
||||||
|
<div class="cesium-container">
|
||||||
|
<div id="cesiumContainer"></div>
|
||||||
|
</div>
|
||||||
|
<p>请在控制台查看Cesium相关信息</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#cesiumContainer {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue
Block a user