import Vue from 'vue' import utils from '@/hotent-ui-util.js' import FormMath from '@/math.js' import dialog from '@/api/dialogApi.js' import CustomQuery from '@/components/eipControl/bus/CustomQuery.js' import _ from 'lodash' import req from '@/request.js' import app from '@/main.js' // 表单tr中根据隐藏字段动态合并单元格的指令 Vue.directive('pinyin', { // 指令的定义 componentUpdated: function(el, binding, vnode) { let context = vnode.context // 防抖 let debounceGetPinyin = _.debounce(newVal => { // disabled 或者 readonly 时 不需要请求 if (el.__vue__.disabled || el.__vue__.readonly) return req .request({ url: `${window.context.uc}/base/tools/v1/getPinyin`, method: 'GET', params: {chinese: newVal, type: `${binding.modifiers.full ? 1 : 0}`} }) .then(res => { if (res.data.state) { let modelExp = vnode.data.model.expression.replace( /\[\w+.?\$\w+\]/g, '[' + binding.arg + ']' ) utils.setValueByPath(context, modelExp, res.data.value) app.$nextTick(() => { app.$validator.validate() }) } }) .finally(() => {}) }, 300) if (binding.value && binding.value != binding.oldValue) { debounceGetPinyin(binding.value) } // context.$watch(watchExp(), function (newVal, oldVal) { // if (newVal && newVal != oldVal) { // debounceGetPinyin(newVal); // } // }, { // deep: true, // immediate: false // }); } }) Vue.directive('permit', { componentUpdated: function(el, binding) { if (el.tagName !== 'TR') { throw 'v-permit指令只能用在tr元素上.' } if (!binding.value || binding.value.constructor !== Number) { throw 'v-permit指令的值只能是大于0的数字.' } el.removeAttribute('hidden') // tr中没有子元素时,删除tr自身 if (el.cells.length == 0) { el.setAttribute('hidden', 'hidden') } else if (el.cells.length < binding.value) { let colspan = binding.value - el.cells.length + 1 // 设置colspan实现单元格合并 el.cells[el.cells.length - 1].setAttribute('colspan', colspan) } else if (el.cells.length === binding.value) { for (var i = 0, c; (c = el.cells[i++]); ) { c.removeAttribute('colspan') } } } }) // 表单指令,会在表单的vue实例上添加一个map,用以存放数学运算的表达式 Vue.directive('form', { bind: function(el, binding, vnode) { const inst = vnode.context if (inst && !inst.hasOwnProperty('watchMap')) { inst['watchMap'] = new Map() } } }) // 判断输入框是否作为计算字段,是则添加监听 Vue.directive('express', { componentUpdated: function(el, binding, vnode) { const inst = vnode.context if (!inst.$vnode.data.model) { return } const elAttr = inst.$vnode.componentOptions.propsData.modelExpression if (elAttr && !inst._expressInit) { inst._expressInit = true // 子表每一行数据作用域所在的dom元素 let {subScopeEl} = utils.getSubScopeElAndIndex(el) let subname = null let aliasElAttr = null // 子表数据,需要找到配置了data-subname的元素 if (subScopeEl) { subname = subScopeEl.dataset['subname'] if (!subname) { throw '无法获取到当前子表前缀' } const elAttrAry = elAttr.split('.'), elAttrArySize = elAttrAry.length if (elAttrArySize < 1) { throw `子表中的数据绑定表达式${elAttr}错误` } aliasElAttr = `${subname}.${elAttrAry[elAttrArySize - 1]}` } const p = utils.getOnlineFormInstance(inst) if ( p.watchMap && (p.watchMap.has(elAttr) || p.watchMap.has(aliasElAttr)) ) { if ( !inst._watchers.some(m => { return m.expression === 'inputVal' }) ) { inst.$watch( 'inputVal', function(newVal, oldVal, farewell) { if (newVal !== oldVal) { const expList = p.watchMap.get(elAttr) || p.watchMap.get(aliasElAttr) expList.forEach(item => { let result = 0 const t = item.target // 当在子表单行中时,而且不是对子表进行列运算时,判定为子表当前行内运算 if (subScopeEl && !/.*?\[\{.*?\}\].*?/.test(item.exp)) { // 组件销毁时,不再计算子表单行的公式 if (farewell) { return } const index = subScopeEl.dataset['index'] if (index === undefined) { throw '获取不到当前子表行的索引,无法完成计算.' } result = FormMath.calcSubExpValue( item.exp, p, subname, index ) p.$emit(t, {result, index}) } else { result = FormMath.calcExpValue(item.exp, p) p.$emit(t, {result}) } }) } }, {immediate: true} ) } } } } }) // 自定义对话框 v-auth-set-event Vue.directive('auth-set-event', { bind: function(el, bindings, vnode) { const htAuthSetEvent = el.getAttribute('attr') if (!htAuthSetEvent) return var defaultPermissionList = [] dialog.getPermissionList(result => { defaultPermissionList = result }) /** * 设置设置权限。 * ownerNameJson 格式。 * [{type:"everyone",title:"所有人"},{type:"user",title:"用户",id:"1,2",name:"ray,tom"}] */ const setAuth = function() { var conf = { right: ownerNameJson, permissionList: defaultPermissionList } //授权选择器 vnode.child.AuthSettingShow(conf) } var ownerNameJson = [] var initData = bindings.value if (initData) { ownerNameJson = JSON.parse(initData) // showLable(ownerNameJson); } //对话框初始化监听 el.childNodes[2].onclick = function() { setAuth() } } }) Vue.directive('parseTemplete', { bind: function(el, binding, vnode) { var s = JSON.stringify el.innerHTML = 'name: ' + s(binding.name) + '
' + 'value: ' + s(binding.value) + '
' + 'expression: ' + s(binding.expression) + '
' + 'argument: ' + s(binding.arg) + '
' + 'modifiers: ' + s(binding.modifiers) + '
' + 'vnode keys: ' + Object.keys(vnode).join(', ') } }) Vue.directive('alsCharts', { inserted(el, binding, vnode) { const inst = binding.context function init(data) { if ( !( data.value && data.value !== true && data.value.constructor == Array && data.value[0].legend ) ) { return } var options = data.value[0] var height = getDivHeight(el) - 35 var wrap = $('
').css({ width: '100%', height: height }) $(el).css({ display: 'block', width: '100%', height: height }) // const echarts = require('echarts'); // var myChart = echarts.init(el); // inst.$root.$on("resize", () => { // myChart.resize();//监测图表自适应 // }); var option = { title: { text: options.name, subtext: options.subtext, top: 12 }, tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } }, calculable: true, legend: { x: 'right', data: options.legend }, toolbox: { show: true, orient: 'vertical', y: 'center', right: 20, itemGap: 13, feature: { mark: {show: true}, dataView: {show: true, readOnly: false}, magicType: {show: true, type: ['line', 'bar', 'stack', 'tiled']}, restore: {show: true}, saveAsImage: {show: true}, dataZoom: { yAxisIndex: 'none' }, dataView: { show: true, readOnly: true, optionToContent: function(opt) { //console.info(opt); var axisData = opt.xAxis[0].data var series = opt.series var tdHeaders = '' //表头 series.forEach(function(item) { tdHeaders += '' + item.name + '' //组装表头 }) var table = '
' + tdHeaders + '' var tdBodys = '' //数据 var colors = ['#FFFFFF', '#F5F5F5'] for (let i = 0, l = axisData.length; i < l; i++) { for (let j = 0; j < series.length; j++) { tdBodys += '' //组装表数据 } var curColor = colors[i % 2] table += '' + tdBodys + '' tdBodys = '' } table += '
' + series[j].data[i] + '
' + axisData[i] + '
' return table } } } }, calculable: true, grid: { y: 80, y2: 40, x2: 40 }, xAxis: [ { type: 'category', data: options.xAxis } ], yAxis: [ { type: 'value' } ], //x轴数据区域缩放组件--暂时不添加 /*dataZoom: [ { type: 'slider', show: true, xAxisIndex: [0], start: 1, end: 35 }, { type: 'inside', xAxisIndex: [0], start: 1, end: 35 }, ],*/ series: options.series } // myChart.setOption(option, true); } //获取当前栏目的高度 function getDivHeight(el) { if (el) { var pHeight = $(el) .parent() .height() if (pHeight < 1) { return getDivHeight($(el).parent()) } } else { return 340 } return pHeight } init(binding) } }) Vue.directive('opinion', { bind: function(el, binding, vnode) { if (binding.value) { while (binding.value.indexOf('\n') != -1) { binding.value = binding.value.replace('\n', '
') } el.innerHTML = binding.value } } }) Vue.directive('iframetrigger', { bind: function(el, binding, vnode) { el.onload = function() { $('body').trigger('formLoaded') } $('body').bind('formLoaded', function(e) { var frm = $('#frmFrame')[0] window.addEventListener('message', function(e) { if (e.data && e.data.constructor == Object && e.data.type == 'height') { frm.style.visibility = 'hidden' // 提前还原高度 frm.setAttribute('height', 'auto') setTimeout(function() { frm.setAttribute('height', e.data.height) frm.style.visibility = 'visible' $(frm).trigger('mouseover') }, 0) } }) }) } }) Vue.directive('methodauth', { bind: function(el, binding, vnode) { let allMethod = window.sessionStorage.allMethod let methodAuth = window.sessionStorage.methodAuth let elAuth = binding.expression let allMethodArray = allMethod.split(',') let methodAuthArray = methodAuth.split(',') // 无权限则隐藏按钮 if ( $.inArray(elAuth, methodAuthArray) == -1 && $.inArray(elAuth, allMethodArray) ) { $(el).css('display', 'none') } } }) // 注册全局公式计算组件 Vue.directive('formula', { bind(el, binding, vnode) { let propsData = vnode.context.$options.propsData //初始化的时候,如果没有值,则用公式的计算结果来赋值给当前字段 let oldVal = utils.getValueByPath(propsData, binding.value.bindPath) if (propsData && !oldVal) { utils.setValueByPath( propsData, binding.value.bindPath, binding.value.value ) vnode.context.$forceUpdate() } }, update(el, binding, vnode, oldVnode) { if (binding.oldValue.value instanceof Date) { if (binding.oldValue.value.getTime() !== binding.value.value.getTime()) { utils.setValueByPath( vnode.context.$options.propsData, binding.value.bindPath, binding.value.value ) vnode.context.$forceUpdate() } } else { if (binding.oldValue.value != binding.value.value) { utils.setValueByPath( vnode.context.$options.propsData, binding.value.bindPath, binding.value.value ) vnode.context.$forceUpdate() } } } }) Vue.directive('mapping', { update(el, binding, vnode, oldVnode) { if (binding.oldValue !== binding.value) { Vue.set(el.__vue__, 'inputVal', binding.value) } } }) Vue.directive('dynamic-options', { bind(el, binding, vnode) { let exp = null if (binding.expression) { exp = utils.parseToJson(binding.expression) } const inst = vnode.context if (inst) { // 上一次动态选项查询条件 inst.preDynamicLoadParams = null inst.$on('dynamic-options:load', (alias, params) => { params = params || {} // 是否执行查询 let doLoad = true if (exp && exp.cache) { // 相比上一次,查询参数是否有变化 const changed = !utils.objectEquals(inst.preDynamicLoadParams, params) if (changed) { doLoad = true inst.preDynamicLoadParams = params } else { doLoad = false } } doLoad && CustomQuery.load(alias, params).then(data => { inst.$emit('dynamic-options:update', alias, data) }) }) } } }) //用于上级值变化后,下级内容需要清空 Vue.directive('watch-parent', { update(el, binding, vnode) { if (binding.value && binding.value.pid) { for (var key in binding.value.pid) { const inst = vnode.context const instParent = utils.getOnlineFormInstance(inst) instParent.$watch( () => { return utils.getValueByPath( instParent, binding.value.pid[key], binding.value.index ) }, function(newVal, oldVal, farewell) { if (newVal !== oldVal) { inst.inputVal = '' } } ) } } } }) Vue.directive('related-query', { bind(el, binding, vnode) { const inst = vnode.context let exp = null if (binding.expression) { exp = utils.parseToJson(binding.expression) } if (inst) { // 上一次关联查询条件(一个组件可以绑定多个关联查询,) inst.preRelatedQueryParams = {} inst.$on('related-query:load', (alias, params, resultBind) => { params = params || {} // 是否执行查询 let doLoad = true if (exp && exp.cache) { // 相比上一次,查询参数是否有变化 const changed = !utils.objectEquals( inst.preRelatedQueryParams[alias], params ) if (changed) { doLoad = true inst.preRelatedQueryParams[alias] = params } else { doLoad = false } } doLoad && CustomQuery.load(alias, params).then(data => { if ( data && data.constructor == Array && data.length > 0 && resultBind && resultBind.constructor == Object ) { // 获取当前控件是否在子表某行中 let {index} = utils.getSubScopeElAndIndex(el) const pInst = utils.getOnlineFormInstance(inst) // 关联查询值回绑时,默认获取返回的第一条记录 const singleData = data[0] Object.keys(resultBind).forEach(k => { const path = resultBind[k] // 主表 if (index == null) { utils.setValueByPath(pInst, path, singleData[k]) } // 子表 else { utils.setValueByPath(pInst, path, singleData[k], index) } }) } }) }) } } }) //表格横向拖拽 Vue.directive('tableDrag', { inserted: function(el) { const currentElement = el.getElementsByClassName('el-table__body-wrapper')[0] || el const tagNames = ['span', 'input', 'textarea', 'aside'] if (currentElement) { currentElement.onmousedown = function(event) { const currentTagNames = event.target.tagName.toLowerCase() if (tagNames.includes(currentTagNames)) return currentElement.style.cursor = 'grab' let gapX = event.clientX let startX = el.scrollLeft document.onmousemove = function(e) { let x = e.clientX - gapX currentElement.scrollLeft = startX - x return false } document.onmouseup = function(e) { document.onmousemove = null document.onmouseup = null } } } } }) //用于控制子表或孙表单行permission Vue.directive('permission-line', { bind(el, binding, vnode) { if (binding.value) { const inst = vnode.context let idxObj = utils.getSubScopeElAndIndex(el) let paths = binding.value.split('_') let boType = paths[0] let idStr = binding.value + '_' + idxObj.index //孙表时,获取孙表所属子表序号 if (boType == 'sun' && idxObj.subScopeEl) { const subIdxObj = utils.getSubScopeElAndIndex( idxObj.subScopeEl.parentElement ) idStr = binding.value + '_' + subIdxObj.index + '_' + idxObj.index } if ( inst.permission && inst.permission['subFields'] && inst.permission['subFields'][idStr] ) { setTimeout(function() { if (el.__vue__) { el.__vue__.permission_sub = inst.permission['subFields'][idStr] el.__vue__.sub_work = true } }, 0) } } }, update(el, binding, vnode) { if (binding.value) { const inst = vnode.context let idxObj = utils.getSubScopeElAndIndex(el) let paths = binding.value.split('_') let boType = paths[0] let idStr = binding.value + '_' + idxObj.index //孙表时,获取孙表所属子表序号 if (boType == 'sun' && idxObj.subScopeEl) { const subIdxObj = utils.getSubScopeElAndIndex( idxObj.subScopeEl.parentElement ) idStr = binding.value + '_' + subIdxObj.index + '_' + idxObj.index } if ( inst.permission && inst.permission['subFields'] && inst.permission['subFields'][idStr] ) { setTimeout(function() { if (el.__vue__) { el.__vue__.permission_sub = inst.permission['subFields'][idStr] } }, 0) } } } }) //用于控制子表或孙表单行permission lable标签 Vue.directive('permission-line-lable', { bind(el, binding, vnode) { if (binding.value) { const inst = vnode.context let idxObj = utils.getSubScopeElAndIndex(el) let paths = binding.value.split('_') let boType = paths[0] let idStr = binding.value + '_' + idxObj.index //孙表时,获取孙表所属子表序号 if (boType == 'sun' && idxObj.subScopeEl) { const subIdxObj = utils.getSubScopeElAndIndex( idxObj.subScopeEl.parentElement ) idStr = binding.value + '_' + subIdxObj.index + '_' + idxObj.index } if ( inst.permission && inst.permission['subFields'] && inst.permission['subFields'][idStr] ) { setTimeout(function() { el.parentElement.hidden = inst.permission['subFields'][idStr] == 'n' ? true : false }, 0) } } }, update(el, binding, vnode) { if (binding.value) { const inst = vnode.context let idxObj = utils.getSubScopeElAndIndex(el) let paths = binding.value.split('_') let boType = paths[0] let idStr = binding.value + '_' + idxObj.index //孙表时,获取孙表所属子表序号 if (boType == 'sun' && idxObj.subScopeEl) { const subIdxObj = utils.getSubScopeElAndIndex( idxObj.subScopeEl.parentElement ) idStr = binding.value + '_' + subIdxObj.index + '_' + idxObj.index } if ( inst.permission && inst.permission['subFields'] && inst.permission['subFields'][idStr] ) { setTimeout(function() { el.parentElement.hidden = inst.permission['subFields'][idStr] == 'n' ? true : false }, 0) } } } }) // 用于点击指定区域外执行某功能 Vue.directive('click-outside', { bind(el, bindings, vnode) { el.handler = function(e) { if (!el.contains(e.target)) { let method = bindings.expression vnode.context[method]() } } document.addEventListener('click', el.handler) }, unbind(el) { // 可用于解除事件绑定 document.removeEventListener('click', el.handler) } }) // 指令定义 Vue.directive('charge', { bind(el, binding, vnode) { const vm = vnode.context const toggleDisplay = value => { el.style.display = value === 1 ? '' : 'none' } toggleDisplay(vm.$store.state.user.currentUserDetail?.user.isCharge || 0) // 保存函数,以便在指令解绑时调用 el.__vueUnWatch__ = vm.$store.watch( state => state.user.currentUserDetail?.user.isCharge, isCharge => toggleDisplay(isCharge) ) }, unbind(el) { // 清理监听器,防止内存泄漏 if (el.__vueUnWatch__) { el.__vueUnWatch__() delete el.__vueUnWatch__ } } }) var directive = {} export default directive