mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-10-29 08:58:22 +08:00
原实现三个组件在 JS 顶层用 $.ajax({async:false}) 同步拉取 .html 模板,
每个页面打开固定发 3 个同步请求(阻塞主线程,与组件是否被使用无关),
且路径硬编码 /static/ 与 __STATIC__(OSS 部署)脱节,模板 URL 无版本
参数存在与 js 缓存不同步的漂移问题,请求失败时静默渲染空白。
改造内容:
- 模板改为首次 render() 时异步获取,Deferred 缓存供同页多实例共享,
失败不缓存并在下次 render 自动重试,失败时 console.error + 提示
- 模板 URL 取 CONFIG.STATIC + CONFIG.STATIC_VERSION,layout 的
window.CONFIG 新增这两项注入;无注入时逐级回退 /static 与 VERSION,
兼容下游覆盖 layout 的旧页面
- 组件 CSS 由 _require.html 直接 link 引入(__STATIC__ + 版本键),
替代原 JS 动态注入
- render() 返回 Promise(resolve Vue 实例);仓库内调用均为
fire-and-forget,无兼容影响
212 lines
8.1 KiB
PHP
212 lines
8.1 KiB
PHP
(function () {
|
||
// 组件模板懒加载:首次 render 时才异步请求,同页多实例共享一次请求;
|
||
// 路径与版本跟随页面注入的 CONFIG.STATIC / CONFIG.STATIC_VERSION,
|
||
// 与 _require.html 中 js/css 的缓存键保持一致;失败不缓存,下次 render 重试。
|
||
// 样式 tableData.css 已改为在 _require.html 中直接引入,不再由 JS 注入。
|
||
var tableDataTemplatePromise = null;
|
||
|
||
function loadTableDataTemplate() {
|
||
if (tableDataTemplatePromise !== null) {
|
||
return tableDataTemplatePromise;
|
||
}
|
||
|
||
var config = window.CONFIG || {};
|
||
var staticRoot = config.STATIC || '/static';
|
||
var version = config.STATIC_VERSION || config.VERSION || '';
|
||
var url = staticRoot + '/plugs/lay-module/tableData/tableData.html?t=' + version;
|
||
var deferred = $.Deferred();
|
||
|
||
$.ajax({
|
||
type: 'get',
|
||
url: url,
|
||
cache: true,
|
||
dataType: 'text'
|
||
}).done(function (template) {
|
||
if ($.trim(template)) {
|
||
deferred.resolve(template);
|
||
} else {
|
||
deferred.reject('模板内容为空');
|
||
}
|
||
}).fail(function (xhr) {
|
||
deferred.reject(xhr);
|
||
});
|
||
|
||
tableDataTemplatePromise = deferred.promise();
|
||
tableDataTemplatePromise.fail(function (reason) {
|
||
console.error('tableData 模板加载失败: ' + url, reason);
|
||
var ua = window.UA_ADMIN || window.ua;
|
||
if (ua) {
|
||
ua.msg.error('tableData 组件初始化失败');
|
||
}
|
||
// 失败不缓存,下次 render 自动重试
|
||
tableDataTemplatePromise = null;
|
||
});
|
||
|
||
return tableDataTemplatePromise;
|
||
}
|
||
|
||
var tableData = function () { };
|
||
|
||
tableData.prototype.render = function (elem, data) {
|
||
var clienWidth, clientHeight;
|
||
clienWidth = '100%';
|
||
clientHeight = '100%';
|
||
|
||
var defaultOption = {
|
||
width: clienWidth,
|
||
height: clientHeight,
|
||
trim: 0,
|
||
placeholder: '请选择',
|
||
selectConfirmCallback: 'onTableDataConfirm',
|
||
type: 'input',
|
||
className: 'layui-input',
|
||
style:''
|
||
};
|
||
|
||
var options = $.extend(defaultOption, data);
|
||
options.style = $(elem).attr('style')
|
||
var valueField = options.valueField;
|
||
|
||
if (options.index.indexOf('?') > -1) {
|
||
options.index += '&';
|
||
} else {
|
||
options.index += '?';
|
||
}
|
||
options.index += 'select_mode=' + options.selectType;
|
||
|
||
if(!options.selectIndex){
|
||
options.selectIndex = options.index;
|
||
}else{
|
||
if (options.selectIndex.indexOf('?') > -1) {
|
||
options.selectIndex += '&';
|
||
} else {
|
||
options.selectIndex += '?';
|
||
}
|
||
options.selectIndex += 'select_mode=' + options.selectType;
|
||
}
|
||
|
||
if (options.type == 'textarea') {
|
||
options.className = 'layui-textarea';
|
||
}
|
||
|
||
return loadTableDataTemplate().then(function (template) {
|
||
return new Vue({
|
||
el: elem,
|
||
data() {
|
||
return {
|
||
setting: options,
|
||
listSelected: [],
|
||
value: ''
|
||
};
|
||
},
|
||
watch: {
|
||
listSelected(value) {
|
||
|
||
var valueList = value.map(itemValue => itemValue[valueField]);
|
||
var valueStr = valueList.join(',');
|
||
if (options.selectType == 'checkbox') {
|
||
if (options.trim == 0) {
|
||
valueStr = ',' + valueStr + ',';
|
||
}
|
||
}
|
||
this.value = valueStr;
|
||
}
|
||
},
|
||
computed: {
|
||
listSelectedShow() {
|
||
if (this.setting.fieldName.indexOf('|') < 0) {
|
||
return this.listSelected.map(
|
||
(item) => {
|
||
item['_select_show'] = ua.dataGet(item, this.setting.fieldName);
|
||
return item;
|
||
}
|
||
);
|
||
}
|
||
|
||
var fieldNameList = this.setting.fieldName.split('|');
|
||
return this.listSelected.map(item => {
|
||
var showText = '';
|
||
fieldNameList.forEach(fieldName => {
|
||
showText += ua.dataGet(item, fieldName) + ' ';
|
||
});
|
||
item['_select_show'] = showText;
|
||
|
||
return item;
|
||
});
|
||
},
|
||
},
|
||
created() {
|
||
this.value = options.selectValue;
|
||
if (typeof this.value != 'string') {
|
||
this.value = this.value.toString();
|
||
}
|
||
var valueLength = this.value.split(',').length;
|
||
loading.show();
|
||
$.get(options.index, {
|
||
page: 1,
|
||
limit: valueLength,
|
||
filter: JSON.stringify({ [options.valueField]: this.value }),
|
||
op: JSON.stringify({ [options.valueField]: 'in' }),
|
||
group: options.valueField
|
||
}, (result) => {
|
||
loading.hide();
|
||
this.listSelected = result.data;
|
||
});
|
||
|
||
},
|
||
mounted() {
|
||
if (options.required == 1) {
|
||
$(this.$refs['tableData']).closest('.layui-form-item').children('.layui-form-label').addClass('required');
|
||
}
|
||
},
|
||
template: template,
|
||
|
||
methods: {
|
||
openSelectPage() {
|
||
|
||
if (options.readonly == 1) {
|
||
return false;
|
||
}
|
||
|
||
var selectedIds = this.listSelected.map(item => item.id);
|
||
var index = layer.open({
|
||
title: '选择数据',
|
||
type: 2,
|
||
area: [options.width, options.height],
|
||
content: options.selectIndex + '&selectedIds=' + selectedIds.join(','),
|
||
maxmin: true,
|
||
moveOut: true,
|
||
shadeClose: true,
|
||
success: (layero, index) => {
|
||
window[options.selectConfirmCallback] = (data) => {
|
||
data.forEach(dataItem => {
|
||
|
||
if (options.selectType == 'radio') {
|
||
this.listSelected = [];
|
||
}
|
||
var itemFind = this.listSelected.find(itemSelect => itemSelect[valueField] == dataItem[valueField]);
|
||
if (itemFind == undefined) {
|
||
this.listSelected.push(dataItem);
|
||
}
|
||
});
|
||
this.$forceUpdate();
|
||
layer.close(index);
|
||
};
|
||
},
|
||
end: function () {
|
||
index = null;
|
||
window[options.selectConfirmCallback] = undefined;
|
||
}
|
||
});
|
||
|
||
},
|
||
removeItem(item, index) {
|
||
this.listSelected.splice(index, 1);
|
||
}
|
||
}
|
||
});
|
||
});
|
||
};
|
||
|
||
window.tableData = new tableData();
|
||
})(); |