import { mergeOptions } from '../utils/mergeOptions'
const defaultOption = {
fileName: 'index.js',
path: './src/router'
}
const setDefaultRoute = (routes) => {
return routes.reduce((acc, route) => {
const newRoute = {
name: route.name,
path: route.path,
component: route.component,
children: setDefaultRoute(route.children)
}
if (route?.children?.length) {
const redirectChild = route.children.find((item) => item.isDefault)
if (redirectChild) {
newRoute.redirect = { name: `${redirectChild.name}` }
}
}
acc.push(newRoute)
return acc
}, [])
}
const flattenRoutes = (routes, parentPath = '') => {
return routes.reduce((acc, route) => {
const fullPath = `${parentPath}${route.path}`
if (route.component) {
const newRoute = {
name: `${route.name}`,
path: fullPath,
component: route.component,
children: flattenRoutes(route.children),
isDefault: route.isDefault
}
acc.push(newRoute)
} else if (route?.children?.length) {
const children = flattenRoutes(route.children, fullPath + '/')
acc.push(...children)
}
return acc
}, [])
}
const convertToNestedRoutes = (schema) => {
const pageSchema = (schema.pageSchema || []).sort((a, b) => a.meta?.router?.length - b.meta?.router?.length)
const result = []
let home = {
path: '/'
}
let isGetHome = false
pageSchema.forEach((item) => {
if ((item.meta?.isHome || item.meta?.isDefault) && !isGetHome) {
home.redirect = { name: `${item.meta.id}` }
isGetHome = true
}
const parts = item.meta?.router?.split('/').filter(Boolean)
let currentLevel = result
parts.forEach((part, index) => {
let found = false
for (let i = 0; i < currentLevel.length; i++) {
if (currentLevel[i].path === part) {
currentLevel = currentLevel[i].children
found = true
break
}
}
if (!found) {
const newNode = {
path: part,
children: []
}
if (index === parts.length - 1) {
newNode.component = `() => import('@/views${item.path ? `/${item.path}` : ''}/${item.fileName}.vue')`
newNode.isDefault = item.meta.isDefault
newNode.name = item.meta.id
}
currentLevel.push(newNode)
currentLevel = newNode.children
}
})
})
home.children = setDefaultRoute(flattenRoutes(result))
return [home]
}
function genRouterPlugin(options = {}) {
const realOptions = mergeOptions(defaultOption, options)
const { path, fileName } = realOptions
return {
name: 'tinyEngine-generateCode-plugin-router',
description: 'transform router schema to router code plugin',
* 根据页面生成路由配置
* @param {import('@opentiny/tiny-engine-dsl-vue').IAppSchema} schema
* @returns
*/
run(schema) {
const routesList = convertToNestedRoutes(schema)
const resultStr = JSON.stringify(routesList, null, 2).replace(
/("component":\s*)"(.*?)"/g,
(match, p1, p2) => p1 + p2
)
const importSnippet = "import { createRouter, createWebHashHistory } from 'vue-router'"
const exportSnippet = `
export default createRouter({
history: createWebHashHistory(),
routes
})`
const routeSnippets = `const routes = ${resultStr}`
const res = {
fileType: 'js',
fileName,
path,
fileContent: `${importSnippet}\n ${routeSnippets} \n ${exportSnippet}`
}
return res
}
}
}
export default genRouterPlugin