ZaiZai 1 year ago
parent
commit
10dd1479c2
2 changed files with 675 additions and 162 deletions
  1. 579 0
      src/global/components/table-form/index-bak.vue
  2. 96 162
      src/global/components/table-form/index.vue

+ 579 - 0
src/global/components/table-form/index-bak.vue

@@ -0,0 +1,579 @@
+<template>
+    <div
+        :id="`table-form-item-${keyId}`" v-loading="isLoading" :class="!isTableForm ? 'no-scroll-bar' : ''"
+        :style="tableFormStyle" class="hc-table-form-data-item"
+    >
+        <el-scrollbar v-if="isScroll" class="table-form-item-scrollbar">
+            <div :id="`table-form-${keyId}`" class="hc-excel-table-form" @click.capture="excelTableFormClick" />
+        </el-scrollbar>
+        <div v-else :id="`table-form-${keyId}`" class="hc-excel-table-form" @click.capture="excelTableFormClick" />
+        <div v-if="!isTableForm" class="hc-no-table-form">
+            <div class="table-form-no">
+                <img :src="notableform" alt="">
+                <div class="desc">
+                    {{ noTips }}
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { nextTick, onMounted, ref, watch } from 'vue'
+import HTableForm from '~src/plugins/HTableForm'
+import notableform from '~src/assets/view/notableform.svg'
+import { delStoreValue, getStoreValue, setStoreValue } from '~uti/storage'
+import { arrIndex, deepClone, getArrValue, getObjVal, isNullES, isString } from 'js-fast-way'
+
+//初始
+const props = defineProps({
+    pkey: [String, Number],
+    noTip: {
+        type: [String, Number],
+        default: '暂无表单数据',
+    },
+    html: String,
+    form: {
+        type: Object,
+        default: () => ({}),
+    },
+    cols: {
+        type: Array,
+        default: () => ([]),
+    },
+    loading: Boolean,
+    scroll: {
+        type: Boolean,
+        default: true,
+    },
+    height: {
+        type: String,
+        default: '100%',
+    },
+    width: {
+        type: String,
+        default: 'auto',
+    },
+    isMessage: {
+        type: Boolean,
+        default: true,
+    },
+    pid: {
+        type: String,
+        default: '',
+    },
+})
+
+//事件
+const emit = defineEmits(['rightTap', 'render', 'excelBodyTap'])
+//初始变量
+const keyId = ref(props.pkey)
+const noTips = ref(props.noTip)
+const isScroll = ref(props.scroll)
+const isLoading = ref(props.loading)
+const activeKey = ref(props.pid)
+
+//表单数据
+const excelHtml = ref(props.html)
+const excelForm = ref(props.form)
+const colsKeys = ref(props.cols)
+
+//样式
+const tableFormApp = ref(null)
+const tableFormVM = ref(null)
+const tableFormStyle = ref('')
+const isTableForm = ref(false)
+
+//监听
+watch(() => [
+    props.pkey, props.noTip, props.scroll, props.loading, props.width, props.height, props.pid,
+], ([pkey, tip, scroll, loading, width, height, pid]) => {
+    keyId.value = pkey
+    noTips.value = tip
+    isScroll.value = scroll
+    isLoading.value = loading
+    activeKey.value = pid
+    setItemStyle(width, height)
+})
+
+//html变动
+watch(() => props.html, (html) => {
+    excelHtml.value = html
+    setExcelHtml()
+})
+
+//深度监听变动的对象数据
+watch(() => [
+    props.form,
+], ([val]) => {
+    excelForm.value = val
+    //console.log('表单数据变动', val)
+    setPickerKey()
+    setFormData(val)
+}, {
+    deep: true,
+})
+
+//深度监听按键切换的key列表
+watch(() => [
+    props.cols,
+], ([cols]) => {
+    colsKeys.value = cols
+}, {
+    deep: true,
+})
+
+
+//渲染完成
+onMounted(() => {
+    setItemStyle(props.width, props.height)
+    setPickerKey()
+    nextTick(() => {
+        getExcelHtml()
+    })
+})
+
+
+//设置样式
+const setItemStyle = (width, height) => {
+    tableFormStyle.value = `width: ${width}; height: ${height};`
+}
+
+//表单被点击
+const excelTableFormClick = () => {
+    emit('excelBodyTap', keyId.value)
+}
+
+//获取已填写的数据
+const setPickerKey = () => {
+    HTableForm.setPickerKey(excelForm.value)
+}
+
+const setExcelHtml = () => {
+    setPickerKey()
+    //先卸载
+    if (tableFormApp.value) {
+        tableFormApp.value?.unmount()
+        tableFormApp.value = null
+        nextTick(() => {
+            getExcelHtml()
+        })
+    } else {
+        getExcelHtml()
+    }
+}
+
+//获取模板标签数据
+const getExcelHtml = async () => {
+    const pkeyId = keyId.value, pid = activeKey.value
+    const temp = isString(excelHtml.value) ? excelHtml.value : ''
+    if (isNullES(temp) || isNullES(pkeyId)) {
+        isTableForm.value = false
+        excelForm.value.isRenderForm = false
+        emit('render', excelForm.value)
+        return
+    }
+    await getAppTableId(`table-form-${pkeyId}`)
+    //渲染表单
+    isTableForm.value = true
+    const { app, vm } = HTableForm.createForm({
+        pid: pid,
+        template: temp,
+        keys: colsKeys.value,
+        tableForm: excelForm.value,
+        appId: `#table-form-${pkeyId}`,
+        onFormDataChange: (form) => {
+            excelForm.value = form
+            emit('render', form)
+        },
+        onRight: (event, KeyName) => {
+            onRightClick(pkeyId, event, KeyName, pid)
+        },
+        //表单正则效验
+        /*onBlur: (event, key, reg, val, msg) => {
+            setTableFormBlurReg(pkeyId, event, key, reg, val, msg, pid)
+        },*/
+        onLeftClick: (key) => {
+            setShiftTableForm(key, pid)
+        },
+    })
+    tableFormApp.value = app
+    tableFormVM.value = vm
+    excelForm.value.isRenderForm = true
+    await nextTick()
+    HTableForm.setByClassKeyup(colsKeys.value, pid)
+    emit('render', excelForm.value)
+}
+
+//检查元素是否存在
+const getAppTableId = async (key, maxAttempts = 10, interval = 500) => {
+    return new Promise((resolve, reject) => {
+        let attempts = 0
+        const checkElement = () => {
+            const dom = document.getElementById(key)
+            if (dom) {
+                resolve(dom)
+            } else if (++attempts < maxAttempts) {
+                setTimeout(checkElement, interval)
+            } else {
+                reject(new Error(`在${maxAttempts}次尝试后未找到元素 ${key}`))
+            }
+        }
+        checkElement()
+    })
+}
+
+//正则效验
+const formRegExpJson = ref({})
+const setTableFormBlurReg = (pkeyId, event, key, reg, val, msg, pid) => {
+    const dom = document.getElementById(key)?.parentElement ?? ''
+    if (dom) {
+        if (val && reg) {
+            let regx = new RegExp(reg)
+            let state = regx.test(val)
+            if (state) {
+                delete formRegExpJson.value[key]
+                HTableForm.setFormStyle(key, 'hc-red-border', pid)
+            } else {
+                formRegExpJson.value[key] = { key, reg, val, msg, state }
+                HTableForm.setFormStyle(key, 'hc-red-border', pid, true)
+                window?.$message?.warning(msg)
+            }
+        } else {
+            delete formRegExpJson.value[key]
+            HTableForm.setFormStyle(key, 'hc-red-border', pid)
+        }
+    } else {
+        delete formRegExpJson.value[key]
+    }
+}
+
+//鼠标右键事件
+const onRightClick = async (pkeyId, event, KeyName, pid) => {
+    //取光标位置
+    const specialDom = await HTableForm.getQuerySelector(KeyName, pid)
+    //const specialDom = document.getElementById(KeyName + "")
+    const startPos = specialDom?.selectionStart || 0
+    const endPos = specialDom?.selectionEnd || 0
+    emit('rightTap', { event, KeyName, startPos, endPos, pkeyId, pid })
+}
+
+const isCtrlKey = ref(false)
+const checkKeyList = ref([])
+
+//设置选择数据
+const setShiftTableForm = (key, pid) => {
+    if (isCtrlKey.value) {
+        const form = excelForm.value
+        const keys = checkKeyList.value
+        const index = arrIndex(keys, 'key', key)
+        if (index === -1) {
+            keys.push({ key: key, val: form[key] })
+        } else {
+            keys.splice(index, 1)
+        }
+        checkKeyList.value = keys
+        HTableForm.setCheckKeyStyle(key, pid, index !== -1)
+    }
+}
+
+//按下ctrl键
+const setIsCtrlKey = (state) => {
+    isCtrlKey.value = state
+}
+
+//按下复制快捷键
+const setCopyKeyList = (event) => {
+    const pid = activeKey.value
+    const keysList = deepClone(checkKeyList.value)
+    if (keysList.length > 0) {
+        event.preventDefault()
+        setStoreValue('TableFormCopyKeys', keysList)
+        keysList.forEach(item => {
+            HTableForm.setCheckKeyStyle(item['key'], pid, true)
+        })
+        checkKeyList.value = []
+    }
+}
+
+//按下粘贴快捷键
+const setPasteKeyList = async (event) => {
+    let keysList = getArrValue(getStoreValue('TableFormCopyKeys'))
+    const checkList = checkKeyList.value
+    if (checkList.length > 0) {
+        event.preventDefault()
+        //粘贴多个
+        if (checkList.length > 1 && keysList.length > 1) {
+            await setMultipleCheckValue(checkList, keysList)
+        }
+        //粘贴单个复制
+        if (checkList.length > 1 && keysList.length === 1) {
+            await setSingleCopyValue(checkList, keysList)
+        }
+        //复制单个粘贴
+        if (checkList.length === 1 && keysList.length >= 1) {
+            await setCopySingleValue(checkList, keysList)
+        }
+        //清除缓存
+        checkKeyList.value = []
+        delStoreValue('TableFormCopyKeys')
+    }
+}
+
+//复制单个粘贴
+const setCopySingleValue = async (checkList, keysList) => {
+    const keys = deepClone(keysList)
+    let form_val = '', key = checkList[0]['key']
+    for (let i = 0; i < keys.length; i++) {
+        const val = keys[i]['val']
+        form_val = form_val ? form_val + '、' + val : val
+        keys.splice(0, 1) //删除第一个元素
+    }
+    console.log('key', key)
+    console.log('form_val', form_val)
+    await setTableFormInfoValue(key, form_val)
+    HTableForm.setCheckKeyStyle(key, activeKey.value, true)
+}
+
+//粘贴单个复制
+const setSingleCopyValue = async (checkList, keysList) => {
+    const keys = deepClone(keysList)
+    const form_val = keys[0]['val']
+    for (let i = 0; i < checkList.length; i++) {
+        const { key } = checkList[i]
+        await setTableFormInfoValue(key, form_val)
+        HTableForm.setCheckKeyStyle(key, activeKey.value, true)
+    }
+    keys.splice(0, 1) //删除第一个元素
+}
+
+//粘贴多个
+const setMultipleCheckValue = async (checkList, keysList) => {
+    const keys = deepClone(keysList)
+    for (let i = 0; i < checkList.length; i++) {
+        const { key, val } = checkList[i]
+        if (keys.length > 0) {
+            const form_val = keys[0]['val']
+            await setTableFormInfoValue(key, form_val ? form_val : val)
+            keys.splice(0, 1) //删除第一个元素
+        } else {
+            await setTableFormInfoValue(key, val)
+        }
+        HTableForm.setCheckKeyStyle(key, activeKey.value, true)
+    }
+}
+
+//设置表单数据
+const setTableFormInfoValue = async (key, value) => {
+    return new Promise((resolve) => {
+        setTimeout(() => {
+            excelForm.value[key] = value
+            resolve(true)
+        }, 100)
+    })
+}
+
+//获取表单数据
+const getFormData = () => {
+    return excelForm.value
+}
+
+//设置表单数据
+const setFormData = (data) => {
+    excelForm.value = data
+    tableFormVM.value?.setFormData(excelForm.value)
+}
+
+//获取表单效验数据
+const getRegExpJson = () => {
+    return deepClone(formRegExpJson.value)
+}
+
+//正则效验
+const isFormRegExp = async () => {
+    const isRegExp = !!getObjVal(formRegExpJson.value)
+    if (!isRegExp) {
+        return true
+    } else {
+        window?.$message?.warning('请先修改完红色输入框的数据')
+        return false
+    }
+}
+
+//卸载渲染
+const unmountHtml = () => {
+    if (tableFormApp.value) {
+        tableFormApp.value?.unmount()
+    }
+}
+
+// 暴露出去
+defineExpose({
+    getFormData,
+    setFormData,
+    getRegExpJson,
+    isFormRegExp,
+    setExcelHtml,
+    unmountHtml,
+    setIsCtrlKey,
+    setCopyKeyList,
+    setPasteKeyList,
+})
+</script>
+
+<style lang="scss">
+//插入特殊字符弹窗的输入框
+.hc-table-form-data-item .hc-excel-table-form td,
+.hc-table-form-data-item .hc-excel-table-form td .el-input .el-input__wrapper .el-input__inner,
+.el-form-item.special-form-item .el-form-item__content .el-input .el-input__wrapper .el-input__inner {
+    font-family: "hc-eudc", hc-sans, 宋体, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important;
+}
+
+.hc-table-form-data-item {
+    position: relative;
+    padding: 12px;
+    height: 100%;
+    overflow: hidden;
+    background-color: white;
+    &.no-scroll-bar .el-scrollbar {
+        display: none;
+    }
+    .hc-excel-table-form {
+        position: relative;
+        display: flex;
+        padding: 10px;
+        justify-content: center;
+        td {
+            position: relative;
+            padding: 6px;
+            background-clip: padding-box;
+            .el-input {
+                clear: both;
+                color: #606266;
+                border-radius: 3px;
+                height: $initials;
+                background-color: #ffffff !important;
+                .el-input__wrapper {
+                    background-color: inherit;
+                    caret-color: var(--el-color-primary);
+                }
+                .el-input__suffix-inner {
+                    width: 18px;
+                }
+            }
+            .el-textarea {
+                width: 100%;
+                height: 100%;
+                .el-textarea__inner {
+                    min-height: $initials;
+                    background-color: #ffffff;
+                    border-radius: 3px;
+                    color: #606266;
+                    height: 100%;
+                    caret-color: var(--el-color-primary);
+                }
+            }
+            //日期选择框
+            .el-date-editor.el-input .el-input__wrapper,
+            .el-date-editor.el-date-editor--datetimerange.el-input__wrapper {
+                width: 100%;
+                height: $initials;
+                clear: both;
+            }
+            //焦点
+            .el-input .el-input__wrapper.is-focus, .el-input .el-input__wrapper:hover,
+            .el-textarea .el-textarea__inner:hover {
+                box-shadow: 0 0 0 1.5px var(--el-input-focus-border-color) inset;
+                background-color: #eddac4;
+            }
+            //公式
+            &[gscolor] {
+                .el-input, .el-textarea .el-textarea__inner {
+                    background-color: #dcdcdc !important;
+                }
+                .el-date-editor.el-input__wrapper{
+                    background-color: #dcdcdc !important;
+                }
+                .el-select .el-select__wrapper {
+                    background: #dcdcdc !important;
+                }
+            }
+            //文本选中颜色
+            .el-input .el-input__wrapper input,
+            .el-textarea textarea {
+                &::selection {
+                    background: var(--el-color-primary-light-9);
+                    color: var(--el-color-primary);
+                }
+                &::-moz-selection {
+                    background: var(--el-color-primary-light-9);
+                    color: var(--el-color-primary);
+                }
+            }
+            //下拉框
+            .el-select {
+                width: 100%;
+                height: $initials;
+                clear: both;
+            }
+            .el-select .el-select__wrapper.is-focused {
+                background: var(--el-color-primary-light-9);
+                color: var(--el-color-primary);
+            }
+            //表单上传
+            .hc-upload-table-form {
+                position: absolute;
+                top: 6px;
+                bottom: 6px;
+                left: 6px;
+                right: 6px;
+                .el-upload {
+                    height: 100%;
+                }
+            }
+        }
+        //列合并的单元格
+        td[rowspan] {
+            height: $initials;
+        }
+        //非输入框颜色
+        td:not([titlexx]), td[titlexx*=''],
+        td:not([title]), td[title*=''] {
+            background-color: white !important;
+            user-select: none;
+        }
+    }
+    .hc-no-table-form {
+        position: relative;
+        height: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        .table-form-no {
+            position: relative;
+            img {
+                width: 350px;
+            }
+            .desc {
+                text-align: center;
+                font-size: 20px;
+                color: #aaa;
+            }
+        }
+    }
+}
+
+.hc-red-border {
+    &.el-textarea__inner, &.el-input .el-input__wrapper {
+        --el-input-border-color: #fe0000 !important;
+        box-shadow: 0 0 0 2px #fe0000 inset !important;
+    }
+}
+
+.hc-green-border {
+    &.el-textarea__inner, &.el-input .el-input__wrapper {
+        --el-input-border-color: #1ECC95 !important;
+        box-shadow: 0 0 0 2px #1ECC95 inset !important;
+    }
+}
+</style>

+ 96 - 162
src/global/components/table-form/index.vue

@@ -1,8 +1,5 @@
 <template>
-    <div
-        :id="`table-form-item-${keyId}`" v-loading="isLoading" :class="!isTableForm ? 'no-scroll-bar' : ''"
-        :style="tableFormStyle" class="hc-table-form-data-item"
-    >
+    <div :id="`table-form-item-${keyId}`" v-loading="isLoading" :class="{ 'no-scroll-bar': !isTableForm }" :style="tableFormStyle" class="hc-table-form-data-item">
         <el-scrollbar v-if="isScroll" class="table-form-item-scrollbar">
             <div :id="`table-form-${keyId}`" class="hc-excel-table-form" @click.capture="excelTableFormClick" />
         </el-scrollbar>
@@ -10,148 +7,105 @@
         <div v-if="!isTableForm" class="hc-no-table-form">
             <div class="table-form-no">
                 <img :src="notableform" alt="">
-                <div class="desc">
-                    {{ noTips }}
-                </div>
+                <div class="desc">{{ noTips }}</div>
             </div>
         </div>
     </div>
 </template>
 
 <script setup>
-import { nextTick, onMounted, ref, watch } from 'vue'
+import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
 import HTableForm from '~src/plugins/HTableForm'
 import notableform from '~src/assets/view/notableform.svg'
 import { delStoreValue, getStoreValue, setStoreValue } from '~uti/storage'
 import { arrIndex, deepClone, getArrValue, getObjVal, isNullES, isString } from 'js-fast-way'
 
-//初始
+// Props 定义
 const props = defineProps({
-    pkey: [String, Number],
-    noTip: {
-        type: [String, Number],
-        default: '暂无表单数据',
-    },
+    pkey: { type: [String, Number], required: true },
+    noTip: { type: String, default: '暂无表单数据' },
     html: String,
-    form: {
-        type: Object,
-        default: () => ({}),
-    },
-    cols: {
-        type: Array,
-        default: () => ([]),
-    },
+    form: { type: Object, default: () => ({}) },
+    cols: { type: Array, default: () => ([]) },
     loading: Boolean,
-    scroll: {
-        type: Boolean,
-        default: true,
-    },
-    height: {
-        type: String,
-        default: '100%',
-    },
-    width: {
-        type: String,
-        default: 'auto',
-    },
-    isMessage: {
-        type: Boolean,
-        default: true,
-    },
-    pid: {
-        type: String,
-        default: '',
-    },
+    scroll: { type: Boolean, default: true },
+    height: { type: String, default: '100%' },
+    width: { type: String, default: 'auto' },
+    isMessage: { type: Boolean, default: true },
+    pid: { type: String, default: '' },
 })
 
-//事件
+// Emits 定义
 const emit = defineEmits(['rightTap', 'render', 'excelBodyTap'])
-//初始变量
+
+// 响应式数据
 const keyId = ref(props.pkey)
 const noTips = ref(props.noTip)
 const isScroll = ref(props.scroll)
 const isLoading = ref(props.loading)
 const activeKey = ref(props.pid)
-
-//表单数据
 const excelHtml = ref(props.html)
 const excelForm = ref(props.form)
 const colsKeys = ref(props.cols)
-
-//样式
 const tableFormApp = ref(null)
 const tableFormVM = ref(null)
-const tableFormStyle = ref('')
 const isTableForm = ref(false)
+const isCtrlKey = ref(false)
+const checkKeyList = ref([])
+const formRegExpJson = ref({})
 
-//监听
-watch(() => [
-    props.pkey, props.noTip, props.scroll, props.loading, props.width, props.height, props.pid,
-], ([pkey, tip, scroll, loading, width, height, pid]) => {
-    keyId.value = pkey
-    noTips.value = tip
-    isScroll.value = scroll
-    isLoading.value = loading
-    activeKey.value = pid
-    setItemStyle(width, height)
-})
+// 计算属性
+const tableFormStyle = computed(() => `width: ${props.width}; height: ${props.height};`)
+
+// 监听属性变化
+watch(() => [props.pkey, props.noTip, props.scroll, props.loading, props.pid],
+    ([pkey, tip, scroll, loading, pid]) => {
+        keyId.value = pkey
+        noTips.value = tip
+        isScroll.value = scroll
+        isLoading.value = loading
+        activeKey.value = pid
+    })
 
-//html变动
 watch(() => props.html, (html) => {
     excelHtml.value = html
     setExcelHtml()
 })
 
-//深度监听变动的对象数据
-watch(() => [
-    props.form,
-], ([val]) => {
+watch(() => props.form, (val) => {
     excelForm.value = val
-    //console.log('表单数据变动', val)
     setPickerKey()
     setFormData(val)
-}, {
-    deep: true,
-})
+}, { deep: true })
 
-//深度监听按键切换的key列表
-watch(() => [
-    props.cols,
-], ([cols]) => {
+watch(() => props.cols, (cols) => {
     colsKeys.value = cols
-}, {
-    deep: true,
-})
+}, { deep: true })
 
-
-//渲染完成
+// 生命周期钩子
 onMounted(() => {
-    setItemStyle(props.width, props.height)
     setPickerKey()
     nextTick(() => {
         getExcelHtml()
     })
 })
 
+onUnmounted(() => {
+    // 清理工作
+    unmountHtml()
+})
 
-//设置样式
-const setItemStyle = (width, height) => {
-    tableFormStyle.value = `width: ${width}; height: ${height};`
-}
-
-//表单被点击
+// 方法定义
 const excelTableFormClick = () => {
     emit('excelBodyTap', keyId.value)
 }
 
-//获取已填写的数据
 const setPickerKey = () => {
     HTableForm.setPickerKey(excelForm.value)
 }
 
 const setExcelHtml = () => {
     setPickerKey()
-    //先卸载
     if (tableFormApp.value) {
         tableFormApp.value?.unmount()
         tableFormApp.value = null
@@ -163,7 +117,6 @@ const setExcelHtml = () => {
     }
 }
 
-//获取模板标签数据
 const getExcelHtml = async () => {
     const pkeyId = keyId.value, pid = activeKey.value
     const temp = isString(excelHtml.value) ? excelHtml.value : ''
@@ -173,39 +126,41 @@ const getExcelHtml = async () => {
         emit('render', excelForm.value)
         return
     }
-    await getAppTableId(`table-form-${pkeyId}`)
-    //渲染表单
-    isTableForm.value = true
-    const { app, vm } = HTableForm.createForm({
-        pid: pid,
-        template: temp,
-        keys: colsKeys.value,
-        tableForm: excelForm.value,
-        appId: `#table-form-${pkeyId}`,
-        onFormDataChange: (form) => {
-            excelForm.value = form
-            emit('render', form)
-        },
-        onRight: (event, KeyName) => {
-            onRightClick(pkeyId, event, KeyName, pid)
-        },
-        //表单正则效验
-        /*onBlur: (event, key, reg, val, msg) => {
-            setTableFormBlurReg(pkeyId, event, key, reg, val, msg, pid)
-        },*/
-        onLeftClick: (key) => {
-            setShiftTableForm(key, pid)
-        },
-    })
-    tableFormApp.value = app
-    tableFormVM.value = vm
-    excelForm.value.isRenderForm = true
-    await nextTick()
-    HTableForm.setByClassKeyup(colsKeys.value, pid)
-    emit('render', excelForm.value)
+
+    try {
+        await getAppTableId(`table-form-${pkeyId}`)
+        isTableForm.value = true
+        const { app, vm } = HTableForm.createForm({
+            pid,
+            template: temp,
+            keys: colsKeys.value,
+            tableForm: excelForm.value,
+            appId: `#table-form-${pkeyId}`,
+            onFormDataChange: (form) => {
+                excelForm.value = form
+                emit('render', form)
+            },
+            onRight: (event, KeyName) => {
+                onRightClick(pkeyId, event, KeyName, pid)
+            },
+            onLeftClick: (key) => {
+                setShiftTableForm(key, pid)
+            },
+        })
+        tableFormApp.value = app
+        tableFormVM.value = vm
+        excelForm.value.isRenderForm = true
+        await nextTick()
+        HTableForm.setByClassKeyup(colsKeys.value, pid)
+        emit('render', excelForm.value)
+    } catch (error) {
+        console.error('Error in getExcelHtml:', error)
+        isTableForm.value = false
+        excelForm.value.isRenderForm = false
+        emit('render', excelForm.value)
+    }
 }
 
-//检查元素是否存在
 const getAppTableId = async (key, maxAttempts = 10, interval = 500) => {
     return new Promise((resolve, reject) => {
         let attempts = 0
@@ -216,17 +171,15 @@ const getAppTableId = async (key, maxAttempts = 10, interval = 500) => {
             } else if (++attempts < maxAttempts) {
                 setTimeout(checkElement, interval)
             } else {
-                reject(new Error(`在${maxAttempts}次尝试后未找到元素 ${key}`))
+                reject(new Error(`Element ${key} not found after ${maxAttempts} attempts`))
             }
         }
         checkElement()
     })
 }
 
-//正则效验
-const formRegExpJson = ref({})
 const setTableFormBlurReg = (pkeyId, event, key, reg, val, msg, pid) => {
-    const dom = document.getElementById(key)?.parentElement ?? ''
+    const dom = document.getElementById(key)?.parentElement
     if (dom) {
         if (val && reg) {
             let regx = new RegExp(reg)
@@ -237,7 +190,9 @@ const setTableFormBlurReg = (pkeyId, event, key, reg, val, msg, pid) => {
             } else {
                 formRegExpJson.value[key] = { key, reg, val, msg, state }
                 HTableForm.setFormStyle(key, 'hc-red-border', pid, true)
-                window?.$message?.warning(msg)
+                if (props.isMessage) {
+                    window?.$message?.warning(msg)
+                }
             }
         } else {
             delete formRegExpJson.value[key]
@@ -248,20 +203,17 @@ const setTableFormBlurReg = (pkeyId, event, key, reg, val, msg, pid) => {
     }
 }
 
-//鼠标右键事件
 const onRightClick = async (pkeyId, event, KeyName, pid) => {
-    //取光标位置
-    const specialDom = await HTableForm.getQuerySelector(KeyName, pid)
-    //const specialDom = document.getElementById(KeyName + "")
-    const startPos = specialDom?.selectionStart || 0
-    const endPos = specialDom?.selectionEnd || 0
-    emit('rightTap', { event, KeyName, startPos, endPos, pkeyId, pid })
+    try {
+        const specialDom = await HTableForm.getQuerySelector(KeyName, pid)
+        const startPos = specialDom?.selectionStart || 0
+        const endPos = specialDom?.selectionEnd || 0
+        emit('rightTap', { event, KeyName, startPos, endPos, pkeyId, pid })
+    } catch (error) {
+        console.error('Error in onRightClick:', error)
+    }
 }
 
-const isCtrlKey = ref(false)
-const checkKeyList = ref([])
-
-//设置选择数据
 const setShiftTableForm = (key, pid) => {
     if (isCtrlKey.value) {
         const form = excelForm.value
@@ -277,12 +229,10 @@ const setShiftTableForm = (key, pid) => {
     }
 }
 
-//按下ctrl键
 const setIsCtrlKey = (state) => {
     isCtrlKey.value = state
 }
 
-//按下复制快捷键
 const setCopyKeyList = (event) => {
     const pid = activeKey.value
     const keysList = deepClone(checkKeyList.value)
@@ -296,46 +246,35 @@ const setCopyKeyList = (event) => {
     }
 }
 
-//按下粘贴快捷键
 const setPasteKeyList = async (event) => {
     let keysList = getArrValue(getStoreValue('TableFormCopyKeys'))
     const checkList = checkKeyList.value
     if (checkList.length > 0) {
         event.preventDefault()
-        //粘贴多个
         if (checkList.length > 1 && keysList.length > 1) {
             await setMultipleCheckValue(checkList, keysList)
-        }
-        //粘贴单个复制
-        if (checkList.length > 1 && keysList.length === 1) {
+        } else if (checkList.length > 1 && keysList.length === 1) {
             await setSingleCopyValue(checkList, keysList)
-        }
-        //复制单个粘贴
-        if (checkList.length === 1 && keysList.length >= 1) {
+        } else if (checkList.length === 1 && keysList.length >= 1) {
             await setCopySingleValue(checkList, keysList)
         }
-        //清除缓存
         checkKeyList.value = []
         delStoreValue('TableFormCopyKeys')
     }
 }
 
-//复制单个粘贴
 const setCopySingleValue = async (checkList, keysList) => {
     const keys = deepClone(keysList)
     let form_val = '', key = checkList[0]['key']
     for (let i = 0; i < keys.length; i++) {
         const val = keys[i]['val']
         form_val = form_val ? form_val + '、' + val : val
-        keys.splice(0, 1) //删除第一个元素
+        keys.splice(0, 1)
     }
-    console.log('key', key)
-    console.log('form_val', form_val)
     await setTableFormInfoValue(key, form_val)
     HTableForm.setCheckKeyStyle(key, activeKey.value, true)
 }
 
-//粘贴单个复制
 const setSingleCopyValue = async (checkList, keysList) => {
     const keys = deepClone(keysList)
     const form_val = keys[0]['val']
@@ -344,10 +283,9 @@ const setSingleCopyValue = async (checkList, keysList) => {
         await setTableFormInfoValue(key, form_val)
         HTableForm.setCheckKeyStyle(key, activeKey.value, true)
     }
-    keys.splice(0, 1) //删除第一个元素
+    keys.splice(0, 1)
 }
 
-//粘贴多个
 const setMultipleCheckValue = async (checkList, keysList) => {
     const keys = deepClone(keysList)
     for (let i = 0; i < checkList.length; i++) {
@@ -355,7 +293,7 @@ const setMultipleCheckValue = async (checkList, keysList) => {
         if (keys.length > 0) {
             const form_val = keys[0]['val']
             await setTableFormInfoValue(key, form_val ? form_val : val)
-            keys.splice(0, 1) //删除第一个元素
+            keys.splice(0, 1)
         } else {
             await setTableFormInfoValue(key, val)
         }
@@ -363,7 +301,6 @@ const setMultipleCheckValue = async (checkList, keysList) => {
     }
 }
 
-//设置表单数据
 const setTableFormInfoValue = async (key, value) => {
     return new Promise((resolve) => {
         setTimeout(() => {
@@ -373,41 +310,38 @@ const setTableFormInfoValue = async (key, value) => {
     })
 }
 
-//获取表单数据
 const getFormData = () => {
     return excelForm.value
 }
 
-//设置表单数据
 const setFormData = (data) => {
     excelForm.value = data
     tableFormVM.value?.setFormData(excelForm.value)
 }
 
-//获取表单效验数据
 const getRegExpJson = () => {
     return deepClone(formRegExpJson.value)
 }
 
-//正则效验
 const isFormRegExp = async () => {
     const isRegExp = !!getObjVal(formRegExpJson.value)
     if (!isRegExp) {
         return true
     } else {
-        window?.$message?.warning('请先修改完红色输入框的数据')
+        if (props.isMessage) {
+            window?.$message?.warning('请先修改完红色输入框的数据')
+        }
         return false
     }
 }
 
-//卸载渲染
 const unmountHtml = () => {
     if (tableFormApp.value) {
         tableFormApp.value?.unmount()
     }
 }
 
-// 暴露出去
+// 暴露方法
 defineExpose({
     getFormData,
     setFormData,