|
@@ -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,
|