|
@@ -0,0 +1,380 @@
|
|
|
+import { nextTick } from 'vue'
|
|
|
+import { createApp } from 'vue/dist/vue.esm-bundler.js'
|
|
|
+import { getHeader } from 'hc-vue3-ui'
|
|
|
+import { isArray, 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' ElSelect, ElOption,
|
|
|
+
|
|
|
+import ElementPlus from 'element-plus'
|
|
|
+import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
|
|
+
|
|
|
+const components = {
|
|
|
+ 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: getHeader(),
|
|
|
+ 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,
|
|
|
+ })
|
|
|
+ nextTick(() => {
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|