UNPKG

@ovine/core

Version:

Build flexible admin system with json.

254 lines (253 loc) 10.1 kB
/** * 路由相关工具函数 * TODO: 添加 unit test */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { cloneDeep, get, isFunction, isPlainObject } from 'lodash'; import { app } from "../app"; import { defLoadPageSchema, rootRoute } from "../constants"; import logger from "../utils/logger"; import { isSubStr, retryPromise, loadScriptAsync, deserialize } from "../utils/tool"; const log = logger.getLogger('lib:routes:exports'); const requestComponent = 'request://pathToComponent'; // 计算 路由 path export function getRoutePath(path, origin = false) { const routePrefix = app.constants.routePrefix || rootRoute; const currPthStr = currPath(path); const pathStr = `${rootRoute}${currPthStr}`; const withBaseUrl = isSubStr(pathStr, routePrefix, 0); let routePath = `${withBaseUrl ? rootRoute : routePrefix}${currPthStr}`; if (origin) { routePath = pathStr.replace(new RegExp(`^${routePrefix}`), rootRoute); } return routePath; } export function getCurrRoutePath() { return getRoutePath(window.location.pathname, true); } // 判断是否是本地文件地址 function isLocalFile(url) { return !(url.indexOf('://') > -1 || url.startsWith('//')); } // 获取 pages 内组件文件在项目内本地的相对路径 或者 远程服务器路径, export function getPageFilePath(option) { const { pathToComponent, nodePath = '', path = '' } = option; // pathToComponent 为 reqOpt 时, 直接返回 一个 固定标示字符串 if (isPlainObject(pathToComponent) && get(pathToComponent, 'url')) { return requestComponent; } const url = typeof pathToComponent === 'string' // 任意路径 ? pathToComponent : pathToComponent === true // pathToComponent 默认 使用 nodePath 如果设置为 true,表示 使用 path 路径 ? path || nodePath : nodePath || path; // 本地文件路径 if (isLocalFile(url)) { return currPath(url); } // 当前域名服务器下路径 if (url.startsWith('root://')) { return window.location.origin + url.substring(6); } // 远程服务器下 路径 if (url.startsWith('http://') || url.startsWith('https://')) { return url; } // 宽泛协议 if (url.startsWith('//')) { return window.location.protocol + url; } return ''; } // 获取 页面预设值。默认为 pages/xxx/preset.ts 该文件是权限设置必须文件 export function getPagePreset(option) { var _a; const filePath = getPageFilePath(option); if (((_a = app.asyncPage) === null || _a === void 0 ? void 0 : _a.preset) && option.nodePath && app.asyncPage.preset[option.nodePath]) { return cloneDeep(app.asyncPage.preset[option.nodePath]); } // 加载本地文件 if (isLocalFile(filePath)) { try { /* webpackInclude: /pages[\\/].*[\\/]preset\.[t|j]sx?$/ */ const pagePest = require(`~/pages/${filePath}/preset`).default; return isFunction(pagePest) ? pagePest(option) : pagePest; } catch (e) { // } } return undefined; } // 获取 mock。默认为 pages/xxx/mock.ts 存在该文件,将自动注入mock到prest每一个 api export function getPageMockSource(option) { var _a; if (!app.env.isMock) { return undefined; } if (((_a = app.asyncPage) === null || _a === void 0 ? void 0 : _a.mock) && option.nodePath && app.asyncPage.mock[option.nodePath]) { return cloneDeep(app.asyncPage.mock[option.nodePath]); } const filePath = getPageFilePath(option); // 加载本地文件 if (isLocalFile(filePath)) { try { /* webpackInclude: /pages[\\/].*[\\/]mock\.[t|j]sx?$/ */ const pagePest = require(`~/pages/${filePath}/mock`); return pagePest.default; } catch (e) { // } } return undefined; } // 异步获取页面文件 export function getPageFileAsync(option) { var _a; return __awaiter(this, void 0, void 0, function* () { const filePath = getPageFilePath(option); // TODO: 支持传入 页面出错 自定义 schema,并将注入参数 const pageAlias = option.nodePath; // 加载本地文件 if (isLocalFile(filePath)) { return retryPromise(() => import( /* webpackInclude: /[\\/]src[\\/]pages[\\/].*[\\/]index\.[t|j]sx?$/ */ /* webpackChunkName: "p_[request]" */ `~/pages/${filePath}/index`)); } if (!pageAlias) { return defLoadPageSchema; } if (((_a = app.asyncPage) === null || _a === void 0 ? void 0 : _a.schema) && app.asyncPage.schema[pageAlias]) { return cloneDeep(app.asyncPage.schema[pageAlias]); } // 动态渲染页面 return retryPromise(() => { var _a; app.asyncPage.schema = ((_a = app.asyncPage) === null || _a === void 0 ? void 0 : _a.schema) || {}; // 异步加载脚本,规范 window.ovine.addPageSchemaJs(option.nodePath, {default?,schema}) if (/\.js/.test(filePath)) { return loadScriptAsync(filePath) .then(() => { if (!app.asyncPage.schema[pageAlias]) { log.error(`Please add page schema for "${pageAlias}" by using 'window.ovine.addPageSchemaJs()'.`); return defLoadPageSchema; } return cloneDeep(app.asyncPage.schema[pageAlias]); }) .catch((err) => { log.error('An error occurred by load js scripts.', err); return defLoadPageSchema; }); } // 接口获取 schema, 不缓存页面 return app .request(filePath === requestComponent ? option.pathToComponent : { method: 'GET', url: filePath, }) .then(({ data }) => { const { schema: resSchema } = (data === null || data === void 0 ? void 0 : data.data) || {}; const schema = isPlainObject(resSchema) ? resSchema : deserialize(resSchema || ''); if (!schema) { log.error(`Please add page schema string for "${pageAlias}" by http server api.`); return defLoadPageSchema; } const pageSchema = { schema }; return pageSchema; }) .catch((err) => { log.error('An error occurred when fetch page schema.', err); return defLoadPageSchema; }); }); }); } // 获取 nodePath export function getNodePath(option) { return option.nodePath || getPageFilePath(option); } // 当前路径,去除多余前缀/,保持一致性 /login ==> login export function currPath(path, defaultPath = '') { if (!path || path === rootRoute) { return defaultPath; } return !isSubStr(path, rootRoute, 0) ? path : path.substring(1); } // amis 官方 格式化项目内 链接 export const normalizeLink = (option) => { const { location: loc = window.location, to: toLink } = option; const location = Object.assign({ pathname: rootRoute, search: '', hash: '' }, loc); let to = toLink || ''; if (to && to[0] === '#') { to = location.pathname + location.search + to; } else if (to && to[0] === '?') { to = location.pathname + to; } const searchIdx = to.indexOf('?'); const hashIdx = to.indexOf('#'); const isSearch = searchIdx > -1; const isHash = hashIdx > -1; let pathname = isSearch ? to.substring(0, searchIdx) : isHash ? to.substring(0, hashIdx) : to; const search = isSearch ? to.substring(searchIdx, isHash ? hashIdx : undefined) : ''; const hash = isHash ? to.substring(hashIdx) : location.hash; if (!pathname) { pathname = location.pathname; } else if (pathname[0] !== rootRoute && !/^https?:\/\//.test(pathname)) { const relativeBase = location.pathname; const paths = relativeBase.split(rootRoute); paths.pop(); let m = /^\.\.?\//.exec(pathname); while (m) { if (m[0] === '../') { paths.pop(); } pathname = pathname.substring(m[0].length); m = /^\.\.?\//.exec(pathname); } pathname = paths.concat(pathname).join(rootRoute); } return { href: pathname + search + hash, pathname, search, hash, }; }; export function jumpTo(link, option = {}) { const { href } = normalizeLink({ to: link }); const { blank, replace, origin = true } = option; if (/^https?:\/\//.test(href)) { if (blank) { window.open(href, '_blank'); } else if (replace) { window.location.replace(href); } else { window.location.href = href; } return; } if (blank) { window.open(`${window.location.origin}${href}`, '_blank'); } else { const method = replace ? 'replace' : 'push'; // TODO: 确定是否有不需要替换 url 的场景 app.routerHistory[method](getRoutePath(href, origin)); } }