import { createApp } from 'vue/dist/vue.esm-bundler.js' import { getTokenHeader } from '~src/api/request/header' import { isArray, isNullES, toParse } from 'js-fast-way' //自定义组件或二次封装的组件 import HcTableFormUpload from '~com/plugins/table-form/hc-form-upload.vue' import HcFormSelectSearch from '~com/plugins/table-form/hc-form-select-search.vue' import HcFormSelectSearch2 from '~com/plugins/table-form/hc-form-select-search2.vue' import HcFormCheckboxGroup from '~com/plugins/table-form/hc-form-checkbox-group.vue' import ElTimePicker from '~com/plugins/table-form/hc-time-picker.vue' import ElDatePicker from '~com/plugins/table-form/hc-date-picker-1.vue' import ElRadioGroup from '~com/plugins/table-form/hc-form-radio-group.vue' import HcEchart from '~com/plugins/table-form/echart.vue' //修改过的组件 import { ElOption, ElSelect } from 'z-element-plus' import ElementPlus from 'element-plus' import zhCn from 'element-plus/es/locale/lang/zh-cn' const components = { ElSelect, ElOption, ElDatePicker, ElTimePicker, HcTableFormUpload, ElRadioGroup, HcFormSelectSearch, HcFormSelectSearch2, HcFormCheckboxGroup, HcEchart, } //表单渲染 export default class HTableForm { static tableFormApp = null static tableFormVM = null static createForm({ template, tableForm, keys, appId, pid, onRight, onBlur, onLeftClick, onFormDataChange, onChartRefs }) { const _this = this const app = createApp({ //自定义组件,需要把饿了么的组件,或者自定义组件手动传递进来绑定,否则渲染时,自定义组件不会生效 components, data() { return { getTokenHeader: getTokenHeader(), formData: tableForm, } }, //监听数据,伪双向绑定(v-model) watch: { formData: { handler(obj) { tableForm = obj this.formDataChange(obj) }, deep: true, }, }, methods: { //表单数据改变 formDataChange(obj) { if (onFormDataChange) { onFormDataChange(obj) } }, //改变表单数据 setFormData(obj) { this.formData = obj }, //鼠标右键菜单 contextmenuClick(a, b, c, d, e, f, event) { event.preventDefault() }, //鼠标右键事件 RightClick(a, b, c, d, e, f, event) { setTimeout(() => { const KeyName = event?.target?.getAttribute('keyname') || '' if (onRight) { event.preventDefault() onRight(event, KeyName) } }, 100) }, //焦点事件 getInformation() { }, //日期选择事件 datePickerChange(val, key) { this.formData[key] = val }, //上传完成 formUploadSuccess({ src, key }) { this.formData[key] = src }, //删除上传的文件 delTableFormFile(key) { this.formData[key] = '' }, //失去焦点事件 getRegularExpression(event, reg, msg, a, b, leng, type, c, d) { const KeyName = event?.target?.getAttribute('keyname') || '' if (onBlur) { onBlur(event, KeyName, reg, this.formData[KeyName], msg, leng, type, c, d) } }, //远程搜索处理 formRemoteChange(data) { Object.keys(data).forEach(key => { this.formData[key] = data[key] }) }, //多选框处理 checkboxGroupChange({ key, val }) { this.formData[key] = val }, //键盘事件 上键 keyupShiftUp(event) { _this.setKeyupData(event, 'up', keys, pid) }, //键盘事件 下键 keyupShiftDown(event) { _this.setKeyupData(event, 'down', keys, pid) }, //键盘事件 左键 keyupShiftLeft(event) { _this.setKeyupData(event, 'left', keys, pid) }, //键盘事件 右键 keyupShiftRight(event) { _this.setKeyupData(event, 'right', keys, pid) }, //日期时间框键盘事件 dateKeydown({ type, name }) { _this.setKeyupData(name, type, keys, pid) }, //输入左键点击事件 inputLeftClick(event, key) { setTimeout(() => { if (onLeftClick) { onLeftClick(key) } }, 100) }, setChartRefs(el, pKeyId, key) { if (onChartRefs) onChartRefs(el, pKeyId, key) }, }, //html标签数据 template, }) // 饿了么UI框架 app.use(ElementPlus, { locale: zhCn, }) const vm = app.mount(appId) this.tableFormApp = app this.tableFormVM = vm return { app, vm } } //处理日期范围数据 static setPickerKey(data) { const pickerKey = data['pickerKey'] || '' if (pickerKey) { const pickerKeys = pickerKey.split(',') for (let i = 0; i < pickerKeys.length; i++) { const val = data[pickerKeys[i]] || '' if (val) { const dataVal = val.replace(/'/g, '"') data[pickerKeys[i]] = toParse(dataVal) || [] } else { data[pickerKeys[i]] = [] } } } return data } //处理日期时间框的切换事件 static setByClassKeyup(keys, pid = '') { try { let poppers = document.getElementsByClassName('hc-table-form-date-picker') for (let i = 0; i < poppers.length; i++) { let item = poppers[i], key = '' const ids = item.getAttribute('class').split('-form-id-') if (ids.length >= 1) { key = ids[1] } if (ids) { let panels = item.getElementsByClassName('el-picker-panel__content') this.setElementsEvent(panels, key, keys, pid) } } } catch (e) { console.log(e) } } //设置事件 static setElementsEvent(elements, key, keys, pid = '') { if (elements.length > 0) { const _this = this elements[0].addEventListener('keydown', e => { e.stopPropagation() if (e.key === 'ArrowUp') { _this.setKeyupData({ target: { id: key } }, 'up', keys, pid) } else if (e.key === 'ArrowDown') { _this.setKeyupData({ target: { id: key } }, 'down', keys, pid) } else if (e.key === 'ArrowLeft') { _this.setKeyupData({ target: { id: key } }, 'left', keys, pid) } else if (e.key === 'ArrowRight') { _this.setKeyupData({ target: { id: key } }, 'right', keys, pid) } }, { capture: true, }) } } //计算上下左右快捷键的 static setKeyupData({ target }, type, keys, pid = '') { const key = target.id //处理快捷键数据和事件 if (key && type && isArray(keys)) { //计算当前的位置 let left = -1, top = -1 for (let i = 0; i < keys.length; i++) { if (isArray(keys[i])) { const index = keys[i].findIndex(id => id === key) if (index !== -1) { left = index top = i break } } } if (type === 'up') { //向上移动 if (top > 0) { let keyId = '' const tops = keys[top - 1] const keyLength = tops.length - 1 if (keyLength < left) { keyId = tops[keyLength] } else { keyId = tops[left] } this.setElementFocus(keyId, pid) } } else if (type === 'down') { //向下移动 const tops = keys.length - 1 if (tops > top) { let keyId = '' const tops = keys[top + 1] const keyLength = tops.length - 1 if (keyLength < left) { keyId = tops[keyLength] } else { keyId = tops[left] } this.setElementFocus(keyId, pid) } } else if (type === 'left') { //向左移动 if (left > 0) { const keyId = keys[top][left - 1] this.setElementFocus(keyId, pid) } } else if (type === 'right') { //向右移动 const lefts = keys[top] const leftLength = lefts.length - 1 if (leftLength > left) { const keyId = lefts[left + 1] this.setElementFocus(keyId, pid) } } } } //设置元素焦点 static setElementFocus(key, pid) { if (key) { try { this.getQuerySelector(key, pid)?.focus() } catch { /* empty */ } } } //获取表单元素 static async getQuerySelector(key, pid = '') { let dom if (pid) { dom = document.querySelector(`#${pid} #${key.toString()}`) } else { dom = document.getElementById(key.toString()) } return dom } //设置表单样式 static async setFormStyle(key, name = 'hc-red-border', pid = '', add = false) { const dom = await this.getQuerySelector(key, pid) const parent = dom?.parentElement ?? '' if (dom?.tagName === 'INPUT') { const parentElement = parent?.parentElement ?? '' this.setFormClass(parentElement, name, add) } else if (dom?.tagName === 'TEXTAREA') { this.setFormClass(dom, name, add) } } static setFormClass(dom, name = 'hc-red-border', add = false) { const classStr = dom.getAttribute('class') const classArr = classStr.split(' ') const index = classArr.indexOf(name) if (index === -1 && add) { classArr.push(name) } else if (index !== -1 && add === false) { classArr.splice(index, 1) } dom.setAttribute('class', classArr.join(' ')) } //设置选中样式 static setCheckKeyStyle(key, pid = '', remove = false) { if (remove) { this.setFormStyle(key, 'hc-green-border', pid).then() } else { this.setFormStyle(key, 'hc-green-border', pid, true).then() } } //设置全局按键监听 static setOnEventKey({ onCtrlDown, onCtrlDownC, onCtrlDownV, onCtrlUp }) { //全局按键按下监听 document.onkeydown = (event) => { if (onCtrlDown || onCtrlDownC || onCtrlDownV) { const { key, ctrlKey, metaKey } = event const isCtrl = window.isMac ? metaKey : window.isWin ? ctrlKey : false //window.$HcLog('全局按键', 'isCtrl', isCtrl) //按下ctrl键 或 control 键 if (onCtrlDown && isCtrl && key === window?.isCtrl) { onCtrlDown(event) } //按下复制快捷键 if (onCtrlDownC && isCtrl && key === 'c') { onCtrlDownC(event) } //按下粘贴快捷键 if (onCtrlDownV && isCtrl && key === 'v') { onCtrlDownV(event) } } } //全局键盘放开监听 document.onkeyup = (event) => { if (onCtrlUp) { const { key, ctrlKey, metaKey } = event const isCtrl = window.isMac ? metaKey : window.isWin ? ctrlKey : false if (!isCtrl && key === window?.isCtrl) { onCtrlUp(event) } } } } //卸载全局按键监听 static unmountEventKey() { document.onkeydown = null document.onkeyup = null } //卸载实例 static unmountFormApp() { if (this.tableFormApp) { this.tableFormApp?.unmount() this.tableFormApp = null } } }