table-form.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <template>
  2. <div :id="`table-form-item-${uuid}`" :class="!isTableForm ? 'no-scroll-bar' : ''" class="hc-table-form-data-item h-full w-full">
  3. <el-scrollbar class="table-form-item-scrollbar">
  4. <div :id="`table-form-${uuid}`" class="hc-excel-table-form" />
  5. </el-scrollbar>
  6. <hc-empty v-if="!isTableForm" :src="notableform" title="暂无表单数据" />
  7. </div>
  8. </template>
  9. <script setup>
  10. import { nextTick, onMounted, ref, watch } from 'vue'
  11. import HTableForm from '~src/plugins/HTableForm'
  12. import notableform from '~src/assets/view/notableform.svg'
  13. import { getRandom, isNullES, isString } from 'js-fast-way'
  14. //初始
  15. const props = defineProps({
  16. html: String,
  17. form: {
  18. type: Object,
  19. default: () => ({}),
  20. },
  21. })
  22. //事件
  23. const emit = defineEmits(['tap', 'render'])
  24. const uuid = getRandom(8)
  25. //表单数据
  26. const excelHtml = ref(props.html)
  27. const excelForm = ref(props.form)
  28. //样式
  29. const tableFormApp = ref(null)
  30. const tableFormVM = ref(null)
  31. const isTableForm = ref(false)
  32. //渲染完成
  33. onMounted(() => {
  34. getExcelHtml()
  35. })
  36. //html变动
  37. watch(() => props.html, (html) => {
  38. excelHtml.value = html
  39. setExcelHtml()
  40. }, { deep: true })
  41. //深度监听变动的对象数据
  42. watch(() => props.form, (val) => {
  43. excelForm.value = val
  44. setFormData(val)
  45. }, { deep: true })
  46. const setExcelHtml = () => {
  47. //先卸载
  48. if (tableFormApp.value) {
  49. tableFormApp.value?.unmount()
  50. tableFormApp.value = null
  51. nextTick(() => {
  52. getExcelHtml()
  53. })
  54. } else {
  55. getExcelHtml()
  56. }
  57. }
  58. //获取模板标签数据
  59. const getExcelHtml = () => {
  60. const temp = isString(excelHtml.value) ? excelHtml.value : ''
  61. if (isNullES(temp)) {
  62. isTableForm.value = false
  63. excelForm.value.isRenderForm = false
  64. emit('render', excelForm.value)
  65. return
  66. }
  67. //渲染表单
  68. isTableForm.value = true
  69. const { app, vm } = HTableForm.createForm({
  70. template: temp,
  71. tableForm: excelForm.value,
  72. appId: `#table-form-${uuid}`,
  73. onFormDataChange: (form) => {
  74. excelForm.value = form
  75. },
  76. /*onRight: () => {
  77. console.log('onRight')
  78. },
  79. onBlur: () => {
  80. console.log('onBlur')
  81. },
  82. onLeftClick: () => {
  83. console.log('onLeftClick')
  84. },*/
  85. })
  86. tableFormApp.value = app
  87. tableFormVM.value = vm
  88. excelForm.value.isRenderForm = true
  89. emit('render', excelForm.value)
  90. initEmits()
  91. }
  92. //获取表单数据
  93. const getFormData = () => {
  94. return excelForm.value
  95. }
  96. //设置表单数据
  97. const setFormData = (data) => {
  98. excelForm.value = data
  99. tableFormVM.value?.setFormData(excelForm.value)
  100. }
  101. //卸载渲染
  102. const unmountHtml = () => {
  103. if (tableFormApp.value) {
  104. tableFormApp.value?.unmount()
  105. }
  106. }
  107. //获取所有组件
  108. const getAllComponents = async () => {
  109. try {
  110. return document.getElementById(`table-form-${uuid}`).querySelectorAll('.hc-table-form-components-box')
  111. } catch (error) {
  112. return []
  113. }
  114. }
  115. //注册事件
  116. const initEmits = async () => {
  117. const boxs = await getAllComponents()
  118. for (let i = 0; i < boxs.length; i++) {
  119. boxs[i].addEventListener('click', async (e) => {
  120. await tableFormComponentsClick(e)
  121. })
  122. }
  123. }
  124. //被点击
  125. const tableFormComponentsClick = async (e) => {
  126. const boxs = await getAllComponents()
  127. for (let i = 0; i < boxs.length; i++) {
  128. boxs[i].classList.remove('cur')
  129. }
  130. e.target.classList.add('cur')
  131. emit('tap', e)
  132. }
  133. //清空全部选择
  134. const clearClick = async () => {
  135. const boxs = await getAllComponents()
  136. for (let i = 0; i < boxs.length; i++) {
  137. boxs[i].classList.remove('cur')
  138. }
  139. }
  140. //设置选中
  141. const setSelect = async (arr) => {
  142. await clearClick()
  143. if (arr.length <= 0) return
  144. const boxs = await getAllComponents()
  145. for (let i = 0; i < boxs.length; i++) {
  146. const index = boxs[i].getAttribute('data-index')
  147. if (arr.indexOf(index) > -1) {
  148. boxs[i].classList.add('cur')
  149. }
  150. }
  151. }
  152. // 暴露出去
  153. defineExpose({
  154. getFormData,
  155. setFormData,
  156. setExcelHtml,
  157. unmountHtml,
  158. clearClick,
  159. setSelect,
  160. })
  161. </script>
  162. <style lang="scss">
  163. //插入特殊字符弹窗的输入框
  164. .hc-table-form-data-item .hc-excel-table-form td,
  165. .hc-table-form-data-item .hc-excel-table-form td .hc-table-form-components-box {
  166. 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;
  167. }
  168. .hc-table-form-data-item {
  169. position: relative;
  170. padding: 12px;
  171. background-color: white;
  172. border: 1px solid #101010;
  173. border-radius: 4px;
  174. overflow: hidden;
  175. .el-scrollbar .el-scrollbar__bar.is-vertical {
  176. right: -10px;
  177. }
  178. &.no-scroll-bar .el-scrollbar {
  179. display: none;
  180. }
  181. .hc-excel-table-form {
  182. position: relative;
  183. padding: 10px;
  184. display: flex;
  185. justify-content: center;
  186. td {
  187. position: relative;
  188. padding: 6px;
  189. background-clip: padding-box;
  190. //公式
  191. &[gscolor] .hc-table-form-components-box {
  192. background-color: #dcdcdc !important;
  193. }
  194. }
  195. //列合并的单元格
  196. td[rowspan] {
  197. height: initial;
  198. }
  199. //非输入框颜色
  200. td:not([titlexx]), td[titlexx*=''],
  201. td:not([title]), td[title*=''] {
  202. background-color: white !important;
  203. user-select: none;
  204. }
  205. }
  206. }
  207. </style>