chore: 重写初始提交(清空历史,整理后全量提交)
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* YwxApp 路由模块(ThinkPHP 风格 URL 生成)
|
||||
* ------------------------------------------------------------------
|
||||
* 通过后端模板注入的全局 layui.app 获取部署配置(root / module /
|
||||
* routeBase / controller / action / assetUrl),对外提供 path / asset /
|
||||
* api / route 四个方法,供任意 layui 模块以模块化方式调用:
|
||||
*
|
||||
* layui.use(['route'], function () {
|
||||
* var route = layui.route;
|
||||
* route.route('edit', 'user', null, { id: 1 }); // -> /admin/user/edit?id=1
|
||||
* route.asset('ywxapp/css/style.css');
|
||||
* });
|
||||
*
|
||||
* 同时本模块会把方法挂回 layui.app,保持对旧代码的向后兼容
|
||||
* (旧的 layui.app.route(...) 仍可正常工作)。
|
||||
*/
|
||||
layui.define(function (exports) {
|
||||
// 基础配置来自后端模板注入的全局 layui.app
|
||||
// 注意:必须在每次调用时实时读取 layui.app,不能在此处缓存。
|
||||
// 因为本模块(route.js)作为 layui 模块被异步加载,若此时 layui.app
|
||||
// 尚未被 layout.html 的同步脚本赋值,缓存到的就是空对象,导致后续
|
||||
// route() 生成的 URL 缺少应用前缀(如 /index/menu 而非 /admin/index/menu)。
|
||||
var getConf = function () {
|
||||
return (typeof layui !== 'undefined' && layui.app) || window.layui.app || {};
|
||||
};
|
||||
|
||||
var trim = function (s) {
|
||||
return String(s).replace(/(^\/+|\/+$)/g, '');
|
||||
};
|
||||
|
||||
/**
|
||||
* 页面路径拼接(ThinkPHP 风格:/模块/控制器/方法)
|
||||
* 控制器、模块参数均可选,模块缺省使用当前模块(即后端注入的虚拟名):
|
||||
* route.path('index') -> /<当前模块>/index
|
||||
* route.path('index', 'user') -> /<当前模块>/user/index
|
||||
* route.path('index', 'user', 'admin') -> /admin/user/index
|
||||
*/
|
||||
var path = function (method, controller, module) {
|
||||
var conf = getConf();
|
||||
var cfgRoot = conf.root || '/';
|
||||
var cfgModule = conf.module || '';
|
||||
var r = String(cfgRoot || '/').replace(/\/+$/, '');
|
||||
if (module === undefined || module === null || module === '') {
|
||||
module = cfgModule;
|
||||
}
|
||||
var parts = [];
|
||||
if (module) parts.push(trim(module));
|
||||
if (controller) parts.push(trim(controller));
|
||||
if (method) parts.push(trim(method));
|
||||
if (parts.length === 0) return r + '/';
|
||||
return r + '/' + parts.join('/');
|
||||
};
|
||||
|
||||
/**
|
||||
* 静态资源路径拼接
|
||||
* route.asset('ywxapp/css/style.css') -> /assets/ywxapp/css/style.css
|
||||
*/
|
||||
var asset = function (p) {
|
||||
var conf = getConf();
|
||||
var base = String(conf.assetUrl || '/assets').replace(/\/+$/, '');
|
||||
p = String(p || '').replace(/^\/+/, '');
|
||||
return base + '/' + p;
|
||||
};
|
||||
|
||||
/**
|
||||
* API 路径拼接,同 path()(控制器、模块均可选,模块缺省为当前模块)
|
||||
* route.api('save') -> /<当前模块>/save
|
||||
* route.api('save', 'user') -> /<当前模块>/user/save
|
||||
* route.api('save', 'user', 'admin')-> /admin/user/save
|
||||
*/
|
||||
var api = function (method, controller, module) {
|
||||
return path(method, controller, module);
|
||||
};
|
||||
|
||||
/**
|
||||
* 后端 Route::buildUrl() 的 JS 版:与后端路由规则完全一致
|
||||
* 签名同 path():route(方法, 控制器, 模块),控制器/模块可选(缺省用当前模块)。
|
||||
* 额外支持参数与锚点:route('edit','user', null, {id:5}, 'top')
|
||||
* -> /admin/user/edit?id=5#top
|
||||
*/
|
||||
var route = function (method, controller, module, vars, anchor) {
|
||||
// 实时读取后端注入的 layui.app(避免模块异步加载时缓存到空的 layui.app)
|
||||
var conf = getConf();
|
||||
var cfgRoot = conf.root || '/';
|
||||
var cfgModule = conf.module || '';
|
||||
var cfgRouteBase = conf.routeBase || '';
|
||||
var cfgController = conf.controller || '';
|
||||
var cfgAction = conf.action || '';
|
||||
// 基准 URL:优先用后端注入的 cfgRouteBase(形如 /admin/{__CTRL__}/{__ACT__})。
|
||||
// fallback(后端未注入时)基于 root+module 拼带占位符的合法基准,
|
||||
// 绝不再用 path('{__CTRL__}','{__ACT__}') —— 那会产出裸 /{__CTRL__}/{__ACT__}。
|
||||
var base;
|
||||
if (cfgRouteBase) {
|
||||
base = String(cfgRouteBase);
|
||||
// 防御:若后端注入的 routeBase 不含占位符(异常),补上后缀,避免漏替换
|
||||
if (base.indexOf('{__CTRL__}') === -1) {
|
||||
base = base.replace(/\/+$/, '') + '/{__CTRL__}/{__ACT__}';
|
||||
}
|
||||
} else {
|
||||
base = String(cfgRoot || '/').replace(/\/+$/, '')
|
||||
+ (cfgModule ? '/' + trim(cfgModule) : '')
|
||||
+ '/{__CTRL__}/{__ACT__}';
|
||||
}
|
||||
if (module === undefined || module === null || module === '') {
|
||||
module = cfgModule;
|
||||
}
|
||||
// 未显式传 controller 时,优先用后端注入的 cfgController,再兜底默认 'index'
|
||||
// (绝不再裸用字面量 '{__CTRL__}',否则会拼出 /{__CTRL__}/xxx 这类非法 URL)
|
||||
var ctrl = controller ? trim(controller) : (cfgController || 'index');
|
||||
var act = method ? trim(method) : (cfgAction || 'index');
|
||||
// 若显式传了 module,则替换掉基准里的应用前缀
|
||||
if (module) {
|
||||
base = base.replace(/\/[^\/]+\/\{__CTRL__\}/, '/' + trim(module) + '/{__CTRL__}');
|
||||
}
|
||||
var url = base
|
||||
.replace('{__CTRL__}', ctrl)
|
||||
.replace('{__ACT__}', act);
|
||||
// 拼装查询参数
|
||||
if (vars && typeof vars === 'object') {
|
||||
var q = [];
|
||||
for (var k in vars) {
|
||||
if (Object.prototype.hasOwnProperty.call(vars, k) && vars[k] !== '' && vars[k] !== null && vars[k] !== undefined) {
|
||||
q.push(encodeURIComponent(k) + '=' + encodeURIComponent(vars[k]));
|
||||
}
|
||||
}
|
||||
if (q.length) url += (url.indexOf('?') >= 0 ? '&' : '?') + q.join('&');
|
||||
}
|
||||
if (anchor) url += '#' + String(anchor).replace(/^#/, '');
|
||||
return url;
|
||||
};
|
||||
|
||||
var routeModule = {
|
||||
// 配置快照(只读,便于调试)—— 实时读取 layui.app
|
||||
config: function () {
|
||||
var c = getConf();
|
||||
return {
|
||||
root: c.root || '/',
|
||||
assetUrl: c.assetUrl || '/assets',
|
||||
module: c.module || '',
|
||||
routeBase: c.routeBase || '',
|
||||
controller: c.controller || '',
|
||||
action: c.action || ''
|
||||
};
|
||||
},
|
||||
path: path,
|
||||
asset: asset,
|
||||
api: api,
|
||||
route: route
|
||||
};
|
||||
|
||||
// 向后兼容:把方法挂回全局 layui.app,旧代码 layui.app.route() 继续可用
|
||||
if (layui.app) {
|
||||
layui.app.path = path;
|
||||
layui.app.asset = asset;
|
||||
layui.app.api = api;
|
||||
layui.app.route = route;
|
||||
layui.app.config = routeModule.config;
|
||||
}
|
||||
|
||||
exports('route', routeModule);
|
||||
});
|
||||
Reference in New Issue
Block a user