ZaiZai 1 year ago
parent
commit
fb6388986c
1 changed files with 228 additions and 146 deletions
  1. 228 146
      src/plugins/HTableForm.js

+ 228 - 146
src/plugins/HTableForm.js

@@ -2,7 +2,7 @@ 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'
@@ -12,27 +12,49 @@ 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 {
+// 定义键盘事件常量
+const ARROW_UP = 'ArrowUp'
+const ARROW_DOWN = 'ArrowDown'
+const ARROW_LEFT = 'ArrowLeft'
+const ARROW_RIGHT = 'ArrowRight'
 
+/**
+ * HTableForm类:用于创建和管理表单
+ */
+export default class HTableForm {
     static tableFormApp = null
     static tableFormVM = null
 
+    /**
+     * 创建表单
+     * @param {Object} options - 配置选项
+     * @param {string} options.template - Vue模板
+     * @param {Object} options.tableForm - 表单数据
+     * @param {Array} options.keys - 键值数组
+     * @param {string} options.appId - 应用ID
+     * @param {string} options.pid - 父级ID
+     * @param {Function} options.onRight - 右键点击回调
+     * @param {Function} options.onBlur - 失焦回调
+     * @param {Function} options.onLeftClick - 左键点击回调
+     * @param {Function} options.onFormDataChange - 表单数据变化回调
+     * @param {Function} options.onChartRefs - 图表引用回调
+     * @returns {Object} 返回创建的Vue应用和VM实例
+     */
     static createForm({ template, tableForm, keys, appId, pid, onRight, onBlur, onLeftClick, onFormDataChange, onChartRefs }) {
-        const _this = this
+        if (!template || !tableForm || !keys || !appId) {
+            throw new Error('Missing required parameters')
+        }
+
         const app = createApp({
-            //自定义组件,需要把饿了么的组件,或者自定义组件手动传递进来绑定,否则渲染时,自定义组件不会生效
             components,
             data() {
                 return {
@@ -40,7 +62,6 @@ export default class HTableForm {
                     formData: tableForm,
                 }
             },
-            //监听数据,伪双向绑定(v-model)
             watch: {
                 formData: {
                     handler(obj) {
@@ -51,22 +72,22 @@ export default class HTableForm {
                 },
             },
             methods: {
-                //表单数据
+                // 表单数据变化处理
                 formDataChange(obj) {
                     if (onFormDataChange) {
                         onFormDataChange(obj)
                     }
                 },
-                //改变表单数据
+                // 设置表单数据
                 setFormData(obj) {
                     this.formData = obj
                 },
-                //鼠标右键菜单
-                contextmenuClick(a, b, c, d, e, f, event) {
+                // 右键菜单点击处理
+                contextmenuClick(event) {
                     event.preventDefault()
                 },
-                //鼠标右键事件
-                RightClick(a, b, c, d, e, f, event) {
+                // 右键点击处理
+                RightClick(event) {
                     setTimeout(() => {
                         const KeyName = event?.target?.getAttribute('keyname') || ''
                         if (onRight) {
@@ -75,59 +96,60 @@ export default class HTableForm {
                         }
                     }, 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) {
+                // 正则表达式验证
+                getRegularExpression(event, reg, msg, leng, type) {
                     const KeyName = event?.target?.getAttribute('keyname') || ''
                     if (onBlur) {
-                        onBlur(event, KeyName, reg, this.formData[KeyName], msg, leng, type, c, d)
+                        onBlur(event, KeyName, reg, this.formData[KeyName], msg, leng, type)
                     }
                 },
-                //远程搜索处理
+                // 远程表单变化处理
                 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)
+                    HTableForm.setKeyupData(event, 'up', keys, pid)
                 },
-                //键盘事件 下键
+                // 下键处理
                 keyupShiftDown(event) {
-                    _this.setKeyupData(event, 'down', keys, pid)
+                    HTableForm.setKeyupData(event, 'down', keys, pid)
                 },
-                //键盘事件 左键
+                // 左键处理
                 keyupShiftLeft(event) {
-                    _this.setKeyupData(event, 'left', keys, pid)
+                    HTableForm.setKeyupData(event, 'left', keys, pid)
                 },
-                //键盘事件 右键
+                // 右键处理
                 keyupShiftRight(event) {
-                    _this.setKeyupData(event, 'right', keys, pid)
+                    HTableForm.setKeyupData(event, 'right', keys, pid)
                 },
-                //日期时间框键盘事件
+                // 日期键盘事件处理
                 dateKeydown({ type, name }) {
-                    _this.setKeyupData(name, type, keys, pid)
+                    HTableForm.setKeyupData({ target: { id: name } }, type, keys, pid)
                 },
-                //输入左键点击事件
+                // 输入框左键点击处理
                 inputLeftClick(event, key) {
                     setTimeout(() => {
                         if (onLeftClick) {
@@ -135,24 +157,29 @@ export default class HTableForm {
                         }
                     }, 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 }
     }
 
-    //处理日期范围数据
+    /**
+     * 设置日期选择器的键值
+     * @param {Object} data - 包含pickerKey的数据对象
+     * @returns {Object} 处理后的数据对象
+     */
     static setPickerKey(data) {
         const pickerKey = data['pickerKey'] || ''
         if (pickerKey) {
@@ -170,40 +197,55 @@ export default class HTableForm {
         return data
     }
 
-    //处理日期时间框的切换事件
+    /**
+     * 设置日期选择器的键盘事件
+     * @param {Array} keys - 键值数组
+     * @param {string} pid - 父级ID
+     */
     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 poppers = document.querySelectorAll('.hc-table-form-date-picker')
+            poppers.forEach(item => {
+                let 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')
+                    const panels = item.querySelectorAll('.el-picker-panel__content')
                     this.setElementsEvent(panels, key, keys, pid)
                 }
-            }
+            })
         } catch (e) {
-            console.log(e)
+            console.error('Error in setByClassKeyup:', e)
         }
     }
 
-    //设置事件
+    /**
+     * 为元素设置键盘事件
+     * @param {NodeList} elements - 需要设置事件的元素列表
+     * @param {string} key - 键值
+     * @param {Array} keys - 键值数组
+     * @param {string} pid - 父级ID
+     */
     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)
+                switch (e.key) {
+                    case ARROW_UP:
+                        _this.setKeyupData({ target: { id: key } }, 'up', keys, pid)
+                        break
+                    case ARROW_DOWN:
+                        _this.setKeyupData({ target: { id: key } }, 'down', keys, pid)
+                        break
+                    case ARROW_LEFT:
+                        _this.setKeyupData({ target: { id: key } }, 'left', keys, pid)
+                        break
+                    case ARROW_RIGHT:
+                        _this.setKeyupData({ target: { id: key } }, 'right', keys, pid)
+                        break
                 }
             }, {
                 capture: true,
@@ -211,12 +253,16 @@ export default class HTableForm {
         }
     }
 
-    //计算上下左右快捷键的
+    /**
+     * 设置键盘事件数据
+     * @param {Object} target - 目标对象
+     * @param {string} type - 事件类型
+     * @param {Array} keys - 键值数组
+     * @param {string} pid - 父级ID
+     */
     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])) {
@@ -228,150 +274,186 @@ export default class HTableForm {
                     }
                 }
             }
-            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]
+
+            let newKey = ''
+            switch (type) {
+                case 'up':
+                    if (top > 0) {
+                        const tops = keys[top - 1]
+                        newKey = tops[Math.min(left, tops.length - 1)]
                     }
-                    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]
+                    break
+                case 'down':
+                    if (top < keys.length - 1) {
+                        const bottoms = keys[top + 1]
+                        newKey = bottoms[Math.min(left, bottoms.length - 1)]
                     }
-                    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)
-                }
+                    break
+                case 'left':
+                    if (left > 0) {
+                        newKey = keys[top][left - 1]
+                    }
+                    break
+                case 'right':
+                    if (left < keys[top].length - 1) {
+                        newKey = keys[top][left + 1]
+                    }
+                    break
+            }
+            if (newKey) {
+                this.setElementFocus(newKey, pid)
             }
         }
     }
 
-    //设置元素焦点
+    /**
+     * 设置元素焦点
+     * @param {string} key - 元素的key
+     * @param {string} pid - 父级ID
+     */
     static setElementFocus(key, pid) {
         if (key) {
             try {
-                this.getQuerySelector(key, pid)?.focus()
-            } catch { /* empty */ }
+                const element = this.getQuerySelector(key, pid)
+                if (element) {
+                    element.focus()
+                }
+            } catch (e) {
+                console.error('Error in setElementFocus:', e)
+            }
         }
     }
 
-    //获取表单元素
-    static async getQuerySelector(key, pid = '') {
-        let dom
+    /**
+     * 获取查询选择器
+     * @param {string} key - 元素的key
+     * @param {string} pid - 父级ID
+     * @returns {Element|null} 返回查询到的元素或null
+     */
+    static getQuerySelector(key, pid = '') {
         if (pid) {
-            dom = document.querySelector(`#${pid} #${key.toString()}`)
+            return document.querySelector(`#${pid} #${key.toString()}`)
         } else {
-            dom = document.getElementById(key.toString())
+            return document.getElementById(key.toString())
         }
-        return dom
     }
 
-    //设置表单样式
+    /**
+     * 设置表单样式
+     * @param {string} key - 元素的key
+     * @param {string} name - 样式名称
+     * @param {string} pid - 父级ID
+     * @param {boolean} add - 是否添加样式
+     */
     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') {
+        if (!dom) return
+
+        const parent = dom.parentElement
+        if (dom.tagName === 'INPUT') {
+            const parentElement = parent?.parentElement
+            if (parentElement) {
+                this.setFormClass(parentElement, name, add)
+            }
+        } else if (dom.tagName === 'TEXTAREA') {
             this.setFormClass(dom, name, add)
         }
     }
 
+    /**
+     * 设置表单类名
+     * @param {Element} dom - DOM元素
+     * @param {string} name - 类名
+     * @param {boolean} add - 是否添加类名
+     */
     static setFormClass(dom, name = 'hc-red-border', add = false) {
-        const classStr = dom.getAttribute('class')
+        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) {
+        } else if (index !== -1 && !add) {
             classArr.splice(index, 1)
         }
         dom.setAttribute('class', classArr.join(' '))
     }
 
-    //设置选中样式
+    /**
+     * 设置选中键的样式
+     * @param {string} key - 元素的key
+     * @param {string} pid - 父级ID
+     * @param {boolean} remove - 是否移除样式
+     */
     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()
-        }
+        this.setFormStyle(key, 'hc-green-border', pid, !remove)
     }
 
-    //设置全局按键监听
+    /**
+     * 设置全局键盘事件
+     * @param {Object} options - 配置选项
+     * @param {Function} options.onCtrlDown - Ctrl键按下回调
+     * @param {Function} options.onCtrlDownC - Ctrl+C按下回调
+     * @param {Function} options.onCtrlDownV - Ctrl+V按下回调
+     * @param {Function} options.onCtrlUp - Ctrl键抬起回调
+     * @returns {Function} 返回一个用于清理事件监听器的函数
+     */
     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) {
+        const handleKeyDown = (event) => {
+            const { key, ctrlKey, metaKey } = event
+            const isCtrl = window.isMac ? metaKey : window.isWin ? ctrlKey : false
+
+            if (isCtrl) {
+                if (onCtrlDown && key === window?.isCtrl) {
                     onCtrlDown(event)
-                }
-                //按下复制快捷键
-                if (onCtrlDownC && isCtrl && key === 'c') {
+                } else if (onCtrlDownC && key === 'c') {
                     onCtrlDownC(event)
-                }
-                //按下粘贴快捷键
-                if (onCtrlDownV && isCtrl && key === 'v') {
+                } else if (onCtrlDownV && 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)
-                }
+
+        const handleKeyUp = (event) => {
+            const { key, ctrlKey, metaKey } = event
+            const isCtrl = window.isMac ? metaKey : window.isWin ? ctrlKey : false
+
+            if (!isCtrl && key === window?.isCtrl && onCtrlUp) {
+                onCtrlUp(event)
             }
         }
+
+        document.addEventListener('keydown', handleKeyDown)
+        document.addEventListener('keyup', handleKeyUp)
+
+        // 返回一个清理函数
+        return () => {
+            document.removeEventListener('keydown', handleKeyDown)
+            document.removeEventListener('keyup', handleKeyUp)
+        }
     }
 
-    //卸载全局按键监听
+    /**
+     * 卸载事件监听器(已废弃)
+     * 使用setOnEventKey返回的清理函数代替
+     */
     static unmountEventKey() {
+        // 这个方法现在不需要了,因为setOnEventKey返回了一个清理函数
         document.onkeydown = null
         document.onkeyup = null
     }
 
-    //卸载实例
+    /**
+     * 卸载表单应用
+     * 清理Vue应用实例和相关引用
+     */
     static unmountFormApp() {
         if (this.tableFormApp) {
-            this.tableFormApp?.unmount()
+            this.tableFormApp.unmount()
             this.tableFormApp = null
+            this.tableFormVM = null
         }
     }
-
 }
+
+//使用了奇乐AI(https://ai.qilepan.com/auth?type=register&invite=NjM4) claude-3.5模型,优化了本文件的代码。
+//2024年07月29日 09时31分