index.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. fieldReadonly: false, // 配置field是否可以编辑
  49. hiddenDragMenu: false, // 隐藏拖拽操作按钮
  50. hiddenDragBtn: false, // 隐藏拖拽按钮
  51. hiddenMenu: [], // 隐藏部分菜单
  52. hiddenItem: [], // 隐藏部分组件
  53. hiddenItemConfig: {}, // 隐藏组件的部分配置项
  54. disabledItemConfig: {}, // 禁用组件的部分配置项
  55. showSaveBtn: false, // 是否显示保存按钮
  56. showConfig: true, // 是否显示右侧的配置界面
  57. showBaseForm: true, // 是否显示组件的基础配置表单
  58. showControl: true, // 是否显示组件联动
  59. showPropsForm: true, // 是否显示组件的属性配置表单
  60. showEventForm: true, // 是否显示组件的事件配置表单
  61. showValidateForm: true, // 是否显示组件的验证配置表单
  62. showFormConfig: true, // 是否显示表单配置
  63. showInputData: true, // 是否显示录入按钮
  64. showDevice: true, // 是否显示多端适配选项
  65. appendConfigData: [] // 定义渲染规则所需的formData
  66. })
  67. const designer = ref() // 表单设计器
  68. const dialogVisible = ref(false) // 弹窗的是否展示
  69. const dialogTitle = ref('') // 弹窗的标题
  70. const formType = ref(-1) // 表单的类型:0 - 生成 JSON;1 - 生成 Options;2 - 生成组件
  71. const formData = ref('') // 表单数据
  72. useFormCreateDesigner(designer) // 表单设计器增强
  73. /** 打开弹窗 */
  74. const openModel = (title: string) => {
  75. dialogVisible.value = true
  76. dialogTitle.value = title
  77. }
  78. /** 生成 JSON */
  79. const showJson = () => {
  80. openModel('生成 JSON')
  81. formType.value = 0
  82. formData.value = designer.value.getRule()
  83. }
  84. /** 生成 Options */
  85. const showOption = () => {
  86. openModel('生成 Options')
  87. formType.value = 1
  88. formData.value = designer.value.getOption()
  89. }
  90. /** 生成组件 */
  91. const showTemplate = () => {
  92. openModel('生成组件')
  93. formType.value = 2
  94. formData.value = makeTemplate()
  95. }
  96. const makeTemplate = () => {
  97. const rule = designer.value.getRule()
  98. const opt = designer.value.getOption()
  99. return `<template>
  100. <form-create
  101. v-model:api="fApi"
  102. :rule="rule"
  103. :option="option"
  104. @submit="onSubmit"
  105. ></form-create>
  106. </template>
  107. <script setup lang=ts>
  108. const faps = ref(null)
  109. const rule = ref('')
  110. const option = ref('')
  111. const init = () => {
  112. rule.value = formCreate.parseJson('${formCreate.toJson(rule).replaceAll('\\', '\\\\')}')
  113. option.value = formCreate.parseJson('${JSON.stringify(opt)}')
  114. }
  115. const onSubmit = (formData) => {
  116. //todo 提交表单
  117. }
  118. init()
  119. <\/script>`
  120. }
  121. /** 复制 **/
  122. const copy = async (text: string) => {
  123. const { copy, copied, isSupported } = useClipboard({ source: text })
  124. if (!isSupported) {
  125. message.error(t('common.copyError'))
  126. } else {
  127. await copy()
  128. if (unref(copied)) {
  129. message.success(t('common.copySuccess'))
  130. }
  131. }
  132. }
  133. /**
  134. * 代码高亮
  135. */
  136. const highlightedCode = (code) => {
  137. // 处理语言和代码
  138. let language = 'json'
  139. if (formType.value === 2) {
  140. language = 'xml'
  141. }
  142. if (!isString(code)) {
  143. code = JSON.stringify(code)
  144. }
  145. // 高亮
  146. const result = hljs.highlight(language, code, true)
  147. return result.value || '&nbsp;'
  148. }
  149. /** 初始化 **/
  150. onMounted(async () => {
  151. // 注册代码高亮的各种语言
  152. hljs.registerLanguage('xml', xml)
  153. hljs.registerLanguage('json', json)
  154. })
  155. </script>
  156. <style>
  157. .my-designer {
  158. ._fc-l,
  159. ._fc-m,
  160. ._fc-r {
  161. border-top: none;
  162. }
  163. }
  164. </style>