feat(utils): 重构路由生成逻辑

- 移除 autoRoutes.js 文件,改为使用 apps.js 存储路由信息
- 新增 createRoutes 函数,用于动态生成应用路由
- 更新 build.js,增加路由生成步骤
- 修改 router.js,使用新的路由配置
- 更新 .gitignore,忽略新的 apps.js 文件
This commit is contained in:
aixianling
2024-12-17 09:34:57 +08:00
parent c8d75ab72a
commit 536f579523
7 changed files with 97 additions and 116 deletions

1
.gitignore vendored
View File

@@ -30,3 +30,4 @@ yarn-error.log*
/examples/router/apps.js
/src/apps/
/src/config.json
/src/utils/apps.js

View File

@@ -1,5 +1,6 @@
const axios = require('axios')
const {fsExtra, copyFiles} = require("./tools");
const {fsExtra, copyFiles, findApp, chalkTag, fs} = require("./tools");
const compiler = require('vue-template-compiler')
const getBuildConfig = id => {
axios.post('http://192.168.1.87:12525/node/custom/detail', null, {params: {id}}).then(res => {
if (res?.data) {
@@ -9,6 +10,60 @@ const getBuildConfig = id => {
}
})
}
const getAppInfo = (file, apps) => {
if (/[\\\/](App[A-Z][^\\\/]+)\.vue$/g.test(file)) {
const name = file.replace(/.+[\\\/](App[^\\\/]+)\.vue$/, '$1'),
source = fs.readFileSync(file).toString(),
parsed = compiler.parseComponent(source),
script = parsed.script?.content || "",
label = script.match(/label:[^,]+/)?.[0]?.replace(/.+["']([^"']+).+/, '$1')
const paths = file.split(/[\\\/]/)
apps.push({
id: file.replace(/\.vue$/, '').replace(/[\\\/]/g, '_'),
label: label || name,
path: `/${file.replace(/\.vue$/, '').replace(/[\\\/]/g, '/')}`,
workspace: paths.at(0),
esm: file.replace(/[\\\/]/g, '/').substring(4),
name
})
}
}
/**
* 根据配置生成应用路由
* @param {Object} config - 配置对象,用于定制化路由生成过程
* @returns {Promise} - 返回一个Promise对象表示路由生成完成
*/
const createRoutes = (config = {}) => {
// 初始化路由数组
const routes = []
// 获取签到页面的路径,如果未指定,则使用默认路径
let signPage = '../views/sign'
if (config.extra?.signPage) {
const sign = config.extra.signPage
signPage = `../apps/custom/${sign}/${sign}`
}
// 查找并处理所有应用,将它们的信息添加到路由中
return findApp("src/apps", app => getAppInfo(app, routes)).then(() => {
// 生成并输出apps.js文件定义所有应用的路由
fsExtra.outputFile('src/utils/apps.js', `export default [
{path: "/login", name: "登录", component: () => import('${signPage}')},
{path: '/dv', name: '数据大屏入口', component: () => import('../views/dvIndex')},
{path: '/v', name: 'Home', component: () => import('../views/home'), children: [
${routes.map(e => {
// 解构每个路由的属性,用于生成路由配置
const {name, label, path, esm} = e
// 生成单个路由配置的字符串表示
return `{name:"${name}",label:"${label}",path:"${path}",component:()=>import("../${esm}")}`
}).join(',\n')}
]},
{path: '/', name: "init"},
]`)
// 扫描完毕使用chalkTag标记任务完成
chalkTag.done("扫描完毕")
})
}
const createPages = (config = {}) => {
fsExtra.emptyDir("src/apps", err => {
@@ -24,13 +79,13 @@ const createPages = (config = {}) => {
copyFiles("src/apps/core", "packages/core"),
copyFiles("src/apps/custom", `project/${customPath}`),
...Object.keys(stdApps).map(e => copyFiles(`src/apps/${e.replace(/^packages[\\\/]/, '')}`, e)),
]).then(() => fsExtra.ensureFile("src/apps/actions.js"))
]).then(() => createRoutes(config)).then(() => fsExtra.ensureFile("src/apps/actions.js"))
}
})
}
const start = () => {
const buildId = process.argv[2] || 'f670cc46-7cf7-4a0f-86ee-3077044c0b17'
const buildId = process.argv[2] || process.env.VUE_APP_OMS_ID || 'f670cc46-7cf7-4a0f-86ee-3077044c0b17'
getBuildConfig(buildId)
}
start()

View File

@@ -1,4 +1,4 @@
import {Message} from 'element-ui'
import { Message } from 'element-ui'
import instance from 'dui/lib/js/request'
let baseURLs = {
@@ -12,6 +12,9 @@ instance.interceptors.request.use(config => {
}
if (process.env.VUE_APP_IS_SIMPLE_SERVER == 1) {
config.url = config.url.replace(/(app|auth|admin)\//, "api/")
if (['xumu'].includes(process.env.VUE_APP_SCOPE)) {
config.url = config.url.replace("/api/", "/")
}
}
return config
}, error => Message.error(error))

View File

@@ -12,7 +12,8 @@
"preview": "node bin/build.js && vue-cli-service serve",
"predev": "node bin/scanApps.js",
"preoms": "dotenv -e .env.oms node bin/scanApps.js",
"prexumu": "dotenv -e .env.xumu node bin/scanApps.js"
"prexumu": "dotenv -e .env.xumu node bin/scanApps.js",
"preview:xumu":"dotenv -e .env.xumu node bin/build.js&& vue-cli-service serve --mode xumu"
},
"dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",

View File

@@ -6,7 +6,6 @@ import utils from './utils';
import vcUI from 'dui/packages';
import appComp from 'dui/dv';
import store from './utils/store';
import autoRoutes from "./utils/autoRoutes";
import extra from "./config.json"
import axios from "./utils/axios";
//备注底座信息,勿删
@@ -19,7 +18,7 @@ Vue.config.productionTip = false;
Vue.prototype.$cdn = "https://cdn.cunwuyun.cn"
Vue.prototype.$request = axios
Object.keys(utils).map((e) => (Vue.prototype[e] = utils[e]));
const loadPage = () => autoRoutes.init().finally(() => new Vue({router, store, render: h => h(App)}).$mount("#app"))
const loadPage = () => new Vue({router, store, render: h => h(App)}).$mount("#app")
let theme = null
store.dispatch('getSystem', extra.sysInfo).then(res => {
theme = JSON.parse(res?.colorScheme || null)

View File

@@ -1,107 +0,0 @@
import {waiting} from "./index";
import router from "./router";
import store from "./store";
import {Message} from "element-ui";
import Vue from "vue";
import extra from "../config.json"
let {state: {user}, commit, dispatch} = store
const signOut = () => commit("signOut"),
getUserInfo = () => dispatch("getUserInfo"),
existRoute = route => {
return router.getRoutes()?.find(e => e.name == route?.name || e.path == route?.path)
},
goto = (route, next) => {
const exist = !!existRoute(route)
return exist ? route.name ? next() : router.replace(route) :
!route.name && route.path == "/" ? router.replace({name: "Home"}).catch(() => 0) :
Message.error("无法找到路由,请联系系统管理员!")
}
const loadApps = () => {
//新App的自动化格式
waiting.init({innerHTML: '应用加载中..'})
let apps = require.context('../apps', true, /\.(\/.+)\/App[A-Z][^\/]+\.vue$/, "lazy")
return Promise.all(apps.keys().map(path => apps(path).then(file => {
if (file.default) {
let {name} = file.default
waiting.setContent(`加载${name}...`)
Vue.component(name, file.default)
} else return 0
}))).then(() => {
waiting.setContent(`正在进入系统...`)
setTimeout(() => waiting.close(), 1000)
})
}
const addHome = homePage => {
const component = extra?.homePage || homePage.path
if (extra?.homePage && Vue.component(component)) {
homePage = {...homePage, path: component, component: () => import('../views/mainEntry'), meta: component}
}
router.addRoute('Home', homePage)
router.options.routes[2].children.unshift(homePage)
commit("setHomePage", {
...homePage,
label: homePage.name,
id: `/v/${component}`,
isMenu: 1,
route: homePage.name,
component,
path: component,
})
}
const generateRoutes = (to, from, next) => {
if (router.options.routes[2].children.length > 0) {
goto(to, next)
} else {
Promise.all([getUserInfo(), loadApps()]).then(() => {
//初始化默认工作台
let homePage = {name: "工作台", path: "console", style: "iconfont iconNav_Dashborad", component: () => import('../views/console')}
addHome(homePage)
const mods = user.info.menuSet?.filter(e => !!e.component)?.map(e => ({route: e.id, ...e}))
mods?.map(({route: name, path, component}) => {
if (!!Vue.component(component) && path && !existRoute({name})) {
let search = path.split("?")
path = search?.[0] || path
const route = {name, path, component: () => import('../views/mainEntry'), meta: component}
router.addRoute('Home', route)
router.options.routes[2].children.push(route)
}
})
to.name == "Home" ? next({name: homePage.name, replace: true}) : next({...to, replace: true})
}).then(() => commit("setRoutes", router.options.routes[2].children))
}
}
export const routes = [
{path: "/login", name: "登录", component: () => import('../views/sign')},
{path: '/dv', name: '数据大屏入口', component: () => import('../views/dvIndex')},
{path: '/v', name: 'Home', component: () => import('../views/home'), children: []},
{path: '/', name: "init"},
]
export default {
init: () => {
router.beforeEach((to, from, next) => {
console.log('%s=>%s', from.name, to.name)
if (to.hash == "#pddv") {
const {query} = to
dispatch("getToken", {
username: "18971406276",
password: "admin321!"
}).then(() => next({name: "数据大屏入口", query, hash: "#dv"}))
} else if (["数据大屏入口", "登录"].includes(to.name)) {
next()
} else if (to.hash == "#dv") {
//数据大屏进行的独立页面跳转
let {query, hash} = to
next({name: "数据大屏入口", query, hash})
} else if (user.token) {
to.name == "init" ? next({name: "Home"}) : generateRoutes(to, from, next)
} else {
signOut()
}
})
router.onError(err => {
console.error(err)
})
return Promise.resolve()
}
}

View File

@@ -1,10 +1,13 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import {routes} from "./autoRoutes"
import routes from "./apps.js"
import config from "../config.json"
import store from "@/utils/store";
const {state: {user}, commit, dispatch} = store
const signOut = () => commit("signOut")
Vue.use(VueRouter)
export default new VueRouter({
const router = new VueRouter({
base: config.base || '/',
mode: 'history',
hashbang: false,
@@ -17,3 +20,29 @@ export default new VueRouter({
}
}
})
router.beforeEach((to, from, next) => {
console.log('%s=>%s', from.name, to.name)
if (to.hash == "#pddv") {
const {query} = to
dispatch("getToken", {
username: "18971406276",
password: "admin321!"
}).then(() => next({name: "数据大屏入口", query, hash: "#dv"}))
} else if (["数据大屏入口", "登录"].includes(to.name)) {
next()
} else if (to.hash == "#dv") {
//数据大屏进行的独立页面跳转
let {query, hash} = to
next({name: "数据大屏入口", query, hash})
} else if (user.token) {
to.name == "init" ? next({name: "Home"}) : next()
} else {
signOut()
}
})
router.onError(err => {
console.error(err)
})
export default router