@truenewx/tnxvue2
Version:
互联网技术解决方案:Vue2扩展支持
299 lines (285 loc) • 11 kB
JavaScript
// tnxvue.js
/**
* 基于Vue的扩展支持
*/
import Vue from 'vue';
import tnxcore from '@truenewx/tnxcore/src/tnxcore.js';
import validator from './tnxvue-validator';
import buildRouter from './tnxvue-router';
import Text from './text';
import Percent from './percent';
import './tnxvue.css';
function getDefaultDialogButtons(type, click, theme) {
if (click !== false) {
if (type === 'confirm') {
return [{
text: '确定',
type: theme || 'primary',
click(close) {
if (typeof click === 'function') {
return click.call(this, true, close);
}
}
}, {
text: '取消',
click(close) {
if (typeof click === 'function') {
return click.call(this, false, close);
}
}
}];
} else {
return [{
text: '确定',
type: theme || 'primary',
click(close) {
if (typeof click === 'function') {
return click.call(this, close);
}
}
}];
}
}
return [];
}
export const build = tnxcore.build;
export default build('tnxvue', () => {
const tnxvue = Object.assign({}, tnxcore, {
components: {
Div: {
name: 'TnxvueDiv',
template: '<div><slot></slot></div>'
},
Span: {
name: 'TnxvueSpan',
template: '<span><slot></slot></span>'
},
Text,
Percent,
},
buildRouter,
install(Vue) {
let components = this.components;
Object.keys(components).forEach(key => {
const component = components[key];
Vue.component(component.name, component);
});
this.libs.Vue = Vue;
},
dialog(content, title, buttons, options, contentProps) {
// 默认不实现,由UI框架扩展层实现
throw new Error('Unsupported function');
},
open(component, props, options) {
if (component.methods.dialog) {
options = Object.assign({}, component.methods.dialog(props), options);
} else {
options = options || {};
}
const title = component.title || options.title;
const buttons = options.buttons || getDefaultDialogButtons(options.type, options.click, options.theme);
if (options.buttonText) {
if (!Array.isArray(options.buttonText)) {
options.buttonText = [options.buttonText];
}
for (let i = 0; i < buttons.length; i++) {
let buttonText = options.buttonText[i];
if (buttonText) {
buttons[i].text = buttonText;
}
}
}
delete options.title;
delete options.type;
delete options.click;
return this.dialog(component, title, buttons, options, props);
}
});
Object.assign(tnxvue.util, {
/**
* 判断指定对象是否组件实例
* @param obj 对象
* @returns {boolean} 是否组件实例
*/
isComponent: function (obj) {
return (typeof obj === 'object') && (typeof obj.data === 'function') && (typeof obj.render === 'function');
}
});
tnxvue.app.isProduction = function () {
try {
return !(process && process.env && process.env.NODE_ENV !== 'production');
} catch (e) {
// process未定义时会出错,此时为生产模式
return true;
}
};
tnxvue.app.eventBus = new Vue();
// 元数据到async-validator组件规则的转换处理
tnxvue.app.validator = validator;
tnxvue.app.rpc.getMeta =
tnxvue.util.function.around(tnxvue.app.rpc.getMeta, function (getMeta, url, callback, app) {
return getMeta.call(tnxvue.app.rpc, url, function (meta) {
if (meta) { // meta已被缓存,所以直接修改其内容,以便同步缓存
meta.$rules = validator.getRules(meta);
if (typeof callback === 'function') {
callback.call(this, meta);
}
}
}, app);
});
Object.assign(tnxvue.app.page, {
// TODO 路由缓存迁移至tnxvue-router.js中
startCache: function (router, model, intervalMillis, ignoredFields) {
if (localStorage && intervalMillis && intervalMillis > 1000) { // 缓存间隔必须超过1秒
let path = this._readCache(router, undefined, function (cache) {
Object.assign(model, cache.model);
});
if (path) {
let _this = this;
let intervalId = setInterval(() => {
_this._storeCache(router, path, intervalId, model, ignoredFields);
}, intervalMillis);
}
}
return model;
},
_readCache: function (router, path, callback) {
if (localStorage) {
path = path || router.app.$route.path || '/';
let cache = localStorage[path];
if (cache) {
cache = window.tnx.util.string.parseJson(cache);
if (typeof callback === 'function') {
callback.call(this, cache);
}
}
return path;
}
},
_storeCache: function (router, path, intervalId, model, ignoredFields) {
if (path && intervalId) {
let data = {};
if (Array.isArray(ignoredFields) && ignoredFields.length) {
Object.keys(model).forEach(key => {
if (!ignoredFields.contains(key)) {
data[key] = model[key];
}
});
} else {
data = model;
}
localStorage[path] = tnxvue.util.string.toJson({
intervalId: intervalId,
model: data,
ignored: ignoredFields,
});
}
},
saveCache: function (router, model) {
let intervalId;
let ignoredFields;
let path = this._readCache(router, undefined, function (cache) {
intervalId = cache.intervalId;
ignoredFields = cache.ignored;
});
this._storeCache(router, path, intervalId, model, ignoredFields);
},
stopCache: function (router, path) {
return this._readCache(router, path, function (cache) {
clearInterval(cache.intervalId);
});
},
clearCache: function (router) {
let path = this.stopCache(router);
if (path) {
delete localStorage[path];
}
},
/**
* 前端页面模型转换为后端命令模型,检查文件上传是否完成,去掉后端不需要的多余字段,转换多层嵌入字段数据使其符合服务端命令模型的基本要求
* @param model 前端页面模型
* @param refs 页面中的组件引用集
* @param validFieldNames 有效的字段名称集,如有指定则清除模型中的无效字段
*/
toCommandModel: function (vm, model, validFieldNames) {
let result = {};
if (model) {
if (vm.$refs) {
let refKeys = Object.keys(vm.$refs);
for (let refKey of refKeys) {
let ref = vm.$refs[refKey];
if (typeof ref.getStorageUrl === 'function') {
if (ref.validateUploaded() === false) {
return null;
}
}
}
}
let fieldNames = Object.keys(model);
for (let fieldName of fieldNames) {
if (!validFieldNames || !validFieldNames.length || validFieldNames.contains(fieldName)) {
if (fieldName.contains('__')) {
let path = fieldName.replace('__', '.');
tnxvue.util.object.setValue(result, path, model[fieldName]);
} else {
result[fieldName] = model[fieldName];
}
}
}
}
return result;
},
/**
* 转换多层嵌入字段数据使其符合前端页面模型的基本要求
* @param model 服务端视图模型
*/
toPageModel: function (model) {
let expanded = this._expandRefFields(model);
while (expanded) {
expanded = this._expandRefFields(model);
}
return model;
},
_expandRefFields: function (model) {
let expanded = false;
Object.keys(model).forEach(key => {
let value = model[key];
if (value && typeof value === 'object') {
Object.keys(value).forEach(refKey => {
model[key + '__' + refKey] = value[refKey];
});
delete model[key];
expanded = true;
}
});
return expanded;
}
});
/**
* 页面级缓存支持
*/
tnxvue.app.page.cache = {
_getName: function (key) {
return 'cache_' + key;
},
get: function (vm, key, defaultValue) {
let name = this._getName(key);
let cache = vm.$root[name];
if (cache === undefined) {
cache = defaultValue;
vm.$root[name] = cache;
}
return cache;
},
set: function (vm, key, value) {
let name = this._getName(key);
if (value === undefined) {
delete vm.$root[name];
} else {
vm.$root[name] = value;
}
}
}
Vue.use(tnxvue);
return tnxvue;
});