DesignForm.vue 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <template>
  2. <section h-full bg-white flex>
  3. <aside pt-2 w-62>
  4. <ComponentGroup
  5. title="基础字段"
  6. :fields="basicFieldsList"
  7. :list="basicComponents"
  8. :allList="widgetForm"
  9. />
  10. <ComponentGroup
  11. title="高级字段"
  12. :fields="advanceFieldsList"
  13. :list="advanceComponents"
  14. :allList="widgetForm"
  15. />
  16. <ComponentGroup
  17. title="布局字段"
  18. :fields="layoutFieldsList"
  19. :list="layoutComponents"
  20. :allList="widgetForm"
  21. />
  22. </aside>
  23. <main border="0 x solid gray-200" flex="~ 1 col nowrap">
  24. <header border="0 b solid gray-200" flex gap-2 items-center justify-end h-11 py-0 px-2>
  25. <slot />
  26. <el-button v-if="generateJson" type="text" @click="handleGenerateJson">
  27. <template #icon>
  28. <i class="ep:edit" />
  29. </template>修改
  30. </el-button>
  31. <el-button v-if="clearable" type="text" @click="handleClearable">
  32. <template #icon>
  33. <i class="custom:clearable" />
  34. </template>清空
  35. </el-button>
  36. <el-button v-if="preview" type="text" @click="previewVisible = true">
  37. <template #icon>
  38. <i class="custom:preview" />
  39. </template>预览
  40. </el-button>
  41. </header>
  42. <WidgetFormVue
  43. ref="widgetFormRef"
  44. v-bind="widgetForm"
  45. v-model:selectWidget="selectWidget"
  46. />
  47. </main>
  48. <aside relative w-75 flex="~ col">
  49. <header border="0 b-1 gray-200" grid="~ cols-2" min-h-11 px-2>
  50. <div :class="[{active:!tab}, 'config-tab']" @click="tab = 0">
  51. 字段属性
  52. </div>
  53. <div :class="[{active:tab}, 'config-tab']" @click="tab = 1">
  54. 表单属性
  55. </div>
  56. </header>
  57. <WidgetConfig
  58. v-show="!tab"
  59. v-model:select="selectWidget"
  60. />
  61. <FormConfig
  62. v-show="tab"
  63. v-model:config="widgetForm.config"
  64. />
  65. </aside>
  66. <el-dialog v-model="previewVisible" destroy-on-close title="预览" :z-index="2000" :width="800" @close="dataVisible=false">
  67. <CodeEditor v-show="dataVisible" v-model="generateJsonTemplate" />
  68. <GenerateForm
  69. v-show="!dataVisible"
  70. ref="generateFormRef"
  71. :request="request"
  72. :data="widgetForm"
  73. />
  74. <template #footer>
  75. <el-button @click="dataVisible?handleCopyClick(generateJsonTemplate):handleReset()">
  76. {{ dataVisible?'复制':'重置' }}
  77. </el-button>
  78. <el-button type="primary" @click="handleGetData">
  79. {{ dataVisible?'返回预览':'获取数据' }}
  80. </el-button>
  81. </template>
  82. </el-dialog>
  83. <el-dialog v-model="generateJsonVisible" append-to-body title="修改JSON" :z-index="20000" :width="800">
  84. <CodeEditor v-model="generateJsonTemplate" />
  85. <template #footer>
  86. <el-button @click="handleCopyClick(generateJsonTemplate)">
  87. 复制
  88. </el-button>
  89. <el-button type="primary" @click="handleUploadJson">
  90. 确认修改
  91. </el-button>
  92. </template>
  93. </el-dialog>
  94. </section>
  95. </template>
  96. <script lang="ts" setup>
  97. import type { PropType } from 'vue'
  98. import { ElMessage } from 'element-plus'
  99. // eslint-disable-next-line @typescript-eslint/consistent-type-imports
  100. import GenerateForm from '../generate/GenerateForm.vue'
  101. import WidgetFormVue from './WidgetForm.vue'
  102. import WidgetConfig from './WidgetConfig.vue'
  103. import FormConfig from './FormConfig.vue'
  104. import ComponentGroup from '@/components/ComponentGroup.vue'
  105. import CodeEditor from '@/components/CodeEditor.vue'
  106. import type { WidgetForm } from '@/config'
  107. import { advanceComponents, advanceFields, basicComponents, basicFields, getWidgetForm, layoutComponents, layoutFields } from '@/config'
  108. defineOptions({ name: 'DesignForm' })
  109. defineProps({
  110. preview: {
  111. type: Boolean,
  112. default: true,
  113. },
  114. generateJson: {
  115. type: Boolean,
  116. default: true,
  117. },
  118. clearable: {
  119. type: Boolean,
  120. default: true,
  121. },
  122. basicFieldsList: {
  123. type: Array as PropType<typeof basicFields>,
  124. default: () => basicFields,
  125. },
  126. advanceFieldsList: {
  127. type: Array as PropType<typeof advanceFields>,
  128. default: () => advanceFields,
  129. },
  130. layoutFieldsList: {
  131. type: Array as PropType<typeof layoutFields>,
  132. default: () => layoutFields,
  133. },
  134. request: {
  135. type: Function,
  136. },
  137. })
  138. let tab = $ref(0)
  139. let selectWidget = $ref<any>()
  140. watch(() => selectWidget, (val) => {
  141. tab = val ? 0 : 1
  142. })
  143. let widgetForm = $ref(getWidgetForm())
  144. let generateJsonVisible = $ref(false)
  145. let generateJsonTemplate = $ref(JSON.stringify(getWidgetForm(), null, 2))
  146. const handleUploadJson = () => {
  147. try {
  148. widgetForm = JSON.parse(generateJsonTemplate)
  149. selectWidget = widgetForm.list?.[0]
  150. generateJsonVisible = false
  151. ElMessage.success('修改成功')
  152. }
  153. catch (error) {
  154. ElMessage.error('修改失败,请检查JSON格式是否正确。')
  155. }
  156. }
  157. const handleGenerateJson = () =>
  158. (generateJsonTemplate = JSON.stringify(widgetForm, null, 2))
  159. && (generateJsonVisible = true)
  160. const handleClearable = () => {
  161. widgetForm = getWidgetForm()
  162. selectWidget = undefined
  163. }
  164. let dataVisible = $ref(false)
  165. const generateFormRef = $ref<InstanceType<typeof GenerateForm>|null>(null)
  166. const handleGetData = async() => {
  167. dataVisible = !dataVisible
  168. if (!dataVisible) return
  169. const res = await generateFormRef?.getData()
  170. generateJsonTemplate = JSON.stringify(res, null, 2)
  171. }
  172. const handleReset = () => generateFormRef?.reset()
  173. const handleCopyClick = (text: string) => {
  174. navigator.clipboard.writeText(text)
  175. ElMessage.success({ message: 'Copy成功' })
  176. }
  177. const previewVisible = $ref(false)
  178. defineExpose({
  179. getJson: () => $$(widgetForm).value,
  180. setJson: (json: WidgetForm) => {
  181. widgetForm = json
  182. selectWidget = json.list?.[0]
  183. },
  184. clear: handleClearable,
  185. })
  186. </script>
  187. <style lang="scss">
  188. .config-tab {
  189. @apply cursor-pointer text-sm text-gray-700
  190. flex items-center justify-center
  191. border-0 border-b-2 border-white;
  192. &.active {
  193. @apply border-blue-500;
  194. }
  195. }
  196. </style>