index.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <template>
  2. <ContentWrap :body-style="{ padding: '0px' }" class="!mb-0">
  3. <!-- 表单设计器 -->
  4. <div
  5. class="h-[calc(100vh-var(--top-tool-height)-var(--tags-view-height)-var(--app-content-padding)-var(--app-content-padding)-2px)]"
  6. >
  7. <fc-designer class="my-designer" ref="designer" :config="designerConfig">
  8. <template #handle>
  9. <el-button size="small" type="primary" plain @click="showJson">生成JSON</el-button>
  10. <el-button size="small" type="success" plain @click="showOption">生成Options</el-button>
  11. <el-button size="small" type="danger" plain @click="showTemplate">生成组件</el-button>
  12. </template>
  13. </fc-designer>
  14. </div>
  15. </ContentWrap>
  16. <!-- 弹窗:表单预览 -->
  17. <Dialog v-model="dialogVisible" :title="dialogTitle" max-height="600">
  18. <div v-if="dialogVisible" ref="editor">
  19. <el-button style="float: right" @click="copy(formData)">
  20. {{ t('common.copy') }}
  21. </el-button>
  22. <el-scrollbar height="580">
  23. <div>
  24. <pre><code v-dompurify-html="highlightedCode(formData)" class="hljs"></code></pre>
  25. </div>
  26. </el-scrollbar>
  27. </div>
  28. </Dialog>
  29. </template>
  30. <script lang="ts" setup>
  31. import { useFormCreateDesigner } from '@/components/FormCreate'
  32. import { useClipboard } from '@vueuse/core'
  33. import { isString } from '@/utils/is'
  34. import hljs from 'highlight.js' // 导入代码高亮文件
  35. import 'highlight.js/styles/github.css' // 导入代码高亮样式
  36. import xml from 'highlight.js/lib/languages/java'
  37. import json from 'highlight.js/lib/languages/json'
  38. import formCreate from '@form-create/element-ui'
  39. defineOptions({ name: 'InfraBuild' })
  40. const { t } = useI18n() // 国际化
  41. const message = useMessage() // 消息
  42. // 表单设计器配置
  43. const designerConfig = ref({
  44. switchType: [], // 是否可以切换组件类型,或者可以相互切换的字段
  45. autoActive: true, // 是否自动选中拖入的组件
  46. useTemplate: false, // 是否生成vue2语法的模板组件
  47. formOptions: {
  48. form: {
  49. labelWidth: '100px' // 设置默认的 label 宽度为 100px
  50. }
  51. }, // 定义表单配置默认值
  52. fieldReadonly: false, // 配置field是否可以编辑
  53. hiddenDragMenu: false, // 隐藏拖拽操作按钮
  54. hiddenDragBtn: false, // 隐藏拖拽按钮
  55. hiddenMenu: [], // 隐藏部分菜单
  56. hiddenItem: [], // 隐藏部分组件
  57. hiddenItemConfig: {}, // 隐藏组件的部分配置项
  58. disabledItemConfig: {}, // 禁用组件的部分配置项
  59. showSaveBtn: false, // 是否显示保存按钮
  60. showConfig: true, // 是否显示右侧的配置界面
  61. showBaseForm: true, // 是否显示组件的基础配置表单
  62. showControl: true, // 是否显示组件联动
  63. showPropsForm: true, // 是否显示组件的属性配置表单
  64. showEventForm: true, // 是否显示组件的事件配置表单
  65. showValidateForm: true, // 是否显示组件的验证配置表单
  66. showFormConfig: true, // 是否显示表单配置
  67. showInputData: true, // 是否显示录入按钮
  68. showDevice: true, // 是否显示多端适配选项
  69. appendConfigData: [] // 定义渲染规则所需的formData
  70. })
  71. const designer = ref() // 表单设计器
  72. const dialogVisible = ref(false) // 弹窗的是否展示
  73. const dialogTitle = ref('') // 弹窗的标题
  74. const formType = ref(-1) // 表单的类型:0 - 生成 JSON;1 - 生成 Options;2 - 生成组件
  75. const formData = ref('') // 表单数据
  76. useFormCreateDesigner(designer) // 表单设计器增强
  77. /** 打开弹窗 */
  78. const openModel = (title: string) => {
  79. dialogVisible.value = true
  80. dialogTitle.value = title
  81. }
  82. /** 生成 JSON */
  83. const showJson = () => {
  84. openModel('生成 JSON')
  85. formType.value = 0
  86. formData.value = designer.value.getRule()
  87. }
  88. /** 生成 Options */
  89. const showOption = () => {
  90. openModel('生成 Options')
  91. formType.value = 1
  92. formData.value = designer.value.getOption()
  93. }
  94. /** 生成组件 */
  95. const showTemplate = () => {
  96. openModel('生成组件')
  97. formType.value = 2
  98. formData.value = makeTemplate()
  99. }
  100. const makeTemplate = () => {
  101. const rule = designer.value.getRule()
  102. const opt = designer.value.getOption()
  103. return `<template>
  104. <form-create
  105. v-model:api="fApi"
  106. :rule="rule"
  107. :option="option"
  108. @submit="onSubmit"
  109. ></form-create>
  110. </template>
  111. <script setup lang=ts>
  112. const faps = ref(null)
  113. const rule = ref('')
  114. const option = ref('')
  115. const init = () => {
  116. rule.value = formCreate.parseJson('${formCreate.toJson(rule).replaceAll('\\', '\\\\')}')
  117. option.value = formCreate.parseJson('${JSON.stringify(opt)}')
  118. }
  119. const onSubmit = (formData) => {
  120. //todo 提交表单
  121. }
  122. init()
  123. <\/script>`
  124. }
  125. /** 复制 **/
  126. const copy = async (text: string) => {
  127. const textToCopy = JSON.stringify(text, null, 2)
  128. const { copy, copied, isSupported } = useClipboard({ source: textToCopy })
  129. if (!isSupported) {
  130. message.error(t('common.copyError'))
  131. } else {
  132. await copy()
  133. if (unref(copied)) {
  134. message.success(t('common.copySuccess'))
  135. }
  136. }
  137. }
  138. /**
  139. * 代码高亮
  140. */
  141. const highlightedCode = (code: string) => {
  142. // 处理语言和代码
  143. let language = 'json'
  144. if (formType.value === 2) {
  145. language = 'xml'
  146. }
  147. // debugger
  148. if (!isString(code)) {
  149. code = JSON.stringify(code, null, 2)
  150. }
  151. // 高亮
  152. const result = hljs.highlight(code, { language: language, ignoreIllegals: true })
  153. return result.value || '&nbsp;'
  154. }
  155. /** 初始化 **/
  156. onMounted(async () => {
  157. // 注册代码高亮的各种语言
  158. hljs.registerLanguage('xml', xml)
  159. hljs.registerLanguage('json', json)
  160. })
  161. </script>
  162. <style>
  163. .my-designer {
  164. ._fc-l,
  165. ._fc-m,
  166. ._fc-r {
  167. border-top: none;
  168. }
  169. }
  170. </style>