UNPKG

@truenewx/tnxvue2

Version:

互联网技术解决方案:Vue2扩展支持

299 lines (285 loc) 11 kB
// 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; });