Files
YwxAppThink/public/assets/ywxapp/modules/view.js
T

302 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* The Web UI Theme-v2.7.1
*/
layui.define(["laytpl", "layer", "http"], function (exports) {
// 构造函数 u - 主要接口
function View(e) {
return new Template(e);
}
// 构造函数 t - 模板类
function Template(e) {
this.id = e;
this.container = layui.jquery("#" + (e || "LAY_app_body"));
}
// 引入依赖模块
var $ = layui.jquery,
laytpl = layui.laytpl,
layer = layui.layer,
request = layui.http,
setter = layui.setter,
device = layui.device(),
hint = layui.hint(),
DEFAULT_CONTAINER_ID = "LAY_app_body";
// 加载动画
View.loading = function (container) {
container.append(
this.elemLoad = $('<i class="layui-anim layui-anim-rotate layui-anim-loop layui-icon layui-icon-loading layadmin-loading"></i>')
);
};
// 移除加载动画
View.removeLoad = function () {
this.elemLoad && this.elemLoad.remove();
};
// 退出登录
View.exit = function (callback) {
// setter.request.tokenName 当前为 false,不能作为键,否则等于没清理。
// 统一清空本应用命名空间下的登录态与菜单缓存(对齐 layuiadmin 的退出清理)。
var appName = setter.appName;
['access_token', 'refresh_token', 'menus', 'user', 'note'].forEach(function (key) {
layui.data(appName, { key: key, remove: true });
});
callback && callback();
};
// AJAX 请求封装
View.req = function (options) {
function getUrlInfo() {
return setter.debug ? "<br><cite>URL</cite>" + options.url : "";
}
var successCallback = options.success,
errorCallback = options.error,
requestConfig = setter.request,
responseConfig = setter.response;
// 处理请求数据
options.data = options.data || {};
options.headers = options.headers || {};
// 处理 token
if (requestConfig.tokenName) {
var data = typeof options.data === "string" ? JSON.parse(options.data) : options.data;
options.data[requestConfig.tokenName] =
requestConfig.tokenName in data ?
options.data[requestConfig.tokenName] :
layui.data(setter.appName)[requestConfig.tokenName] || "";
options.headers[requestConfig.tokenName] =
requestConfig.tokenName in options.headers ?
options.headers[requestConfig.tokenName] :
layui.data(setter.appName)[requestConfig.tokenName] || "";
}
// 清除原始回调
delete options.success;
delete options.error;
// 执行 AJAX 请求
return $.ajax($.extend({
type: "get",
dataType: "json",
success: function (response) {
var statusCode = responseConfig.statusCode;
if (response[responseConfig.statusName] == statusCode.ok) {
// 成功
typeof options.done === "function" && options.done(response);
} else if (response[responseConfig.statusName] == statusCode.logout) {
// 退出登录
View.exit();
} else {
// 错误处理
var errorMsg = [
"<cite>Error</cite> " + (response[responseConfig.msgName] || "返回状态码异常"),
getUrlInfo()
].join("");
View.error(errorMsg);
}
typeof successCallback === "function" && successCallback(response);
},
error: function (xhr, status) {
var errorMsg = [
"请求异常,请重试<br><cite>错误信息:</cite>" + status,
getUrlInfo()
].join("");
View.error(errorMsg);
typeof errorCallback === "function" && errorCallback.apply(this, arguments);
}
}, options));
};
// 弹窗
View.popup = function (options) {
var successCallback = options.success, skin = options.skin;
delete options.success;
delete options.skin;
return layer.open($.extend({
type: 1,
title: "提示",
content: "",
id: "LAY-system-view-popup",
skin: "layui-layer-admin" + (skin ? " " + skin : ""),
shadeClose: true,
closeBtn: false,
success: function (layero, index) {
var closeBtn = $('<i class="layui-icon" close>&#x1006;</i>');
layero.append(closeBtn);
closeBtn.on("click", function () {
layer.close(index);
});
typeof successCallback === "function" && successCallback.apply(this, arguments);
}
}, options));
};
// 错误提示
View.error = function (content, options) {
return View.popup($.extend({
content: content,
maxWidth: 300,
offset: "t",
anim: 6,
id: "LAY_adminError"
}, options));
};
// Template 原型方法
// 渲染视图
Template.prototype.render = function (templatePath, params) {
var self = this;
layui.hash();
// 构建完整模板路径
templatePath = (setter.paths && setter.paths.views ? setter.paths : setter).views +
templatePath + setter.engine;
// 移除加载动画
$("#" + DEFAULT_CONTAINER_ID).children(".layadmin-loading").remove();
View.loading(self.container);
// AJAX 获取模板
request.get(templatePath, { v: layui.cache.version }).then(function (html) {
// 提取标题
var titleElem = $(html = "<div>" + html + "</div>").find("title");
var viewData = {
title: titleElem.text() || (html.match(/<title>([\s\S]*)<\/title>/) || [])[1],
body: html
};
titleElem.remove();
// 设置参数
self.params = params || {};
// 执行 then 回调
self.then && (self.then(viewData), delete self.then);
// 解析模板
self.parse(html);
View.removeLoad();
// 执行 done 回调
self.done && (self.done(viewData), delete self.done);
}).catch(function (xhr) {
View.removeLoad();
// 防止重复错误处理
if (self.render.isError) {
return View.error("请求视图文件异常,状态:" + xhr.status);
}
// 根据状态码显示不同错误页面
if (xhr.status === 404) {
self.render("template/tips/404");
} else {
self.render("template/tips/error");
}
self.render.isError = true;
});
return self;
};
// 解析模板
Template.prototype.parse = function (html, isRefresh, callback) {
function processTemplate(templateInfo) {
var compiledTemplate = laytpl(templateInfo.dataElem.html());
var renderData = $.extend({ params: self.params }, templateInfo.res);
// 渲染并插入 DOM
templateInfo.dataElem.after(compiledTemplate.render(renderData));
// 执行回调
typeof callback === "function" && callback();
// 执行 done 回调(可能是 JavaScript 代码)
try {
templateInfo.done && new Function("d", templateInfo.done)(renderData);
} catch (error) {
console.error(templateInfo.dataElem[0], "\n存在错误回调脚本\n\n", error);
}
}
var self = this;
var isObject = typeof html === "object";
var $html = isObject ? html : $(html);
var templateElems = isObject ? html : $html.find("*[template]");
var hashData = layui.hash();
// 移除标题
$html.find("title").remove();
// 插入 HTML
self.container[isRefresh ? "after" : "html"]($html.children());
// 设置参数
hashData.params = self.params || {};
// 处理所有模板元素
for (var i = templateElems.length; i > 0; i--) {
(function () {
var templateElem = templateElems.eq(i - 1);
var doneCallback = templateElem.attr("lay-done") || templateElem.attr("lay-then");
// 解析模板属性
var urlTemplate = templateElem.attr("lay-url") || "";
var dataTemplate = templateElem.attr("lay-data") || "";
var headersTemplate = templateElem.attr("lay-headers") || "";
var url = laytpl(urlTemplate).render(hashData);
var data = laytpl(dataTemplate).render(hashData);
var headers = laytpl(headersTemplate).render(hashData);
// 解析数据对象
try {
data = new Function("return " + data + ";")();
} catch (error) {
hint.error("lay-data: " + error.message);
data = {};
}
// 解析头部对象
try {
headers = new Function("return " + headers + ";")();
} catch (error) {
hint.error("lay-headers: " + error.message);
headers = headers || {};
}
// 如果有 URL,则发起请求
if (url) {
View.req({
type: templateElem.attr("lay-type") || "get",
url: url,
data: data,
dataType: "json",
headers: headers,
success: function (response) {
processTemplate({
dataElem: templateElem,
res: response,
done: doneCallback
});
}
});
} else {
// 直接处理模板
processTemplate({
dataElem: templateElem,
done: doneCallback
});
}
})();
}
return self;
};
// 自动渲染
Template.prototype.autoRender = function (selector, callback) {
var self = this;
$(selector || "body").find("*[template]").each(function () {
var $this = $(this);
self.container = $this;
self.parse($this, "refresh");
});
};
// 发送数据到模板
Template.prototype.send = function (template, data) {
template = laytpl(template || this.container.html()).render(data || {});
this.container.html(template);
return this;
};
// 刷新
Template.prototype.refresh = function (callback) {
var self = this;
var nextTemplateId = self.container.next().attr("lay-templateid");
if (self.id == nextTemplateId) {
self.parse(self.container, "refresh", function () {
self.container.siblings('[lay-templateid="' + self.id + '"]:last').remove();
typeof callback === "function" && callback();
});
}
return self;
};
// 设置 then 回调
Template.prototype.then = function (callback) {
this.then = callback;
return this;
};
// 设置 done 回调
Template.prototype.done = function (callback) {
this.done = callback;
return this;
};
// 导出模块
exports("view", View);
});