Эх сурвалжийг харах

修改表单渲染核心组件

ZaiZai 2 жил өмнө
parent
commit
cfddf21f02

+ 590 - 0
src/components/table-form/bak.vue

@@ -0,0 +1,590 @@
+<template>
+    <div :id="`table-form-item-${keyId}`" v-loading="loading" :style="tableFormItemStyle"
+         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"/>
+        </el-scrollbar>
+        <div v-else :id="`table-form-${keyId}`" class="hc-excel-table-form"/>
+        <div v-if="isTableForm === false" class="hc-no-table-form">
+            <div class="table-form-no">
+                <img :src="notableform" alt=""/>
+                <div class="desc">暂无表单数据</div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import {ref, watch, onMounted, nextTick, onUnmounted} from "vue"
+import {useAppStore} from "~src/store";
+import HTableForm from "~src/plugins/HTableForm"
+import notableform from '~src/assets/view/notableform.svg'
+import {getStoreData, setStoreData, delStoreData} from "~uti/storage";
+import {getObjNullValue, isAsyncFunction, isString, getArrValue, deepClone, getIndex} from "vue-utils-plus"
+
+const useAppState = useAppStore()
+
+//初始
+const props = defineProps({
+    tid: { // 树节点
+        type: [String, Number],
+        default: ''
+    },
+    kid: { // pkeyId
+        type: [String, Number],
+        default: ''
+    },
+    classify: { // 类型
+        type: [String, Number],
+        default: ''
+    },
+    api: { //请求方法函数列表
+        type: Object,
+        default: () => ({
+            dataInfo: null,
+            bussCols: null,
+            excelHtml: null
+        })
+    },
+    height: { // 高度
+        type: String,
+        default: '100%'
+    },
+    width: { // 宽度
+        type: String,
+        default: 'auto'
+    },
+    scroll: { // 可否滚动
+        type: Boolean,
+        default: false
+    },
+    datas: { //变动的数据
+        type: Object,
+        default: () => ({})
+    },
+    nodeName: { // 表单名称
+        type: String,
+        default: ''
+    },
+})
+
+//初始变量
+const projectId = ref(useAppState.getProjectId)
+const contractId = ref(useAppState.getContractId)
+const keyId = ref(props.kid ? props.kid + '' : '')
+const treeId = ref(props.tid)
+const classify = ref(props.classify)
+const apis = ref(props.api)
+const tableFormItemStyle = ref('')
+const loading = ref(false)
+const isScroll = ref(props.scroll)
+const changeData = ref(props.datas)
+const nodeNames = ref(props.nodeName)
+
+//监听
+watch(() => [
+    useAppState.getProjectId,
+    useAppState.getContractId,
+    props.tid,
+    props.kid,
+    props.classify,
+    props.width,
+    props.height,
+    props.scroll,
+    props.nodeName
+], ([project_id, contract_id, tree_id, key_id, cid, width, height, scroll, nodeName]) => {
+    projectId.value = project_id
+    contractId.value = contract_id
+    treeId.value = tree_id
+    keyId.value = key_id ? key_id + '' : ''
+    classify.value = cid
+    isScroll.value = scroll
+    nodeNames.value = nodeName
+    setItemStyle(width, height)
+})
+
+//深度监听变动的对象数据
+watch(() => [
+    props.datas
+], ([data]) => {
+    changeData.value = data
+    setFormChangeData(data)
+}, {deep: true})
+
+//渲染完成
+onMounted(async () => {
+    let keys = []
+    loading.value = true
+    const {dataInfo, bussCols, excelHtml} = apis.value
+    setItemStyle(props.width, props.height)
+    //获取已填写的数据
+    if (isAsyncFunction(dataInfo)) {
+        await getTableFormInfo(keyId.value, dataInfo)
+    }
+    //按键key列表
+    if (isAsyncFunction(bussCols)) {
+        keys = await getHtmlBussColsApi(keyId.value, bussCols)
+    }
+    //渲染表单
+    if (isAsyncFunction(excelHtml)) {
+        await getExcelHtml(keyId.value, excelHtml, keys)
+    }
+    loading.value = false
+})
+
+const setFormChangeData = (data) => {
+    const form = tableFormInfo.value
+    tableFormInfo.value = {
+        ...form,
+        ...data
+    }
+    tableFormInfo.value = form
+}
+
+//设置样式
+const setItemStyle = (width, height) => {
+    tableFormItemStyle.value = `width: ${width}; height: ${height};`
+}
+
+//事件
+const emit = defineEmits(['rightTap', 'render'])
+
+//渲染状态变量
+const isTableForm = ref(false)
+const tableFormInfo = ref({})
+
+//获取表单初始数据
+const getFormDataInit = () => {
+    return {
+        projectId: projectId.value,
+        contractId: contractId.value,
+        classify: classify.value,
+        pkeyId: keyId.value,
+        nodeId: treeId.value,
+        isRenderForm: false,
+    }
+}
+
+//获取已填写的数据
+const getTableFormInfo = async (pkeyId, func) => {
+    if (pkeyId) {
+        const {error, code, data} = await func({
+            pkeyId: pkeyId
+        }, false)
+        const resData = getObjNullValue(data)
+        if (!error && code === 200 && resData) {
+            HTableForm.setPickerKey(resData)
+            tableFormInfo.value = {
+                ...resData,
+                ...getFormDataInit(),
+                ...changeData.value
+            }
+        } else {
+            tableFormInfo.value = {
+                ...getFormDataInit(),
+                ...changeData.value
+            }
+        }
+    } else {
+        tableFormInfo.value = {}
+        window?.$message?.warning('pkeyId为空')
+    }
+}
+
+//获取按键切换输入框的key列表
+const getHtmlBussColsApi = async (pkeyId, func) => {
+    if (pkeyId) {
+        const {error, code, data} = await func({
+            pkeyId: pkeyId
+        }, false)
+        if (!error && code === 200) {
+            let keys = getArrValue(data);
+            for (let i = 0; i < keys.length; i++) {
+                if (keys[i].length <= 0) {
+                    keys.splice(i, 1)
+                }
+            }
+            return keys;
+        } else {
+            return [];
+        }
+    } else {
+        return [];
+    }
+}
+
+//获取模板标签数据
+const getExcelHtml = async (pkeyId, func, keys) => {
+    if (pkeyId) {
+        const {error, code, data} = await func({
+            pkeyId: pkeyId
+        }, false)
+        const resData = isString(data) ? data || '' : ''
+        if (!error && code === 200 && resData) {
+            isTableForm.value = true
+            //渲染表单
+            HTableForm.createForm({
+                template: resData,
+                tableForm: tableFormInfo.value,
+                keys: keys,
+                appId: `#table-form-${pkeyId}`,
+                onRight: (event, KeyName) => {
+                    onRightClick(pkeyId, event, KeyName)
+                },
+                //表单正则效验
+                onBlur: (event, key, reg, val, msg) => {
+                    setTableFormBlurReg(pkeyId, event, key, reg, val, msg)
+                },
+                onLeftClick: (key) => {
+                    setShiftTableForm(key)
+                },
+            })
+            tableFormInfo.value.isRenderForm = true
+            await nextTick(() => {
+                HTableForm.setByClassKeyup(keys)
+            })
+        } else {
+            isTableForm.value = false
+            tableFormInfo.value.isRenderForm = false
+            window?.$message?.warning('暂无表单')
+        }
+    } else {
+        isTableForm.value = false
+        tableFormInfo.value.isRenderForm = false
+        window?.$message?.warning('pkeyId为空')
+    }
+    emit('render', tableFormInfo.value)
+}
+
+//正则效验
+const formRegExpJson = ref({})
+const setTableFormBlurReg = (pkeyId, event, key, reg, val, msg) => {
+    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')
+            } else {
+                formRegExpJson.value[key] = {key, reg, val, msg, state}
+                HTableForm.setFormStyle(key, 'hc-red-border', true)
+                window?.$message?.warning(msg)
+            }
+        } else {
+            delete formRegExpJson.value[key]
+            HTableForm.setFormStyle(key, 'hc-red-border')
+        }
+    } else {
+        delete formRegExpJson.value[key]
+    }
+}
+
+
+//鼠标右键事件
+const onRightClick = (pkeyId, event, KeyName) => {
+    //取光标位置
+    const specialDom = document.getElementById(KeyName + "")
+    const startPos = specialDom?.selectionStart || 0
+    const endPos = specialDom?.selectionEnd || 0
+    emit('rightTap', {event, KeyName, startPos, endPos, pkeyId})
+}
+
+const isCtrlKey = ref(false)
+const checkKeyList = ref([])
+const copyKeyList = ref(getStoreData('TableFormCopyKeyList') || [])
+
+//设置选择数据
+const setShiftTableForm = (key) => {
+    if (isCtrlKey.value) {
+        const form = tableFormInfo.value
+        const keys = checkKeyList.value
+        const index = getIndex(keys, 'key', key)
+        if (index === -1) {
+            keys.push({key: key, val: form[key]})
+        } else {
+            keys.splice(index, 1)
+        }
+        checkKeyList.value = keys
+        HTableForm.setCheckKeyStyle(key, index !== -1)
+    }
+}
+
+//全局按键按下监听
+document.onkeydown = async (event) => {
+    const {key, ctrlKey} = event
+    //按下ctrl键
+    if (ctrlKey && key === 'Control') {
+        isCtrlKey.value = true
+    }
+    //按下复制快捷键
+    if (ctrlKey && key === 'c') {
+        const keysList = deepClone(checkKeyList.value)
+        if (keysList.length > 0) {
+            event.preventDefault()
+            setStoreData('TableFormCopyKeyList', keysList)
+            copyKeyList.value = keysList
+            keysList.forEach(item => {
+                HTableForm.setCheckKeyStyle(item['key'], true)
+            })
+            checkKeyList.value = []
+        }
+    }
+    //按下粘贴快捷键
+    if (ctrlKey && key === 'v') {
+        const keysList = deepClone(copyKeyList.value)
+        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 = []
+            copyKeyList.value = []
+            delStoreData('TableFormCopyKeyList')
+        }
+    }
+}
+
+//复制单个粘贴
+const setCopySingleValue = async (checkList, keysList) => {
+    let form_val = '', key = checkList[0]['key']
+    const form = tableFormInfo.value
+    for (let i = 0; i < keysList.length; i++) {
+        const val = form[keysList[i]['key']]
+        form_val = form_val ? form_val + '、' + val : val
+        keysList.splice(0, 1) //删除第一个元素
+    }
+    await setTableFormInfoValue(key, form_val)
+    HTableForm.setCheckKeyStyle(key, true)
+}
+
+//粘贴单个复制
+const setSingleCopyValue = async (checkList, keysList) => {
+    const form = tableFormInfo.value
+    const form_val = form[keysList[0]['key']]
+    for (let i = 0; i < checkList.length; i++) {
+        const {key} = checkList[i]
+        await setTableFormInfoValue(key, form_val)
+        HTableForm.setCheckKeyStyle(key, true)
+    }
+    keysList.splice(0, 1) //删除第一个元素
+}
+
+
+//粘贴多个
+const setMultipleCheckValue = async (checkList, keysList) => {
+    const form = tableFormInfo.value
+    for (let i = 0; i < checkList.length; i++) {
+        const {key, val} = checkList[i]
+        if (keysList.length > 0) {
+            const form_val = form[keysList[0]['key']]
+            await setTableFormInfoValue(key, form_val ? form_val : val)
+            keysList.splice(0, 1) //删除第一个元素
+        } else {
+            await setTableFormInfoValue(key, val)
+        }
+        HTableForm.setCheckKeyStyle(key, true)
+    }
+}
+
+//设置表单数据
+const setTableFormInfoValue = async (key, value) => {
+    return new Promise((resolve) => {
+        setTimeout(() => {
+            tableFormInfo.value[key] = value
+            resolve(true)
+        }, 100)
+    })
+}
+
+
+//全局键盘放开监听
+document.onkeyup = (event) => {
+    const {key, ctrlKey} = event
+    if (!ctrlKey && key === 'Control') {
+        isCtrlKey.value = false
+    }
+}
+
+//卸载页面
+onUnmounted(() => {
+    document.onkeydown = null
+    document.onkeyup = null
+})
+
+//获取表单数据
+const getFormData = () => {
+    return tableFormInfo.value
+}
+
+//设置表单数据
+const setFormData = (data) => {
+    nextTick(() => {
+        tableFormInfo.value = data
+    })
+}
+
+//获取表单效验数据
+const getRegExpJson = () => {
+    return deepClone(formRegExpJson.value);
+}
+
+const getNodeName = () => {
+    return nodeNames.value
+}
+
+//正则效验
+const isFormRegExp = async () => {
+    const isRegExp = !!getObjNullValue(formRegExpJson.value)
+    if (!isRegExp) {
+        return true
+    } else {
+        window?.$message?.warning('请先修改完红色输入框的数据')
+        return false
+    }
+}
+
+// 暴露出去
+defineExpose({
+    getFormData,
+    setFormData,
+    getRegExpJson,
+    isFormRegExp,
+    getNodeName
+})
+</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: "EUDC", 宋体, v-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;
+    .hc-excel-table-form {
+        position: relative;
+        display: flex;
+        padding: 10px;
+        justify-content: center;
+        td {
+            padding: 6px;
+            .el-input {
+                background-color: #ffffff !important;
+                border-radius: 3px;
+                color: #606266;
+                .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: initial !important;
+                    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 {
+                height: 100%;
+                width: 100%;
+            }
+            //焦点
+            .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-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: 100%;
+            }
+        }
+        //非输入框颜色
+        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>

+ 112 - 200
src/components/table-form/index.vue

@@ -1,5 +1,5 @@
 <template>
-    <div :id="`table-form-item-${keyId}`" v-loading="loading" :style="tableFormItemStyle"
+    <div :id="`table-form-item-${keyId}`" v-loading="isLoading" :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"/>
@@ -8,7 +8,7 @@
         <div v-if="isTableForm === false" class="hc-no-table-form">
             <div class="table-form-no">
                 <img :src="notableform" alt=""/>
-                <div class="desc">暂无表单数据</div>
+                <div class="desc">{{ noTips }}</div>
             </div>
         </div>
     </div>
@@ -16,244 +16,162 @@
 
 <script setup>
 import {ref, watch, onMounted, nextTick, onUnmounted} from "vue"
-import {useAppStore} from "~src/store";
 import HTableForm from "~src/plugins/HTableForm"
 import notableform from '~src/assets/view/notableform.svg'
 import {getStoreData, setStoreData, delStoreData} from "~uti/storage";
-import {getObjNullValue, isAsyncFunction, isString, getArrValue, deepClone, getIndex} from "vue-utils-plus"
-
-const useAppState = useAppStore()
+import {getObjNullValue, isString, deepClone, getIndex} from "vue-utils-plus"
 
 //初始
 const props = defineProps({
-    tid: { // 树节点
+    pkey: [String, Number],
+    noTip: {
         type: [String, Number],
-        default: ''
+        default: '暂无表单数据'
     },
-    kid: { // pkeyId
-        type: [String, Number],
-        default: ''
+    html: String,
+    form: {
+        type: Object,
+        default: () => ({})
     },
-    classify: { // 类型
-        type: [String, Number],
-        default: ''
+    cols: {
+        type: Array,
+        default: () => ([])
     },
-    api: { //请求方法函数列表
-        type: Object,
-        default: () => ({
-            dataInfo: null,
-            bussCols: null,
-            excelHtml: null
-        })
+    loading: Boolean,
+    scroll: {
+        type: Boolean,
+        default: true
     },
-    height: { // 高度
+    height: {
         type: String,
         default: '100%'
     },
-    width: { // 宽度
+    width: {
         type: String,
         default: 'auto'
     },
-    scroll: { // 可否滚动
+    isMessage: {
         type: Boolean,
-        default: false
-    },
-    datas: { //变动的数据
-        type: Object,
-        default: () => ({})
-    },
-    nodeName: { // 表单名称
-        type: String,
-        default: ''
+        default: true
     },
 })
 
 //初始变量
-const projectId = ref(useAppState.getProjectId)
-const contractId = ref(useAppState.getContractId)
-const keyId = ref(props.kid ? props.kid + '' : '')
-const treeId = ref(props.tid)
-const classify = ref(props.classify)
-const apis = ref(props.api)
-const tableFormItemStyle = ref('')
-const loading = ref(false)
+const keyId = ref(props.pkey)
+const noTips = ref(props.noTip)
 const isScroll = ref(props.scroll)
-const changeData = ref(props.datas)
-const nodeNames = ref(props.nodeName)
+const isLoading = ref(props.loading)
+
+//表单数据
+const excelHtml = ref(props.html)
+const excelForm = ref(props.form)
+const colsKeys = ref(props.cols)
+
+//样式
+const tableFormApp = ref(null)
+const tableFormStyle = ref('')
+const isTableForm = ref(false)
 
 //监听
-watch(() => [
-    useAppState.getProjectId,
-    useAppState.getContractId,
-    props.tid,
-    props.kid,
-    props.classify,
-    props.width,
-    props.height,
-    props.scroll,
-    props.nodeName
-], ([project_id, contract_id, tree_id, key_id, cid, width, height, scroll, nodeName]) => {
-    projectId.value = project_id
-    contractId.value = contract_id
-    treeId.value = tree_id
-    keyId.value = key_id ? key_id + '' : ''
-    classify.value = cid
+watch(() => [props.pkey, props.noTip, props.scroll, props.loading, props.width, props.height], ([pkey, tip, scroll, loading, width, height]) => {
+    keyId.value = pkey
+    noTips.value = tip
     isScroll.value = scroll
-    nodeNames.value = nodeName
+    isLoading.value = loading
     setItemStyle(width, height)
 })
 
+//html变动
+watch(() => [
+    props.html
+], ([html]) => {
+    excelHtml.value = html
+    setExcelHtml()
+})
+
 //深度监听变动的对象数据
 watch(() => [
-    props.datas
-], ([data]) => {
-    changeData.value = data
-    setFormChangeData(data)
-}, {deep: true})
+    props.form
+], ([val]) => {
+    excelForm.value = val
+    setPickerKey()
+    setFormData(val)
+}, {
+    deep: true
+})
+
+//深度监听按键切换的key列表
+watch(() => [
+    props.cols
+], ([cols]) => {
+    colsKeys.value = cols
+}, {
+    deep: true
+})
+
 
 //渲染完成
-onMounted(async () => {
-    let keys = []
-    loading.value = true
-    const {dataInfo, bussCols, excelHtml} = apis.value
+onMounted(() => {
     setItemStyle(props.width, props.height)
-    //获取已填写的数据
-    if (isAsyncFunction(dataInfo)) {
-        await getTableFormInfo(keyId.value, dataInfo)
-    }
-    //按键key列表
-    if (isAsyncFunction(bussCols)) {
-        keys = await getHtmlBussColsApi(keyId.value, bussCols)
-    }
-    //渲染表单
-    if (isAsyncFunction(excelHtml)) {
-        await getExcelHtml(keyId.value, excelHtml, keys)
-    }
-    loading.value = false
+    setPickerKey()
+    getExcelHtml()
 })
 
-const setFormChangeData = (data) => {
-    const form = tableFormInfo.value
-    tableFormInfo.value = {
-        ...form,
-        ...data
-    }
-    tableFormInfo.value = form
-}
 
 //设置样式
 const setItemStyle = (width, height) => {
-    tableFormItemStyle.value = `width: ${width}; height: ${height};`
+    tableFormStyle.value = `width: ${width}; height: ${height};`
 }
 
 //事件
 const emit = defineEmits(['rightTap', 'render'])
 
-//渲染状态变量
-const isTableForm = ref(false)
-const tableFormInfo = ref({})
-
-//获取表单初始数据
-const getFormDataInit = () => {
-    return {
-        projectId: projectId.value,
-        contractId: contractId.value,
-        classify: classify.value,
-        pkeyId: keyId.value,
-        nodeId: treeId.value,
-        isRenderForm: false,
-    }
-}
-
 //获取已填写的数据
-const getTableFormInfo = async (pkeyId, func) => {
-    if (pkeyId) {
-        const {error, code, data} = await func({
-            pkeyId: pkeyId
-        }, false)
-        const resData = getObjNullValue(data)
-        if (!error && code === 200 && resData) {
-            HTableForm.setPickerKey(resData)
-            tableFormInfo.value = {
-                ...resData,
-                ...getFormDataInit(),
-                ...changeData.value
-            }
-        } else {
-            tableFormInfo.value = {
-                ...getFormDataInit(),
-                ...changeData.value
-            }
-        }
-    } else {
-        tableFormInfo.value = {}
-        window?.$message?.warning('pkeyId为空')
-    }
+const setPickerKey = () => {
+    HTableForm.setPickerKey(excelForm.value)
 }
 
-//获取按键切换输入框的key列表
-const getHtmlBussColsApi = async (pkeyId, func) => {
-    if (pkeyId) {
-        const {error, code, data} = await func({
-            pkeyId: pkeyId
-        }, false)
-        if (!error && code === 200) {
-            let keys = getArrValue(data);
-            for (let i = 0; i < keys.length; i++) {
-                if (keys[i].length <= 0) {
-                    keys.splice(i, 1)
-                }
-            }
-            return keys;
-        } else {
-            return [];
-        }
-    } else {
-        return [];
+const setExcelHtml = () => {
+    //先卸载
+    if (tableFormApp.value) {
+        tableFormApp.value?.unmount()
     }
+    setPickerKey()
+    getExcelHtml()
 }
 
 //获取模板标签数据
-const getExcelHtml = async (pkeyId, func, keys) => {
-    if (pkeyId) {
-        const {error, code, data} = await func({
-            pkeyId: pkeyId
-        }, false)
-        const resData = isString(data) ? data || '' : ''
-        if (!error && code === 200 && resData) {
-            isTableForm.value = true
-            //渲染表单
-            HTableForm.createForm({
-                template: resData,
-                tableForm: tableFormInfo.value,
-                keys: keys,
-                appId: `#table-form-${pkeyId}`,
-                onRight: (event, KeyName) => {
-                    onRightClick(pkeyId, event, KeyName)
-                },
-                //表单正则效验
-                onBlur: (event, key, reg, val, msg) => {
-                    setTableFormBlurReg(pkeyId, event, key, reg, val, msg)
-                },
-                onLeftClick: (key) => {
-                    setShiftTableForm(key)
-                },
-            })
-            tableFormInfo.value.isRenderForm = true
-            await nextTick(() => {
-                HTableForm.setByClassKeyup(keys)
-            })
-        } else {
-            isTableForm.value = false
-            tableFormInfo.value.isRenderForm = false
-            window?.$message?.warning('暂无表单')
-        }
+const getExcelHtml = () => {
+    const pkeyId = keyId.value
+    const temp = isString(excelHtml.value) ? excelHtml.value : ''
+    if (temp && pkeyId) {
+        isTableForm.value = true
+        //渲染表单
+        tableFormApp.value = HTableForm.createForm({
+            template: temp,
+            tableForm: excelForm.value,
+            keys: colsKeys.value,
+            appId: `#table-form-${pkeyId}`,
+            onRight: (event, KeyName) => {
+                onRightClick(pkeyId, event, KeyName)
+            },
+            //表单正则效验
+            onBlur: (event, key, reg, val, msg) => {
+                setTableFormBlurReg(pkeyId, event, key, reg, val, msg)
+            },
+            onLeftClick: (key) => {
+                setShiftTableForm(key)
+            },
+        })
+        excelForm.value.isRenderForm = true
+        nextTick(() => {
+            HTableForm.setByClassKeyup(colsKeys.value)
+        })
     } else {
         isTableForm.value = false
-        tableFormInfo.value.isRenderForm = false
-        window?.$message?.warning('pkeyId为空')
+        excelForm.value.isRenderForm = false
     }
-    emit('render', tableFormInfo.value)
+    emit('render', excelForm.value)
 }
 
 //正则效验
@@ -281,7 +199,6 @@ const setTableFormBlurReg = (pkeyId, event, key, reg, val, msg) => {
     }
 }
 
-
 //鼠标右键事件
 const onRightClick = (pkeyId, event, KeyName) => {
     //取光标位置
@@ -298,7 +215,7 @@ const copyKeyList = ref(getStoreData('TableFormCopyKeyList') || [])
 //设置选择数据
 const setShiftTableForm = (key) => {
     if (isCtrlKey.value) {
-        const form = tableFormInfo.value
+        const form = excelForm.value
         const keys = checkKeyList.value
         const index = getIndex(keys, 'key', key)
         if (index === -1) {
@@ -360,7 +277,7 @@ document.onkeydown = async (event) => {
 //复制单个粘贴
 const setCopySingleValue = async (checkList, keysList) => {
     let form_val = '', key = checkList[0]['key']
-    const form = tableFormInfo.value
+    const form = excelForm.value
     for (let i = 0; i < keysList.length; i++) {
         const val = form[keysList[i]['key']]
         form_val = form_val ? form_val + '、' + val : val
@@ -372,7 +289,7 @@ const setCopySingleValue = async (checkList, keysList) => {
 
 //粘贴单个复制
 const setSingleCopyValue = async (checkList, keysList) => {
-    const form = tableFormInfo.value
+    const form = excelForm.value
     const form_val = form[keysList[0]['key']]
     for (let i = 0; i < checkList.length; i++) {
         const {key} = checkList[i]
@@ -385,7 +302,7 @@ const setSingleCopyValue = async (checkList, keysList) => {
 
 //粘贴多个
 const setMultipleCheckValue = async (checkList, keysList) => {
-    const form = tableFormInfo.value
+    const form = excelForm.value
     for (let i = 0; i < checkList.length; i++) {
         const {key, val} = checkList[i]
         if (keysList.length > 0) {
@@ -403,7 +320,7 @@ const setMultipleCheckValue = async (checkList, keysList) => {
 const setTableFormInfoValue = async (key, value) => {
     return new Promise((resolve) => {
         setTimeout(() => {
-            tableFormInfo.value[key] = value
+            excelForm.value[key] = value
             resolve(true)
         }, 100)
     })
@@ -424,16 +341,15 @@ onUnmounted(() => {
     document.onkeyup = null
 })
 
-
 //获取表单数据
 const getFormData = () => {
-    return tableFormInfo.value
+    return excelForm.value
 }
 
 //设置表单数据
 const setFormData = (data) => {
     nextTick(() => {
-        tableFormInfo.value = data
+        excelForm.value = data
     })
 }
 
@@ -442,9 +358,6 @@ const getRegExpJson = () => {
     return deepClone(formRegExpJson.value);
 }
 
-const getNodeName = () => {
-    return nodeNames.value
-}
 
 //正则效验
 const isFormRegExp = async () => {
@@ -462,8 +375,7 @@ defineExpose({
     getFormData,
     setFormData,
     getRegExpJson,
-    isFormRegExp,
-    getNodeName
+    isFormRegExp
 })
 </script>
 

+ 21 - 14
src/views/data-fill/collapse-form/index.vue

@@ -66,13 +66,15 @@
                         </div>
                     </div>
                     <div v-else class="data-fill-table-form-box">
-                        <HcTableForm v-if="item.isTableRender" :ref="(el) => setItemRefs(el, item)" :api="apis"
-                                     :classify="classifys" :datas="changeFormDatas(item?.pkeyId, 'collapse')"
-                                     :kid="item?.pkeyId"
-                                     :nodeName="item.nodeName"
-                                     :tid="treeId"
-                                     scroll @render="tableFormRender($event, item, index)"
-                                     @rightTap="tableFormRightTap($event, index)"/>
+                        <TableFormItem v-if="item.isTableRender"
+                                       :ref="(el) => setItemRefs(el, item)"
+                                       :classify="classifys"
+                                       :datas="changeFormDatas(item?.pkeyId, 'collapse')"
+                                       :kid="item?.pkeyId"
+                                       :nodeName="item.nodeName"
+                                       :tid="treeId"
+                                       @render="tableFormRender($event, item, index)"
+                                       @rightTap="tableFormRightTap($event, index)"/>
                     </div>
                     <div class="hc-window-switch-box">
                         <el-tooltip :content="item.isWindow?'关闭窗口并恢复':'当前表单窗口化'" :hide-after="0"
@@ -236,12 +238,17 @@
                      isSortTop
                      @close="TableFormClose(item, index)" @closeIconTap="closeIconTap($event, item, index)">
             <HcDragNode :more-menu="dragNodeMoreMenu" @menuTap="dragNodeMoreMenuTap($event, item)">
-                <HcTableForm :ref="(el) => setItemRefs(el, item)" :api="apis" :classify="item.classify"
-                             :datas="changeFormDatas(item?.pkeyId, 'window')" :height="item.height"
-                             :kid="item.pkeyId" :nodeName="item.title" :tid="item.treeId"
-                             :width="item.width"
-                             @render="tableFormRender($event, item['item'], item['index'])"
-                             @rightTap="tableFormRightTap($event, item['index'])"/>
+                <TableFormItem :ref="(el) => setItemRefs(el, item)"
+                               :classify="item.classify"
+                               :datas="changeFormDatas(item?.pkeyId, 'window')"
+                               :height="item.height"
+                               :kid="item.pkeyId"
+                               :nodeName="item.title"
+                               :scroll="false"
+                               :tid="item.treeId"
+                               :width="item.width"
+                               @render="tableFormRender($event, item['item'], item['index'])"
+                               @rightTap="tableFormRightTap($event, item['index'])"/>
             </HcDragNode>
         </HcDragModal>
     </template>
@@ -253,7 +260,7 @@ import {ref, watch, nextTick} from "vue";
 import {useAppStore} from "~src/store";
 import wbsApi from "~api/data-fill/wbs"
 import HcUpload from "../components/HcUpload.vue"
-import HcTableForm from "~com/table-form/index.vue"
+import TableFormItem from "./table-form-item.vue"
 import HcSpecialDiaolg from "./special-diaolg.vue"
 import HcTestDiaolg from "./test-diaolg.vue"
 import HcTestData from "./test-data.vue"

+ 250 - 0
src/views/data-fill/collapse-form/table-form-item.vue

@@ -0,0 +1,250 @@
+<template>
+    <HcTableForm ref="tableFormRef"
+                 :cols="colsKeys"
+                 :form="tableFormInfo"
+                 :height="heights"
+                 :html="excelHtml"
+                 :loading="loading"
+                 :pkey="keyId"
+                 :scroll="scroll"
+                 :width="widths"
+                 @render="tableFormRender"
+                 @rightTap="tableFormRightTap"/>
+</template>
+
+<script setup>
+import {ref, watch, onMounted} from "vue"
+import HcTableForm from "~com/table-form/index.vue"
+import {useAppStore} from "~src/store";
+import wbsApi from "~api/data-fill/wbs";
+import {getObjNullValue, isString, getArrValue} from "vue-utils-plus"
+
+//初始
+const props = defineProps({
+    tid: { // 树节点
+        type: [String, Number],
+        default: ''
+    },
+    kid: { // pkeyId
+        type: [String, Number],
+        default: ''
+    },
+    classify: { // 类型
+        type: [String, Number],
+        default: ''
+    },
+    scroll: {
+        type: Boolean,
+        default: true
+    },
+    height: {
+        type: String,
+        default: '100%'
+    },
+    width: {
+        type: String,
+        default: 'auto'
+    },
+    datas: {
+        type: Object,
+        default: () => ({})
+    },
+    nodeName: { // 表单名称
+        type: String,
+        default: ''
+    },
+})
+
+//初始变量
+const useAppState = useAppStore()
+const projectId = ref(useAppState.getProjectId)
+const contractId = ref(useAppState.getContractId)
+const keyId = ref(props.kid ? props.kid + '' : '')
+const treeId = ref(props.tid)
+const classify = ref(props.classify)
+const loading = ref(false)
+const changeData = ref(props.datas)
+const nodeNames = ref(props.nodeName)
+
+const heights = ref(props.height)
+const widths = ref(props.width)
+
+const tableFormRef = ref(null)
+
+//监听
+watch(() => [
+    useAppState.getProjectId,
+    useAppState.getContractId,
+    props.tid,
+    props.kid,
+    props.classify,
+    props.nodeName,
+    props.height,
+    props.width,
+], (
+    [project_id, contract_id, tree_id, key_id, cid, nodeName, height, width]
+) => {
+    projectId.value = project_id
+    contractId.value = contract_id
+    treeId.value = tree_id
+    keyId.value = key_id ? key_id + '' : ''
+    classify.value = cid
+    nodeNames.value = nodeName
+
+    heights.value = height
+    widths.value = width
+})
+
+//深度监听变动的对象数据
+watch(() => [
+    props.datas
+], ([data]) => {
+    changeData.value = data
+    setFormChangeData(data)
+}, {deep: true})
+
+
+//渲染完成
+onMounted(async () => {
+    loading.value = true
+    //获取已填写的数据
+    await getTableFormInfo(keyId.value)
+    //按键key列表
+    await getHtmlBussColsApi(keyId.value)
+    //渲染表单
+    await getExcelHtml(keyId.value)
+    loading.value = false
+})
+
+//事件
+const emit = defineEmits(['rightTap', 'render'])
+
+//获取表单初始数据
+const getFormDataInit = () => {
+    return {
+        projectId: projectId.value,
+        contractId: contractId.value,
+        classify: classify.value,
+        pkeyId: keyId.value,
+        nodeId: treeId.value,
+        isRenderForm: false,
+    }
+}
+
+//获取已填写的数据
+const tableFormInfo = ref({})
+const getTableFormInfo = async (pkeyId) => {
+    if (pkeyId) {
+        const {error, code, data} = await wbsApi.getBussDataInfo({
+            pkeyId: pkeyId
+        }, false)
+        const resData = getObjNullValue(data)
+        if (!error && code === 200 && resData) {
+            tableFormInfo.value = {
+                ...resData,
+                ...getFormDataInit(),
+                ...changeData.value
+            }
+        } else {
+            tableFormInfo.value = {
+                ...getFormDataInit(),
+                ...changeData.value
+            }
+        }
+    } else {
+        tableFormInfo.value = {}
+        window?.$message?.warning('pkeyId为空')
+    }
+}
+
+//获取按键切换输入框的key列表
+const colsKeys = ref([])
+const getHtmlBussColsApi = async (pkeyId) => {
+    if (pkeyId) {
+        const {error, code, data} = await wbsApi.getHtmlBussCols({
+            pkeyId: pkeyId
+        }, false)
+        if (!error && code === 200) {
+            let keys = getArrValue(data);
+            for (let i = 0; i < keys.length; i++) {
+                if (keys[i].length <= 0) {
+                    keys.splice(i, 1)
+                }
+            }
+            colsKeys.value = keys;
+        } else {
+            colsKeys.value = [];
+        }
+    } else {
+        colsKeys.value = []
+    }
+}
+
+//获取模板标签数据
+const excelHtml = ref('')
+const getExcelHtml = async (pkeyId) => {
+    if (pkeyId) {
+        const {error, code, data} = await wbsApi.getExcelHtml({
+            pkeyId: pkeyId
+        }, false)
+        const resData = isString(data) ? data || '' : ''
+        if (!error && code === 200 && resData) {
+            excelHtml.value = resData
+        } else {
+            excelHtml.value = ''
+            tableFormInfo.value.isRenderForm = false
+            window?.$message?.warning('暂无表单')
+        }
+    } else {
+        excelHtml.value = ''
+        tableFormInfo.value.isRenderForm = false
+        window?.$message?.warning('pkeyId为空')
+    }
+}
+
+//渲染完成
+const tableFormRender = (form) => {
+    emit('render', form)
+}
+
+//右键点击
+const tableFormRightTap = (item) => {
+    emit('rightTap', item)
+}
+
+//设置数据
+const setFormChangeData = (data) => {
+    const form = tableFormInfo.value
+    tableFormInfo.value = {...form, ...data}
+}
+
+const getFormData = () => {
+    return tableFormRef.value?.getFormData()
+}
+
+const setFormData = (data) => {
+    tableFormRef.value?.setFormData(data)
+}
+
+const getRegExpJson = () => {
+    return tableFormRef.value?.getRegExpJson()
+}
+
+const isFormRegExp = async () => {
+    return await tableFormRef.value?.isFormRegExp()
+}
+
+//获取表单名称
+const getNodeName = () => {
+    return nodeNames.value
+}
+
+// 暴露出去
+defineExpose({
+    getFormData,
+    setFormData,
+    getRegExpJson,
+    isFormRegExp,
+    getNodeName
+})
+</script>

+ 98 - 72
src/views/ledger/components/table-form.vue

@@ -2,19 +2,22 @@
     <div class="hc-table-form-content">
         <div class="hc-content-box">
             <div class="hc-table-forem-box">
+                <!--HcTableForm :ref="tableFormRef" scroll @render="tableFormRender"
+                             @rightTap="tableFormRightTap"/-->
                 <el-scrollbar v-if="excelIdVal && isTableForm">
-                    <div class="hc-excel-table-form-view" :id="`table-form-${excelIdVal}`"></div>
+                    <div :id="`table-form-${excelIdVal}`" class="hc-excel-table-form-view"></div>
                 </el-scrollbar>
-                <HcStatus :desc="statusDesc" v-else/>
+                <HcStatus v-else :desc="statusDesc"/>
             </div>
-            <div class="hc-fixed-page" v-if="formLogDataList.length > 1">
+            <div v-if="formLogDataList.length > 1" class="hc-fixed-page">
                 <el-scrollbar>
                     <div class="hc-fixed-page-list-box">
                         <template v-for="(item,index) in formLogDataList">
-                            <div class="fixed-page-item" :class="index === formLogIndex ? 'primary' : ''" @click="getBussDataInfo(index)">
+                            <div :class="index === formLogIndex ? 'primary' : ''" class="fixed-page-item"
+                                 @click="getBussDataInfo(index)">
                                 <div class="name-box">
                                     <HcIcon name="sticky-note"/>
-                                    <span class="page">第{{index + 1}}页</span>
+                                    <span class="page">第{{ index + 1 }}页</span>
                                 </div>
                                 <div class="close-box" @click.stop="closeBussDataInfo(index)">
                                     <HcIcon name="close"/>
@@ -25,19 +28,19 @@
                 </el-scrollbar>
             </div>
             <div class="hc-right-pian-box hc-flex-column">
-                <DateCalendar :recordDate="recordDates" :dateData="dateData" @choice-date="dateCalendarChoice"/>
-                <el-alert title="蓝色代表当天已填写过日志" type="warning" show-icon/>
-                <div class="my-4" v-if="menuItem?.nodeType === 7 || menuItem?.nodeType === 11">
-                    <el-button type="primary" hc-btn @click="showProcessModal">
+                <DateCalendar :dateData="dateData" :recordDate="recordDates" @choice-date="dateCalendarChoice"/>
+                <el-alert show-icon title="蓝色代表当天已填写过日志" type="warning"/>
+                <div v-if="menuItem?.nodeType === 7 || menuItem?.nodeType === 11" class="my-4">
+                    <el-button hc-btn type="primary" @click="showProcessModal">
                         <HcIcon name="add-circle"/>
                         <span>关联工序</span>
                     </el-button>
                 </div>
-                <div class="hc-process-box" v-if="menuItem?.nodeType === 7 || menuItem?.nodeType === 11">
+                <div v-if="menuItem?.nodeType === 7 || menuItem?.nodeType === 11" class="hc-process-box">
                     <el-scrollbar>
-                        <div class="process-item-box" v-for="(item,index) in processDataList">
-                            <div class="process-item">{{item.path}}</div>
-                            <HcIcon name="close-circle" fill class="process-icon" @click="deleProcess(index)"/>
+                        <div v-for="(item,index) in processDataList" class="process-item-box">
+                            <div class="process-item">{{ item.path }}</div>
+                            <HcIcon class="process-icon" fill name="close-circle" @click="deleProcess(index)"/>
                         </div>
                     </el-scrollbar>
                 </div>
@@ -45,43 +48,51 @@
         </div>
         <div class="hc-footer-box">
             <HcTooltip keys="ledger_query_save_form">
-                <el-button type="primary" hc-btn :disabled="!isTableForm || taskStatus === 3 || taskStatus === 4" :loading="tableFormSaveLoading" @click="tableFormSaveClick">
+                <el-button :disabled="!isTableForm || taskStatus === 3 || taskStatus === 4"
+                           :loading="tableFormSaveLoading" hc-btn
+                           type="primary" @click="tableFormSaveClick">
                     <HcIcon name="save"/>
                     <span>保存</span>
                 </el-button>
             </HcTooltip>
             <HcTooltip keys="ledger_query_report_form">
-                <el-button hc-btn :disabled="!isTableForm || taskStatus === 1 || taskStatus === 3 || taskStatus === 4" @click="reportModalClick">
+                <el-button :disabled="!isTableForm || taskStatus === 1 || taskStatus === 3 || taskStatus === 4" hc-btn
+                           @click="reportModalClick">
                     <HcIcon name="send-plane-2"/>
                     <span>上报</span>
                 </el-button>
             </HcTooltip>
             <HcTooltip keys="ledger_query_preview_form">
-                <el-button hc-btn :disabled="!isTableForm || taskStatus === 1 " :loading="previewLoading" @click="previewBussPdf">
+                <el-button :disabled="!isTableForm || taskStatus === 1 " :loading="previewLoading" hc-btn
+                           @click="previewBussPdf">
                     <HcIcon name="eye"/>
                     <span>预览</span>
                 </el-button>
             </HcTooltip>
             <HcTooltip keys="ledger_query_copy_form">
-                <el-button hc-btn :disabled="!isTableForm || taskStatus === 3 || taskStatus === 4" @click="copyTableFormClick">
+                <el-button :disabled="!isTableForm || taskStatus === 3 || taskStatus === 4" hc-btn
+                           @click="copyTableFormClick">
                     <HcIcon name="file-copy-2"/>
                     <span>复制当前表格及内容</span>
                 </el-button>
             </HcTooltip>
             <HcTooltip keys="ledger_query_time_form">
-                <el-button hc-btn :disabled="!isTableForm || taskStatus === 3 || taskStatus === 4" @click="copyTimeLogModal">
+                <el-button :disabled="!isTableForm || taskStatus === 3 || taskStatus === 4" hc-btn
+                           @click="copyTimeLogModal">
                     <HcIcon name="file-copy-2"/>
                     <span>复制任意时间</span>
                 </el-button>
             </HcTooltip>
             <HcTooltip keys="ledger_query_add_form">
-                <el-button hc-btn :disabled="!isTableForm || taskStatus === 3 || taskStatus === 4" @click="addTableFormClick">
+                <el-button :disabled="!isTableForm || taskStatus === 3 || taskStatus === 4" hc-btn
+                           @click="addTableFormClick">
                     <HcIcon name="add-circle"/>
                     <span>新增表格</span>
                 </el-button>
             </HcTooltip>
             <HcTooltip keys="ledger_query_abolish_form">
-                <el-button hc-btn :disabled="!isTableForm || taskStatus === 1  || taskStatus === 2" @click="abolishTableFormClick">
+                <el-button :disabled="!isTableForm || taskStatus === 1  || taskStatus === 2" hc-btn
+                           @click="abolishTableFormClick">
                     <HcIcon name="delete-bin-3"/>
                     <span>废除</span>
                 </el-button>
@@ -89,30 +100,43 @@
         </div>
 
         <!--关联工序-->
-        <HcDialog :show="processNodeModal" title="选择关联工序" widths="62rem"  @close="processNodeModal = false" @save="processNodeClick">
+        <HcDialog :show="processNodeModal" title="选择关联工序" widths="62rem" @close="processNodeModal = false"
+                  @save="processNodeClick">
             <div class="node-many-tree">
-                <el-tree :load="ElTreeLoadNode" lazy class="my-tree" :props="processTreeProps" show-checkbox node-key="primaryKeyId"
-                         :default-checked-keys="defaultChecked" :default-expanded-keys="defaultExpanded" check-strictly ref="processElTree"/>
+                <el-tree ref="processElTree" :default-checked-keys="defaultChecked"
+                         :default-expanded-keys="defaultExpanded" :load="ElTreeLoadNode" :props="processTreeProps"
+                         check-strictly
+                         class="my-tree" lazy node-key="primaryKeyId"
+                         show-checkbox/>
             </div>
         </HcDialog>
 
         <!--复制任意时间-->
-        <HcDialog :show="copyTimeModal" isTable title="复制任意时间" widths="62rem" saveText="复制" :padding="false" @close="copyTimeModal = false" :loading="copyTimeLoading" @save="copyTimeSaveClick">
+        <HcDialog :loading="copyTimeLoading" :padding="false" :show="copyTimeModal" isTable saveText="复制"
+                  title="复制任意时间"
+                  widths="62rem" @close="copyTimeModal = false" @save="copyTimeSaveClick">
             <div class="hc-user-time-box">
                 <div class="tree-box">
                     <el-scrollbar>
-                        <el-tree class="hc-tree-node" :props="copyTimeTreeProps" :data="copyTimeTreeData" node-key="hierarchy" :default-expanded-keys="copyTimeTreeKeys" highlight-current accordion @node-click="copyTimeTreeNodeClick"/>
+                        <el-tree :data="copyTimeTreeData" :default-expanded-keys="copyTimeTreeKeys"
+                                 :props="copyTimeTreeProps"
+                                 accordion class="hc-tree-node" highlight-current
+                                 node-key="hierarchy" @node-click="copyTimeTreeNodeClick"/>
                     </el-scrollbar>
                 </div>
                 <div class="user-box">
-                    <HcTable ref="copyTimeTableRef" :column="copyTimeTableColumn" :datas="copyTimeTableData" :loading="copyTimeTableLoading" isCheck @selection-change="copyTimeTableSelection"/>
+                    <HcTable ref="copyTimeTableRef" :column="copyTimeTableColumn" :datas="copyTimeTableData"
+                             :loading="copyTimeTableLoading" isCheck @selection-change="copyTimeTableSelection"/>
                 </div>
             </div>
         </HcDialog>
 
         <!--批量上报审批-->
-        <HcReportModal  title="日志填报上报" url="contractLog/startTaskTheLog" :show="showReportModal" :projectId="projectId" :contractId="contractId" type="log" :typeData="menuItem.primaryKeyId"
-                        :taskName="reportTaskName" :addition="reportAddition" @hide="showReportModal = false" @finish="showReportFinish"/>
+        <HcReportModal :addition="reportAddition" :contractId="contractId" :projectId="projectId"
+                       :show="showReportModal" :taskName="reportTaskName" :typeData="menuItem.primaryKeyId"
+                       title="日志填报上报"
+                       type="log" url="contractLog/startTaskTheLog" @finish="showReportFinish"
+                       @hide="showReportModal = false"/>
     </div>
 </template>
 
@@ -123,15 +147,16 @@ import wbsQueryApi from '~api/data-fill/query';
 import HTableForm from "~src/plugins/HTableForm"
 import DateCalendar from "./dateCalendar/index.vue"
 import {getObjValue, getObjNullValue, isString, getArrValue, isValueNull} from "vue-utils-plus"
+import HcTableForm from "~com/table-form/index.vue";
 
 //参数
 const props = defineProps({
     projectId: {
-        type: [String,Number],
+        type: [String, Number],
         default: ''
     },
     contractId: {
-        type: [String,Number],
+        type: [String, Number],
         default: ''
     },
     items: {
@@ -139,7 +164,7 @@ const props = defineProps({
         default: () => ({})
     },
     userName: {
-        type: [String,Number],
+        type: [String, Number],
         default: ''
     }
 })
@@ -151,6 +176,7 @@ const menuItem = ref(props.items);
 const userName = ref(props.userName);
 const excelIdVal = ref('');
 const statusDesc = ref('');
+const tableFormRef = ref(null);
 
 //监听
 watch(() => [
@@ -176,7 +202,7 @@ nextTick(() => {
 const getQueryData = () => {
     setQueryDataDate()
     const date = recordDate.value ?? {}, time = recordTime.value ?? ''
-    getExcelBusinessData(date,time)
+    getExcelBusinessData(date, time)
 }
 
 const setQueryDataDate = () => {
@@ -192,16 +218,16 @@ const dateCalendarChoice = ({date, choices, dates}) => {
     recordTime.value = choices
     recordDate.value = date
     recordDates.value = dates
-    getExcelBusinessData(date,choices)
+    getExcelBusinessData(date, choices)
 }
 
 //获取数据
-const getExcelBusinessData = (date,choices) => {
+const getExcelBusinessData = (date, choices) => {
     const {primaryKeyId} = menuItem.value
     getExcelHtml(excelIdVal.value)
     getTheLogBusinessData(excelIdVal.value, choices)
-    getSubmitLogDateList(date,primaryKeyId)
-    checkTheLogTaskStatus(choices,primaryKeyId)
+    getSubmitLogDateList(date, primaryKeyId)
+    checkTheLogTaskStatus(choices, primaryKeyId)
 }
 
 //获取模板标签数据
@@ -210,7 +236,7 @@ const excelHtmlData = ref('')
 const getExcelHtml = async (excelId) => {
     if (excelId) {
         //获取数据
-        const { error, code, data } = await queryApi.getExcelHtml({
+        const {error, code, data} = await queryApi.getExcelHtml({
             contractId: contractId.value || '',
             pkeyId: excelId
         }, false)
@@ -218,7 +244,7 @@ const getExcelHtml = async (excelId) => {
         const resData = isString(data) ? data || '' : ''
         excelHtmlData.value = resData
         if (!error && code === 200 && resData) {
-            setHTableForm(resData,excelId)
+            setHTableForm(resData, excelId)
         } else {
             isTableForm.value = false
             statusDesc.value = '暂无表单'
@@ -257,7 +283,7 @@ const setHTableForm = (resData, excelId) => {
 const formLogDataList = ref([])
 const getTheLogBusinessData = async (excelId, recordDate) => {
     const {primaryKeyId} = menuItem.value
-    const { data } = await queryApi.getTheLogBusinessData({
+    const {data} = await queryApi.getTheLogBusinessData({
         contractId: contractId.value || '',
         pkeyId: excelId,
         nodePrimaryKeyId: primaryKeyId,
@@ -298,9 +324,9 @@ const getBussDataInfo = (index = 0) => {
 
 //获取日期记录
 const dateData = ref([])
-const getSubmitLogDateList = async ({year},pid) => {
+const getSubmitLogDateList = async ({year}, pid) => {
     if (pid > 0 && year) {
-        const { data } = await queryApi.getSubmitLogDateList({
+        const {data} = await queryApi.getSubmitLogDateList({
             projectId: projectId.value,
             contractId: contractId.value,
             primaryKeyId: pid,
@@ -315,9 +341,9 @@ const getSubmitLogDateList = async ({year},pid) => {
 
 //获取当前资料的任务状态
 const taskStatus = ref(1)
-const checkTheLogTaskStatus = async (choices,primaryKeyId) => {
+const checkTheLogTaskStatus = async (choices, primaryKeyId) => {
     if (primaryKeyId > 0) {
-        const { error, code, data } = await queryApi.checkTheLogTaskStatus({
+        const {error, code, data} = await queryApi.checkTheLogTaskStatus({
             projectId: projectId.value,
             contractId: contractId.value,
             nodePrimaryKeyId: primaryKeyId,
@@ -353,7 +379,7 @@ const defaultChecked = ref([]) //默认选中
 const ElTreeLoadNode = async (node, resolve) => {
     if (node.level === 0) {
         const {error, code, data} = await wbsQueryApi.queryWbsTreeData({
-            contractId: contractId.value ||'',
+            contractId: contractId.value || '',
             contractIdRelation: '',
             primaryKeyId: '',
             parentId: ''
@@ -432,19 +458,19 @@ const tableFormSaveClick = async () => {
     if (res) {
         await checkTheLogTaskStatus(recordTime.value, primaryKeyId)
         await getBussPdfInfo()
-          tableFormSaveLoading.value = false
+        tableFormSaveLoading.value = false
     }
 }
 
 //保存
 const saveExcelBussData = async () => {
     let isLinkTabIds = getLinkTabIds(); //处理工序ID
-    console.log(isLinkTabIds,'isLinkTabIds');
+    console.log(isLinkTabIds, 'isLinkTabIds');
     if (isLinkTabIds) {
         tableFormSaveLoading.value = true
-        const { error, code, msg } = await queryApi.saveExcelBussData({
+        const {error, code, msg} = await queryApi.saveExcelBussData({
             dataInfo: {orderList: formLogDataList.value}
-        },false)
+        }, false)
 
         if (!error && code === 200) {
 
@@ -460,15 +486,15 @@ const saveExcelBussData = async () => {
 //处理工序数据
 const getLinkTabIds = () => {
     let {nodeType} = menuItem.value;
-    let isLink=false
+    let isLink = false
     if (nodeType === 7 || nodeType === 11) {
-        isLink= formLogDataList.value.some((item)=>{
-                const linkIds = getArrValue(item?.linkTabIds)
-                return linkIds.length>0
+        isLink = formLogDataList.value.some((item) => {
+            const linkIds = getArrValue(item?.linkTabIds)
+            return linkIds.length > 0
         })
-        if(isLink){
+        if (isLink) {
             return true
-        }else{
+        } else {
             window?.$message?.warning('请先关联工序')
             return false
         }
@@ -488,7 +514,7 @@ const previewBussPdf = () => {
 const getBussPdfInfo = async () => {
     previewLoading.value = true
     const {primaryKeyId} = menuItem.value
-    const { error, code, data } = await queryApi.getBussPdfInfo({
+    const {error, code, data} = await queryApi.getBussPdfInfo({
         contractId: contractId.value || '',
         pkeyId: excelIdVal.value,
         nodePrimaryKeyId: primaryKeyId,
@@ -499,7 +525,7 @@ const getBussPdfInfo = async () => {
     previewLoading.value = false
     const resData = isString(data) ? data || '' : ''
     if (!error && code === 200 && resData) {
-        window.open(resData,'_blank')
+        window.open(resData, '_blank')
     } else {
         window?.$message?.warning('暂无PDF,无法预览')
     }
@@ -508,7 +534,7 @@ const getBussPdfInfo = async () => {
 //获取当前日志资料关联的工序节点信息
 const queryCurrentLogSelectProcessList = async (bid) => {
     if (bid) {
-        const { error, code, data, msg } = await queryApi.queryCurrentLogSelectProcessList({
+        const {error, code, data, msg} = await queryApi.queryCurrentLogSelectProcessList({
             contractId: contractId.value || '',
             businessId: bid ?? ''
         }, false)
@@ -520,7 +546,7 @@ const queryCurrentLogSelectProcessList = async (bid) => {
             processDataList.value = linkTabIds
         } else {
             processDataList.value = []
-            if(msg) window?.$message?.warning(msg)
+            if (msg) window?.$message?.warning(msg)
         }
     } else {
         const formIndex = formLogIndex.value
@@ -567,8 +593,8 @@ const copyTimeTreeKeys = ref([])
 
 //获取当前合同段下本日志节点的填报资料日期树
 const queryReportLogTimeTree = async () => {
-    const { primaryKeyId } = menuItem.value
-    const { data } = await queryApi.queryReportLogTimeTree({
+    const {primaryKeyId} = menuItem.value
+    const {data} = await queryApi.queryReportLogTimeTree({
         contractId: contractId.value || '',
         nodePrimaryKeyId: primaryKeyId
     })
@@ -587,8 +613,8 @@ const copyTimeTreeNodeClick = (data) => {
 //复制任意时间的记录人
 const copyTimeTableRef = ref(null)
 const copyTimeTableColumn = ref([
-    {key:'createUserName', name: '记录人'},
-    {key:'recordTime', name: '时间'},
+    {key: 'createUserName', name: '记录人'},
+    {key: 'recordTime', name: '时间'},
 ])
 const copyTimeTableData = ref([])
 
@@ -596,8 +622,8 @@ const copyTimeTableData = ref([])
 const copyTimeTableLoading = ref(false)
 const queryLogTimeTreeList = async (time) => {
     copyTimeTableLoading.value = true
-    const { primaryKeyId } = menuItem.value
-    const { data } = await queryApi.queryLogTimeTreeList({
+    const {primaryKeyId} = menuItem.value
+    const {data} = await queryApi.queryLogTimeTreeList({
         contractId: contractId.value || '',
         nodePrimaryKeyId: primaryKeyId,
         time: time
@@ -610,7 +636,7 @@ const queryLogTimeTreeList = async (time) => {
 const copyTimeTableKeys = ref([]);
 const copyTimeTableSelection = (rows) => {
     copyTimeTableKeys.value = rows.filter((item) => {
-        return (item??'') !== '';
+        return (item ?? '') !== '';
     })
 }
 
@@ -630,7 +656,7 @@ const copyTimeSaveClick = () => {
 const copyTheLogBusinessData = async (ids) => {
     copyTimeLoading.value = true
     const {primaryKeyId} = menuItem.value
-    const { error, code } = await queryApi.copyTheLogBusinessData({
+    const {error, code} = await queryApi.copyTheLogBusinessData({
         contractId: contractId.value || '',
         nodePrimaryKeyId: primaryKeyId,
         currentTime: recordTime.value,
@@ -674,7 +700,7 @@ const setFormDefaultData = (formInfo = {}) => {
 //删除记录
 const closeBussDataInfo = (index) => {
     formLogDataList.value.splice(index, 1)
-    const logIndex = index <= 0 ?  0 : index - 1
+    const logIndex = index <= 0 ? 0 : index - 1
     formLogIndex.value = logIndex
     getBussDataInfo(logIndex)
 }
@@ -684,7 +710,7 @@ const reportTaskName = ref('')
 const reportAddition = ref({})
 const showReportModal = ref(false)
 const reportModalClick = () => {
-    const {primaryKeyId,title} = menuItem.value
+    const {primaryKeyId, title} = menuItem.value
     reportTaskName.value = `${recordTime.value} ${title} ${userName.value}`
     reportAddition.value = {
         nodePrimaryKeyId: primaryKeyId,
@@ -715,7 +741,7 @@ const abolishTableFormClick = () => {
 //确认废除
 const theLogOneAbolish = async () => {
     const {primaryKeyId} = menuItem.value
-    const { error, code } = await queryApi.theLogOneAbolish({
+    const {error, code} = await queryApi.theLogOneAbolish({
         projectId: projectId.value,
         contractId: contractId.value,
         nodePrimaryKeyId: primaryKeyId,
@@ -741,7 +767,7 @@ const theLogOneAbolish = async () => {
         padding: 24px;
         background: #f1f5f8;
         border-radius: 10px;
-        box-shadow: -2px 0px 10px 0px rgba(32,37,50,0.03), 0px 10px 21px 20px rgba(32,37,50,0.03);
+        box-shadow: -2px 0px 10px 0px rgba(32, 37, 50, 0.03), 0px 10px 21px 20px rgba(32, 37, 50, 0.03);
     }
     .hc-content-box {
         flex: 1;
@@ -773,7 +799,7 @@ const theLogOneAbolish = async () => {
                     background: #f1f5f8;
                     border: 1px solid #f1f5f8;
                     color: var(--el-color-primary-light-3);
-                    box-shadow: 4px 4px 8px 0 rgba(54,92,167,0.15), -4px -4px 8px 0 #ffffff;
+                    box-shadow: 4px 4px 8px 0 rgba(54, 92, 167, 0.15), -4px -4px 8px 0 #ffffff;
                     transition: .1s;
                     .name-box {
                         position: relative;
@@ -799,7 +825,7 @@ const theLogOneAbolish = async () => {
                         box-shadow: var(--hc-shadow);
                         border: 1px solid #f1f5f8;
                     }
-                    &+.fixed-page-item{
+                    & + .fixed-page-item {
                         margin-top: 20px;
                     }
                 }