/* 异步请求结果返回状态码 */
var ResultStatus = { OK: 100, Failed: 101, NotLogin: 102, Unauthorized: 103 };
String.formatDate = function (format) {
return formatDate(this, format);
}
function formatDate(date, format) {
if (!date || !format)
return "";
if (date.constructor == String) {
date = date.replace(/-/g, "/").replace("T", " ");//IE11里面不能直接转换带"-",必须先替换成"/",如果有T也要替换,不然 2018/1/1T10:10 这种格式会有问题
date = new Date(date);
}
if (date.constructor == Date) {
return date.format(format);
}
return date;
}
Date.prototype.format = function (format) {
var o =
{
"M+": this.getMonth() + 1, //month
"d+": this.getDate(), //day
"H+": this.getHours(), //hour
"m+": this.getMinutes(), //minute
"s+": this.getSeconds(), //second
"q+": Math.floor((this.getMonth() + 3) / 3), //quarter
"S": this.getMilliseconds() //millisecond
};
if (/(y+)/.test(format))
format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(format))
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
return format;
};
Array.prototype.where = function (predicate) {
var arr = this;
var retArr = [];
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
if (predicate(item)) {
retArr.push(item);
}
}
return retArr;
};
Array.prototype.select = function (selector) {
var arr = this;
var retArr = [];
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
retArr.push(selector(item));
}
return retArr;
};
Array.prototype.first = function (predicate) {
var arr = this;
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
if (predicate(item)) {
return item;
}
}
return null;
};
Array.prototype.any = function (predicate) {
var arr = this;
var retArr = [];
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
if (predicate(item)) {
return true;
}
}
return false;
};
Array.prototype.pushRange = function (items) {
for (var i = 0; i < items.length; i++) {
var item = items[i];
this.push(item);
}
};
Array.prototype.each = function (action) {
for (var i = 0; i < this.length; i++) {
var item = this[i];
action(item);
}
};
Array.prototype.sortBy = function (keySelector, rev) {
/*
*此方法返回一个新对象
*/
var arr = [];
for (var i = 0; i < this.length; i++) {
arr.push(this[i]);
}
//第二个参数没有传递 默认升序排列
rev = rev !== undefined && rev !== false;
var compare = function (a, b) {
a = keySelector(a);
b = keySelector(b);
if (rev)
return b - a;
else
return a - b;
}
arr.sort(compare);
return arr;
}
Array.prototype.orderBy = function (keySelector) {
return this.sortBy(keySelector, false);
}
Array.prototype.orderByDesc = function (keySelector) {
return this.sortBy(keySelector, true);
}
Array.prototype.groupBy = function (keySelector) {
var arr = this;
var ret = {};
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
var key = keySelector(item);
var group;
if (key in ret) {
group = ret[key];
}
else {
group = [];
ret[key] = group;
}
group.push(item);
}
return ret;
}
function newGuid() {
var guid = "";
for (var i = 1; i <= 32; i++) {
var n = Math.floor(Math.random() * 16.0).toString(16);
guid += n;
if ((i == 8) || (i == 12) || (i == 16) || (i == 20)) guid += "-";
}
return guid;
};
/* $ace */
(function ($) {
var $ace = {};
/* 返回 json 数据 */
$ace.get = function (url, data, callback) {
if ($.isFunction(data)) {
callback = data;
data = undefined;
}
url = parseUrl(url);
var ret = execAjax("GET", url, data, callback);
return ret;
}
$ace.post = function (url, data, callback) {
if ($.isFunction(data)) {
callback = data;
data = undefined;
}
var ret = execAjax("POST", url, data, callback);
return ret;
}
$ace.alert = function (msg, callBack) {
layerAlert(msg, callBack);
}
$ace.confirm = function (msg, callBack) {
layerConfirm(msg, callBack);
}
$ace.msg = function (msg) {
layerMsg(msg);
}
/* 加载提示,不会自动消失,需手动关闭 */
$ace.load = function (msg) {
var index = layer.msg(msg || "", {
icon: 16
, shade: 0.01
, time: 1024 * 1000 * 1000 //设置超长等待,最后手动关闭
});
var loader = {
close: function () {
layer.close(index);
}
};
return loader;
}
$ace.reload = function () {
location.reload();
return false;
}
/* 将当前 url 的参数值 */
$ace.getQueryParam = function (name) {
if (name === null || name === undefined || name === "")
return "";
name = ("" + name).toLowerCase();
var search = location.search.slice(1);
var arr = search.split("&");
for (var i = 0; i < arr.length; i++) {
var ar = arr[i].split("=");
if (ar[0].toLowerCase() == name) {
return decodeURIComponent(ar[1]);
}
}
return "";
}
/* 将当前 url 参数转成一个 js 对象 */
$ace.getQueryParams = function () {
var params = {};
var loc = window.location;
if (!loc.search) {
return params;
}
var paramsString;
paramsString = loc.search.substr(1);//将?去掉
var arr = paramsString.split("&");
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
var index = item.indexOf("=");
if (index == -1)
continue;
var paramName = item.substr(0, index);
if (!paramName)
continue;
var value = item.substr(index + 1);
params[paramName] = decodeURIComponent(value);
}
return params;
}
$ace.findName = function (optionList, value, valuePropName, textPropName) {
valuePropName = valuePropName || "Id";
textPropName = textPropName || "Name";
return $ace.findText(optionList, value, valuePropName, textPropName);
}
$ace.findText = function (optionList, value, valuePropName, textPropName) {
if (optionList.length == 0)
return null;
var valuePropertyNames;
var textPropertyNames;
if (valuePropName) {
valuePropertyNames = [valuePropName];
textPropertyNames = [textPropName];
}
else {
valuePropertyNames = ["Id", "id", "Value", "value"];
textPropertyNames = ["Name", "name", "Text", "text"];
}
valuePropName = valuePropertyNames.first(function (name) {
return name in optionList[0];
});
textPropName = textPropertyNames.first(function (name) {
return name in optionList[0];
});
var text = null;
var len = optionList.length;
for (var i = 0; i < len; i++) {
if (optionList[i][valuePropName] == value) {
text = optionList[i][textPropName];
break;
}
}
return text;
}
$ace.selectFields = function (items, fieldName) {
return items.select(function (item) {
return item[fieldName];
});
}
$ace.selectIds = function (items) {
if (items.length == 0)
return [];
var names = ["Id", "id", "ID"];
var name;
for (var i = 0; i < names.length; i++) {
if (names[i] in items[0]) {
name = names[i];
break;
}
}
return $ace.selectFields(items, name);
}
$ace.selectTexts = function (items) {
if (items.length == 0)
return [];
var names = ["Name", "name", "Text", "text"];
var name;
for (var i = 0; i < names.length; i++) {
if (names[i] in items[0]) {
name = names[i];
break;
}
}
return $ace.selectFields(items, name);
}
$ace.browser = function () {
var userAgent = navigator.userAgent;
var isOpera = userAgent.indexOf("Opera") > -1;
if (isOpera) {
return "Opera"
};
if (userAgent.indexOf("Firefox") > -1) {
return "FF";
}
if (userAgent.indexOf("Chrome") > -1) {
if (window.navigator.webkitPersistentStorage.toString().indexOf('DeprecatedStorageQuota') > -1) {
return "Chrome";
} else {
return "360";
}
}
if (userAgent.indexOf("Safari") > -1) {
return "Safari";
}
if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera) {
return "IE";
};
}
$ace.download = function (url, data, method) {
if (url && data) {
data = typeof data == 'string' ? data : jQuery.param(data);
var inputs = '';
$.each(data.split('&'), function () {
var pair = this.split('=');
inputs += '<input type="hidden" name="' + pair[0] + '" value="' + pair[1] + '" />';
});
$('<form action="' + url + '" method="' + (method || 'post') + '">' + inputs + '</form>').appendTo('body').submit().remove();
};
};
/* 依赖 bootstrap ui */
$ace.selectRow = function (selectedTr) {
var c = "warning";
$(selectedTr).addClass(c);
$(selectedTr).siblings().removeClass(c);
//console.log($(selectedTr).attr("deny"));
/*if ($(selectedTr).attr("deny") == "true") {
jQuery(".a-btn-edit,.a-btn-delete,.btn-auth").attr("disabled", true);
}
else {
jQuery(".a-btn-edit,.a-btn-delete,.btn-auth").attr("disabled", false);
}*/
return true;
}
$ace.formatBool = function (val) {
if (val == true) {
return "是";
}
else if (val == false) {
return "否";
}
return val;
}
function execAjax(type, url, data, callback) {
var layerIndex = layer.load(2);
var ret = $.ajax({
url: url,
type: type,
dataType: "json",
data: data,
complete: function (xhr) {
layer.close(layerIndex);
},
success: function (result) {
var isStandardResult = ("Status" in result) && ("Msg" in result);
if (isStandardResult) {
if (result.Status == ResultStatus.Failed) {
layerAlert(result.Msg || "操作失败");
return;
}
if (result.Status == ResultStatus.NotLogin) {
layerAlert(result.Msg || "未登录或登录过期,请重新登录");
return;
}
if (result.Status == ResultStatus.Unauthorized) {
layerAlert(result.Msg || "权限不足,禁止访问");
return;
}
if (result.Status == ResultStatus.OK) {
/* 传 result,用 result.Data 还是 result.Msg,由调用者决定 */
callback(result);
}
}
else
callback(result);
},
error: errorCallback
});
return ret;
}
function errorCallback(xhr, textStatus, errorThrown) {
var json = { textStatus: textStatus, errorThrown: errorThrown };
alert("请求失败: " + JSON.stringify(json));
}
function parseUrl(url) {
if (url.indexOf("_dc=") < 0) {
if (url.indexOf("?") >= 0) {
url = url + "&_dc=" + (new Date().getTime());
} else {
url = url + "?_dc=" + (new Date().getTime());
}
}
return url;
};
function layerAlert(msg, callBack) {
msg = msg == null ? "" : msg;/* layer.alert 传 null 会报错 */
var type = 'warning';
var icon = "";
if (type == 'success') {
icon = "fa-check-circle";
}
if (type == 'error') {
icon = "fa-times-circle";
}
if (type == 'warning') {
icon = "fa-exclamation-circle";
}
var idx;
idx = layer.alert(msg, {
icon: icon,
title: "系统提示",
btn: ['确认'],
btnclass: ['btn btn-primary'],
}, function () {
layer.close(idx);
if (callBack)
callBack();
});
}
function layerConfirm(content, callBack) {
var idx;
idx = layer.confirm(content, {
icon: "fa-exclamation-circle",
title: "系统提示",
btn: ['确认', '取消'],
btnclass: ['btn btn-primary', 'btn btn-danger'],
}, function () {
layer.close(idx);
callBack();
}, function () {
});
}
function layerMsg(msg, callBack) {
msg = msg == null ? "" : msg;/* layer.msg 传 null 会报错 */
layer.msg(msg, { time: 2000, shift: 0 });
}
window.$ace = $ace;
})($);
/* $ 扩展 */
(function ($) {
/* 设置标签的值,同时触发 change 事件 */
$.fn.setValue = function (val) {
this.val(val);
this.change();
}
/* 根据值设置 select 标签的选中项,同时触发 change 事件 */
$.fn.setSelectedValue = function (val) {
for (var j = 0; j < this.length; j++) {
var selectElement = this[j];
for (var i = 0; i < selectElement.options.length; i++) {
var op = selectElement.options[i];
if (op.value == val) {
op.selected = true;
$(selectElement).change();
break;
}
}
}
};
$.fn.getSelectedValue = function () {
var ret = "";
var c = "";
for (var j = 0; j < this.length; j++) {
var selectElement = this[j];
var idx = selectElement.selectedIndex;
ret += c + selectElement[idx].value;
c = ";";
}
return ret;
};
$.fn.getSelectedText = function () {
var ret = "";
var c = "";
for (var j = 0; j < this.length; j++) {
var selectElement = this[j];
var idx = selectElement.selectedIndex;
ret += c + selectElement[idx].text;
c = ";";
}
return ret;
};
/* 设置 radio、checkbox 状态为选中 */
$.fn.checked = function () {
for (var j = 0; j < this.length; j++) {
var ele = this[j];
var old = ele.checked;
ele.checked = true;
if (old != ele.checked)
$(ele).change();
}
}
/* 设置 radio、checkbox 状态为未选中 */
$.fn.unchecked = function () {
for (var j = 0; j < this.length; j++) {
var ele = this[j];
var old = ele.checked;
ele.checked = false;
if (old != ele.checked)
$(ele).change();
}
}
/* 设置 radio、checkbox 状态。如果传入的 value 与控件的 value 相等,则设置为选中,否则不选中 */
$.fn.setChecked = function (value) {
var inputValues = [];
if (value instanceof Array) {
inputValues = value;
}
else {
inputValues.push(value);
}
var values = [];
for (var i = 0; i < inputValues.length; i++) {
var value = inputValues[i];
if (value === true)
values.push("true");
else if (value === false)
values.push("false");
else if (value !== undefined && value !== null) {
values.push(value);
}
}
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var checked = false;
for (var j = 0; j < values.length; j++) {
var value = values[j];
if (ele.value == value) {
checked = true;
break;
}
}
var old = ele.checked;
if (checked) {
ele.checked = true;
}
else {
ele.checked = false;
}
if (old != ele.checked)
$(ele).change();
}
}
/* 获取被选中的 radio、checkbox 值 */
$.fn.getCheckedValue = function () {
for (var j = 0; j < this.length; j++) {
var ele = this[j];
if (ele.checked == true) {
return ele.value;
}
}
return null;
}
$.fn.formValid = function () {
return true;//未做前端校验
return $(this).valid({
errorPlacement: function (error, element) {
element.parents('.formValue').addClass('has-error');
element.parents('.has-error').find('i.error').remove();
element.parents('.has-error').append('<i class="form-control-feedback fa fa-exclamation-circle error" data-placement="left" data-toggle="tooltip" title="' + error + '"></i>');
$("[data-toggle='tooltip']").tooltip();
if (element.parents('.input-group').hasClass('input-group')) {
element.parents('.has-error').find('i.error').css('right', '33px')
}
},
success: function (element) {
element.parents('.has-error').find('i.error').remove();
element.parent().removeClass('has-error');
}
});
}
$.fn.getFormData = function () {
var $form = $(this);
var model = {};
$form.find('input,select,textarea').each(function (r) {
var $this = $(this);
var name = $this.attr('name');
if (!name)
return;
var type = $this.attr('type');
if ($this.attr("disabled") == "disabled")
return;
switch (type) {
case "checkbox":
var checkboxValues;
if (name in model) {
checkboxValues = model[name];
}
else {
checkboxValues = [];
model[name] = checkboxValues;
}
if (this.checked) {
checkboxValues.push($this.val());
}
break;
case "radio":
if (model[name] === undefined)
model[name] = null;
if (this.checked == true)
model[name] = this.value;
break;
case "button":
break;
default:
var value = $this.val();
model[name] = value;
break;
}
});
if ($('[name=__RequestVerificationToken]').length > 0) {
model["__RequestVerificationToken"] = $('[name=__RequestVerificationToken]').val();
}
return model;
};
$.fn.setFormData = function (data) {
var $form = $(this);
$form.find('input,select,textarea').each(function (r) {
var $ele = $(this);
var name = $ele.attr('name');
if (!name)
return;
var type = $ele.attr('type');
var value = null;
if (name in data)
value = data[name];
else
return;//如果模型中不存在相应的name属性,则不管
switch (type) {
case "checkbox":
var values = value || []; //对于checkbox,value是一个数组
for (var i = 0; i < $ele.length; i++) {
var checkbox = $ele[i];
var checkboxValue = checkbox.value;
var checked = false;
for (var j = 0; j < values.length; j++) {
if (checkboxValue == values[j]) {
checked = true;
break;
}
}
checkbox.checked = checked;
}
break;
case "radio":
$ele.setChecked(value);
break;
case "select":
$ele.val(value).trigger("change");
break;
case "button":
break;
default:
$ele.val(value);
break;
}
});
};
$.fn.bindSelect = function (options) {
var defaults = {
value: "Id",
text: "Name",
change: null,
items: [],
placeholder: "-请选择-"
};
var options = $.extend(defaults, options);
var $element = $(this);
if (options.placeholder !== null && options.placeholder !== undefined)
$element.append($("<option></option>").val("").html(options.placeholder));
items = options.items;
$.each(items, function (i) {
$element.append($("<option></option>").val(items[i][options.value]).html(items[i][options.text]));
});
if (options.change)
$element.change(options.change);
return;
}
$.fn.disable = function () {
var $element = $(this);
$element.attr("disabled", "disabled");
}
$.fn.enable = function () {
var $element = $(this);
$element.removeAttr("disabled");
}
$.loading = function (bool, text) {
var $loadingpage = top.$("#loadingPage");
var $loadingtext = $loadingpage.find('.loading-content');
if (bool) {
$loadingpage.show();
} else {
if ($loadingtext.attr('istableloading') == undefined) {
$loadingpage.hide();
}
}
if (!!text) {
$loadingtext.html(text);
} else {
$loadingtext.html("数据加载中,请稍后…");
}
$loadingtext.css("left", (top.$('body').width() - $loadingtext.width()) / 2 - 50);
$loadingtext.css("top", (top.$('body').height() - $loadingtext.height()) / 2);
}
})($);
function ViewModel() {
var me = this;
me.searchModel = _ob({});
me.url = null;//加载数据的url
me.deleteUrl = null;
me.modelKeyName = "Id"; /* 实体主键名称 */
/* 如有必要,子类需重写 DataTable、Dialog */
me.dataTable = new PagedDataTable(me);
me.dialog = new Dialog();
me.init = function () {
me.loadData();
}
/* 添加按钮点击事件 */
me.add = function () {
ensureNotNull(me.dialog, "dialog");
me.dialog.open(null, "添加");
}
/* 编辑按钮点击事件 */
me.edit = function () {
ensureNotNull(me.dataTable, "DataTable");
ensureNotNull(me.dialog, "Dialog");
me.dialog.open(me.dataTable.selectedModel(), "修改");
}
/* 删除按钮点击事件 */
me.del = function () {
$ace.confirm("确定要删除该条数据吗?", me.onDelete);
}
me.onDelete = function () {
deleteRow();
}
/* 要求每行必须有 Id 属性,如果主键名不是 Id,则需要重写 me.ModelKeyName */
function deleteRow() {
if (me.deleteUrl == null)
throw new Error("未指定 DeleteUrl");
var url = me.deleteUrl;
var params = { id: me.dataTable.selectedModel()[me.modelKeyName]() };
$ace.post(url, params, function (result) {
var msg = result.Msg || "删除成功";
$ace.msg(msg);
me.dataTable.removeSelectedModel();
});
}
/* 搜索按钮点击事件 */
me.search = function () {
me.loadData();
}
me.getSearchModel = function () {
var model = me.searchModel();
model = JSON.parse(JSON.stringify(model));
return model;
}
/* 加载数据 */
me.loadData = function (page) {
if (me.url == null)
return;
var data = me.getSearchModel();
if (page)
data.page = page;
$ace.get(me.url, data, function (result) {
me.dataTable.setData(result.Data);
});
}
function ensureNotNull(obj, name) {
if (!obj)
throw new Error("属性 " + name + " 未初始化");
}
}
function DataTable(vmOrDataLoader) {
var me = this;
me.models = _oba([]);
me.selectedModel = _ob(null);
me.getOrdinal = function ($index) {
return $index + 1;
}
me.selectRow = function (model, event) {
me.selectedModel(model);
$ace.selectRow(event.currentTarget);
return true;
}
me.removeSelectedModel = function () {
var selectedModel = me.selectedModel();
if (selectedModel) {
me.models.remove(selectedModel);
}
}
me.setData = function (models) {
var wrapedModels = $ko.toOb(models);
me.models(wrapedModels);
me.selectedModel(null);
}
me.setModels = function (models) {
me.setData();
}
me.reload = function () {
if (!vmOrDataLoader)
throw new Error("未实现 loadData 方法");
if ($.isFunction(vmOrDataLoader)) {
vmOrDataLoader();
}
else {
if ("loadData" in vmOrDataLoader)
vmOrDataLoader.loadData();
else
throw new Error("vmOrDataLoader 未实现 loadData 方法");
}
}
}
function PagedDataTable(vmOrDataLoader) {
var me = this;
DataTable.call(me, vmOrDataLoader);
me.showFirstPage = _ob(false);
me.showLastPage = _ob(false);
me.totalCount = _ob(0);
me.totalPage = _ob(0);
me.currentPage = _ob(0);
me.skipPage = _ob(0);
me.pageSize = _ob(0);
me.showPages = _oba();
me.getOrdinal = function ($index) {
return (me.currentPage() - 1) * me.pageSize() + $index + 1;
}
me.setData = function (pagedData) {
var wrapedData = $ko.toOb(pagedData);
me.models(wrapedData.Models());
me.totalCount(wrapedData.TotalCount());
me.totalPage(wrapedData.TotalPage());
me.currentPage(wrapedData.CurrentPage());
me.skipPage(wrapedData.CurrentPage());
me.pageSize(wrapedData.PageSize());
var showPageCount = 6;
var min = me.currentPage() - (showPageCount / 2);
if (min < 1)
min = 1;
var max = min + showPageCount;
if (max > me.totalPage()) {
max = me.totalPage();
min = max - showPageCount;
if (min < 1)
min = 1;
}
var showPages = [];
for (var i = min; i <= max; i++) {
showPages.push(i);
}
me.showPages(showPages);
me.showFirstPage(min != 1);
me.showLastPage(max != me.totalPage());
me.selectedModel(null);
}
me.setPagedData = function (pagedData) {
me.setData();
}
me.toPage = function (page) {
if (page < 1 || page > me.totalPage() || page == me.currentPage())
return;
me.loadData(page);
}
me.loadData = function (page) {
if (!vmOrDataLoader)
throw new Error("未实现 loadData 方法");
if ($.isFunction(vmOrDataLoader)) {
vmOrDataLoader(page);
}
else {
if ("loadData" in vmOrDataLoader)
vmOrDataLoader.loadData(page);
else
throw new Error("vmOrDataLoader 未实现 loadData 方法");
}
}
me.reload = function () {
me.loadData(me.currentPage());
}
function isFunction(obj) {
return typeof obj === "function";
}
}
function Dialog() {
var me = this;
/* must */
me.title = _ob(null);
me.isShow = _ob(false);
me.editModel = _ob(null);
me.model = _ob({});//绑定到界面的 model
/* end must */
/* must */
me.close = function () {
me.isShow(false);
}
me.open = function (model, title) {
if (me.isShow()) {
me.isShow(false);//确保触发值改变事件。有时候当模态框处于未打开状态时me.isShow()的值依然是true,比如按esc关闭模态框后
}
me.isShow(true);
me.model({});
if (model) {
me.editModel(model);
}
else {
me.editModel(null);
}
if (title)
me.title(title);
me.onOpen();
}
me.save = function () {
me.onSave();
}
/* end must */
me.onOpen = function () {
var model = me.editModel();
if (model) {
var bindModel = $ko.toJS(model);
me.model(bindModel);
}
else {
me.model({});
}
}
me.onSave = function () {
throw new Error("未重写 OnSave 方法");
}
}