feat(utils): 重构路由生成逻辑
- 移除 autoRoutes.js 文件,改为使用 apps.js 存储路由信息 - 新增 createRoutes 函数,用于动态生成应用路由 - 更新 build.js,增加路由生成步骤 - 修改 router.js,使用新的路由配置 - 更新 .gitignore,忽略新的 apps.js 文件
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -30,3 +30,4 @@ yarn-error.log*
|
|||||||
/examples/router/apps.js
|
/examples/router/apps.js
|
||||||
/src/apps/
|
/src/apps/
|
||||||
/src/config.json
|
/src/config.json
|
||||||
|
/src/utils/apps.js
|
||||||
|
|||||||
61
bin/build.js
61
bin/build.js
@@ -1,5 +1,6 @@
|
|||||||
const axios = require('axios')
|
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 => {
|
const getBuildConfig = id => {
|
||||||
axios.post('http://192.168.1.87:12525/node/custom/detail', null, {params: {id}}).then(res => {
|
axios.post('http://192.168.1.87:12525/node/custom/detail', null, {params: {id}}).then(res => {
|
||||||
if (res?.data) {
|
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 = {}) => {
|
const createPages = (config = {}) => {
|
||||||
fsExtra.emptyDir("src/apps", err => {
|
fsExtra.emptyDir("src/apps", err => {
|
||||||
@@ -24,13 +79,13 @@ const createPages = (config = {}) => {
|
|||||||
copyFiles("src/apps/core", "packages/core"),
|
copyFiles("src/apps/core", "packages/core"),
|
||||||
copyFiles("src/apps/custom", `project/${customPath}`),
|
copyFiles("src/apps/custom", `project/${customPath}`),
|
||||||
...Object.keys(stdApps).map(e => copyFiles(`src/apps/${e.replace(/^packages[\\\/]/, '')}`, e)),
|
...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 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)
|
getBuildConfig(buildId)
|
||||||
}
|
}
|
||||||
start()
|
start()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {Message} from 'element-ui'
|
import { Message } from 'element-ui'
|
||||||
import instance from 'dui/lib/js/request'
|
import instance from 'dui/lib/js/request'
|
||||||
|
|
||||||
let baseURLs = {
|
let baseURLs = {
|
||||||
@@ -12,6 +12,9 @@ instance.interceptors.request.use(config => {
|
|||||||
}
|
}
|
||||||
if (process.env.VUE_APP_IS_SIMPLE_SERVER == 1) {
|
if (process.env.VUE_APP_IS_SIMPLE_SERVER == 1) {
|
||||||
config.url = config.url.replace(/(app|auth|admin)\//, "api/")
|
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
|
return config
|
||||||
}, error => Message.error(error))
|
}, error => Message.error(error))
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"preview": "node bin/build.js && vue-cli-service serve",
|
"preview": "node bin/build.js && vue-cli-service serve",
|
||||||
"predev": "node bin/scanApps.js",
|
"predev": "node bin/scanApps.js",
|
||||||
"preoms": "dotenv -e .env.oms 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": {
|
"dependencies": {
|
||||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import utils from './utils';
|
|||||||
import vcUI from 'dui/packages';
|
import vcUI from 'dui/packages';
|
||||||
import appComp from 'dui/dv';
|
import appComp from 'dui/dv';
|
||||||
import store from './utils/store';
|
import store from './utils/store';
|
||||||
import autoRoutes from "./utils/autoRoutes";
|
|
||||||
import extra from "./config.json"
|
import extra from "./config.json"
|
||||||
import axios from "./utils/axios";
|
import axios from "./utils/axios";
|
||||||
//备注底座信息,勿删
|
//备注底座信息,勿删
|
||||||
@@ -19,7 +18,7 @@ Vue.config.productionTip = false;
|
|||||||
Vue.prototype.$cdn = "https://cdn.cunwuyun.cn"
|
Vue.prototype.$cdn = "https://cdn.cunwuyun.cn"
|
||||||
Vue.prototype.$request = axios
|
Vue.prototype.$request = axios
|
||||||
Object.keys(utils).map((e) => (Vue.prototype[e] = utils[e]));
|
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
|
let theme = null
|
||||||
store.dispatch('getSystem', extra.sysInfo).then(res => {
|
store.dispatch('getSystem', extra.sysInfo).then(res => {
|
||||||
theme = JSON.parse(res?.colorScheme || null)
|
theme = JSON.parse(res?.colorScheme || null)
|
||||||
|
|||||||
@@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import VueRouter from 'vue-router'
|
import VueRouter from 'vue-router'
|
||||||
import {routes} from "./autoRoutes"
|
import routes from "./apps.js"
|
||||||
import config from "../config.json"
|
import config from "../config.json"
|
||||||
|
import store from "@/utils/store";
|
||||||
|
|
||||||
|
const {state: {user}, commit, dispatch} = store
|
||||||
|
const signOut = () => commit("signOut")
|
||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
export default new VueRouter({
|
const router = new VueRouter({
|
||||||
base: config.base || '/',
|
base: config.base || '/',
|
||||||
mode: 'history',
|
mode: 'history',
|
||||||
hashbang: false,
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user