|
@@ -0,0 +1,688 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="form-builder">
|
|
|
|
+ <div>
|
|
|
|
+ <h2 class="template-title">{{ templateName }}</h2>
|
|
|
|
+ </div>
|
|
|
|
+ <el-row :gutter="20" class="main-container">
|
|
|
|
+ <el-col :span="5" class="field-selector">
|
|
|
|
+ <div class="panel-content">
|
|
|
|
+ <h3 class="panel-title">选择组件</h3>
|
|
|
|
+ <div class="field-list">
|
|
|
|
+ <div
|
|
|
|
+ v-for="(field, index) in availableFields"
|
|
|
|
+ :key="field.componentId"
|
|
|
|
+ class="field-item"
|
|
|
|
+ @click="addFieldToForm(field, index)"
|
|
|
|
+ >
|
|
|
|
+ <el-button size="small">{{ field.label }}</el-button>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </el-col>
|
|
|
|
+
|
|
|
|
+ <el-col :span="14" class="form-preview">
|
|
|
|
+ <template v-if="formFields.length === 0">
|
|
|
|
+ <div class="empty-tip">请选择添加左侧样式</div>
|
|
|
|
+ </template>
|
|
|
|
+ <draggable
|
|
|
|
+ v-model="formFields"
|
|
|
|
+ 200 animation:
|
|
|
|
+ group="form-fields"
|
|
|
|
+ @end="handleDragEnd"
|
|
|
|
+ >
|
|
|
|
+ <el-scrollbar style="height: 500px; width: 100%;">
|
|
|
|
+ <div
|
|
|
|
+ v-for="(field, index) in formFields"
|
|
|
|
+ :key="index"
|
|
|
|
+ :class="{ 'form-field-active': activeFieldIndex === index }"
|
|
|
|
+ class="form-field-item"
|
|
|
|
+ @click="setActiveField(index)"
|
|
|
|
+ >
|
|
|
|
+ <div class="field-header">
|
|
|
|
+ <el-row align="middle" type="flex">
|
|
|
|
+ <el-col :span="23" class="field-label">
|
|
|
|
+ <span v-if="field.required" class="required-mark">*</span>
|
|
|
|
+ {{ field.label }}
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="1" class="field-operation">
|
|
|
|
+ <i
|
|
|
|
+ v-if="activeFieldIndex === index"
|
|
|
|
+ class="el-icon-delete"
|
|
|
|
+ @click.stop="removeFormField(index)"
|
|
|
|
+ ></i>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- 字段输入组件 -->
|
|
|
|
+ <div class="field-input">
|
|
|
|
+ <!-- 单选框 -->
|
|
|
|
+ <template v-if="field.type === 'radio'">
|
|
|
|
+ <el-radio-group v-model="field.value">
|
|
|
|
+ <el-radio
|
|
|
|
+ v-for="(option, optIdx) in field.options"
|
|
|
|
+ :key="optIdx"
|
|
|
|
+ :label="option"
|
|
|
|
+ style="width: 90px"
|
|
|
|
+ >
|
|
|
|
+ {{ option }}
|
|
|
|
+ </el-radio>
|
|
|
|
+ </el-radio-group>
|
|
|
|
+ </template>
|
|
|
|
+
|
|
|
|
+ <!-- 下拉选择框 -->
|
|
|
|
+ <template v-else-if="field.type === 'select'">
|
|
|
|
+ <el-select
|
|
|
|
+ v-if="!field.multiple"
|
|
|
|
+ v-model="field.value"
|
|
|
|
+ :multiple="field.multiple"
|
|
|
|
+ :placeholder="`请选择${field.label}`"
|
|
|
|
+ clearable
|
|
|
|
+ size="small"
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ >
|
|
|
|
+ <el-option
|
|
|
|
+ v-for="(option, optIdx) in field.options"
|
|
|
|
+ :key="optIdx"
|
|
|
|
+ :label="option"
|
|
|
|
+ :value="optIdx"
|
|
|
|
+ ></el-option>
|
|
|
|
+ </el-select>
|
|
|
|
+
|
|
|
|
+ <el-select
|
|
|
|
+ v-if="field.multiple"
|
|
|
|
+ v-model="field.multiples"
|
|
|
|
+ :multiple="field.multiple"
|
|
|
|
+ :placeholder="`请选择${field.label}`"
|
|
|
|
+ clearable
|
|
|
|
+ size="small"
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ >
|
|
|
|
+ <el-option
|
|
|
|
+ v-for="(option, optIdx) in field.options"
|
|
|
|
+ :key="optIdx"
|
|
|
|
+ :label="option"
|
|
|
|
+ :value="optIdx"
|
|
|
|
+ ></el-option>
|
|
|
|
+ </el-select>
|
|
|
|
+ </template>
|
|
|
|
+
|
|
|
|
+ <!-- 文本输入框 -->
|
|
|
|
+ <template v-else-if="field.type === 'text'">
|
|
|
|
+ <el-input
|
|
|
|
+ v-model="field.value"
|
|
|
|
+ :placeholder="field.placeholder || `请输入${field.label}`"
|
|
|
|
+ clearable
|
|
|
|
+ size="small"
|
|
|
|
+ ></el-input>
|
|
|
|
+ </template>
|
|
|
|
+
|
|
|
|
+ <!-- 复选框 -->
|
|
|
|
+ <template v-else-if="field.type === 'checkbox'">
|
|
|
|
+ <div class="option-container">
|
|
|
|
+ <el-checkbox-group v-model="field.multiples">
|
|
|
|
+ <el-checkbox
|
|
|
|
+ v-for="(option, optIdx) in field.options"
|
|
|
|
+ :key="optIdx"
|
|
|
|
+ :label="optIdx"
|
|
|
|
+ style="width: 90px"
|
|
|
|
+ >{{ option }}
|
|
|
|
+ </el-checkbox>
|
|
|
|
+ </el-checkbox-group>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </el-scrollbar>
|
|
|
|
+ </draggable>
|
|
|
|
+ </el-col>
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ <el-col :span="5" class="field-configurator">
|
|
|
|
+ <template v-if="formFields.length > 0">
|
|
|
|
+ <el-form class="config-form">
|
|
|
|
+ <!-- 字段名称配置 -->
|
|
|
|
+ <el-form-item label="字段名称">
|
|
|
|
+ <el-input
|
|
|
|
+ v-model="formFields[activeFieldIndex].label"
|
|
|
|
+ clearable
|
|
|
|
+ size="small"
|
|
|
|
+ ></el-input>
|
|
|
|
+ </el-form-item>
|
|
|
|
+
|
|
|
|
+ <!-- <template v-if="formFields[activeFieldIndex].type !== 'radio' && formFields[activeFieldIndex].type !== 'checkbox'">-->
|
|
|
|
+ <!-- <el-form-item label="默认值">-->
|
|
|
|
+ <!-- <el-select-->
|
|
|
|
+ <!-- v-model="defaultValueMode"-->
|
|
|
|
+ <!-- size="small"-->
|
|
|
|
+ <!-- style="width: 100%; margin-bottom: 8px"-->
|
|
|
|
+ <!-- >-->
|
|
|
|
+ <!-- <el-option-->
|
|
|
|
+ <!-- v-for="mode in valueModes"-->
|
|
|
|
+ <!-- :key="mode.value"-->
|
|
|
|
+ <!-- :label="mode.label"-->
|
|
|
|
+ <!-- :value="mode.value"-->
|
|
|
|
+ <!-- ></el-option>-->
|
|
|
|
+ <!-- </el-select>-->
|
|
|
|
+ <!-- <el-input-->
|
|
|
|
+ <!-- :v-model="formFields[activeFieldIndex].value"-->
|
|
|
|
+ <!-- clearable-->
|
|
|
|
+ <!-- placeholder="请输入默认值"-->
|
|
|
|
+ <!-- size="small"-->
|
|
|
|
+ <!-- ></el-input>-->
|
|
|
|
+ <!-- </el-form-item>-->
|
|
|
|
+ <!-- </template>-->
|
|
|
|
+
|
|
|
|
+ <template v-if="['radio', 'select','checkbox'].includes(formFields[activeFieldIndex].type)">
|
|
|
|
+ <el-form-item label="选项配置">
|
|
|
|
+ <draggable
|
|
|
|
+ v-model="formFields[activeFieldIndex].options"
|
|
|
|
+ animation:50
|
|
|
|
+ group="options"
|
|
|
|
+ @end="handleOptionDragEnd"
|
|
|
|
+ >
|
|
|
|
+ <el-row
|
|
|
|
+ v-for="(option, idx) in formFields[activeFieldIndex].options"
|
|
|
|
+ :key="idx"
|
|
|
|
+ class="option-item"
|
|
|
|
+ >
|
|
|
|
+ <el-col :span="2" class="option-drag">
|
|
|
|
+ <span class="el-icon-s-operation"></span>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="18">
|
|
|
|
+ <el-input
|
|
|
|
+ v-model="formFields[activeFieldIndex].options[idx]"
|
|
|
|
+ clearable
|
|
|
|
+ size="small"
|
|
|
|
+ ></el-input>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="2" class="option-delete">
|
|
|
|
+ <i
|
|
|
|
+ class="el-icon-delete"
|
|
|
|
+ @click.stop="removeOption(idx)"
|
|
|
|
+ ></i>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ </draggable>
|
|
|
|
+ <el-button
|
|
|
|
+ size="small"
|
|
|
|
+ style="width: 100%; margin-top: 8px"
|
|
|
|
+ @click="addNewOption"
|
|
|
|
+ >
|
|
|
|
+ <span class="el-icon-plus"></span> 添加选项
|
|
|
|
+ </el-button>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </template>
|
|
|
|
+
|
|
|
|
+ <!-- 通用配置:是否必填 -->
|
|
|
|
+ <el-form-item class="required-config" label="是否必填">
|
|
|
|
+ <el-switch v-model="formFields[activeFieldIndex].required"></el-switch>
|
|
|
|
+ </el-form-item>
|
|
|
|
+
|
|
|
|
+ <el-form-item v-if="'select' === formFields[activeFieldIndex].type" class="required-config"
|
|
|
|
+ label="是否多选"
|
|
|
|
+ >
|
|
|
|
+ <el-switch v-model="formFields[activeFieldIndex].multiple"></el-switch>
|
|
|
|
+ </el-form-item>
|
|
|
|
+
|
|
|
|
+ <!-- 文本字段:长度限制 -->
|
|
|
|
+ <el-form-item
|
|
|
|
+ v-if="formFields[activeFieldIndex].type === 'text' && formFields[activeFieldIndex].required"
|
|
|
|
+ class="length-limit"
|
|
|
|
+ label="长度限制"
|
|
|
|
+ >
|
|
|
|
+ <el-input
|
|
|
|
+ v-model.number="formFields[activeFieldIndex].minLength"
|
|
|
|
+ autocomplete="off"
|
|
|
|
+ clearable
|
|
|
|
+ placeholder="最小"
|
|
|
|
+ size="small"
|
|
|
|
+ style="width: 40%; display: inline-block"
|
|
|
|
+ ></el-input>
|
|
|
|
+ <span style="margin: 0 4px">-</span>
|
|
|
|
+ <el-input
|
|
|
|
+ v-model.number="formFields[activeFieldIndex].maxLength"
|
|
|
|
+ autocomplete="off"
|
|
|
|
+ clearable
|
|
|
|
+ placeholder="最大"
|
|
|
|
+ size="small"
|
|
|
|
+ style="width: 40%; display: inline-block"
|
|
|
|
+ ></el-input>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </el-form>
|
|
|
|
+ </template>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+
|
|
|
|
+ <el-row class="action-bar">
|
|
|
|
+ <el-button size="small" @click="resetForm">重置</el-button>
|
|
|
|
+ <el-button size="small" type="primary" @click="submitForm">保存配置</el-button>
|
|
|
|
+ </el-row>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script>
|
|
|
|
+import draggable from 'vuedraggable'
|
|
|
|
+import { getTemplateField, saveTemplate } from '@/api/his/physicalReportTemplateField'
|
|
|
|
+
|
|
|
|
+export default {
|
|
|
|
+ props: {
|
|
|
|
+ templateName: {
|
|
|
|
+ type: String,
|
|
|
|
+ default: '体检报告',
|
|
|
|
+ required: true
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ components: { draggable },
|
|
|
|
+ data() {
|
|
|
|
+ return {
|
|
|
|
+ templateId: null,
|
|
|
|
+ availableFields: [
|
|
|
|
+ { componentId: '1', label: '输入框', type: 'text' },
|
|
|
|
+ { componentId: '2', label: '单选按钮', type: 'radio' },
|
|
|
|
+ { componentId: '3', label: '下拉选项', type: 'select' },
|
|
|
|
+ { componentId: '4', label: '复选框', type: 'checkbox' }
|
|
|
|
+ ],
|
|
|
|
+
|
|
|
|
+ // 中间表单已添加的字段列表
|
|
|
|
+ formFields: [],
|
|
|
|
+
|
|
|
|
+ // 当前激活的字段索引
|
|
|
|
+ activeFieldIndex: 0,
|
|
|
|
+
|
|
|
|
+ // 右侧配置:默认值模式
|
|
|
|
+ defaultValueMode: 1,
|
|
|
|
+
|
|
|
|
+ // 临时存储:默认值模式(用于非单选/下拉字段)
|
|
|
|
+ valueModes: [{ label: '自定义输入', value: 1 }]
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ created() {
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+ computed: {
|
|
|
|
+ // 当前激活字段的类型
|
|
|
|
+ currentFieldType() {
|
|
|
|
+ return this.formFields[this.activeFieldIndex]?.type
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ // 添加字段到表单
|
|
|
|
+ addFieldToForm(field, index) {
|
|
|
|
+ // 检查字段是否已添加(避免重复)
|
|
|
|
+ // const isExist = this.formFields.some(item => item.id === field.id)
|
|
|
|
+ // if (isExist) return
|
|
|
|
+ // 根据字段类型初始化配置
|
|
|
|
+ const fieldConfig = {
|
|
|
|
+ componentId: field.componentId,
|
|
|
|
+ label: field.label,
|
|
|
|
+ type: field.type,
|
|
|
|
+ required: false,
|
|
|
|
+ value: '',
|
|
|
|
+ multiple: false,
|
|
|
|
+ multiples: [],
|
|
|
|
+ placeholder: ''
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 文本字段
|
|
|
|
+ if (field.type === 'text') {
|
|
|
|
+ fieldConfig.minLength = null
|
|
|
|
+ fieldConfig.maxLength = null
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 单选/下拉字段
|
|
|
|
+ if (['radio', 'select', 'checkbox'].includes(field.type)) {
|
|
|
|
+ fieldConfig.options = ['选项1', '选项2']
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.formFields.push(fieldConfig)
|
|
|
|
+ this.activeFieldIndex = this.formFields.length - 1
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 删除表单中的字段
|
|
|
|
+ removeFormField(index) {
|
|
|
|
+ this.formFields.splice(index, 1)
|
|
|
|
+ if (this.activeFieldIndex === index) {
|
|
|
|
+ this.activeFieldIndex = Math.min(index, this.formFields.length - 1)
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 添加新选项
|
|
|
|
+ addNewOption() {
|
|
|
|
+ const currentField = this.formFields[this.activeFieldIndex]
|
|
|
|
+ const optionCount = currentField.options.length + 1
|
|
|
|
+ currentField.options.push(`选项${optionCount}`)
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 删除选项
|
|
|
|
+ removeOption(index) {
|
|
|
|
+ this.formFields[this.activeFieldIndex].options.splice(index, 1)
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 设置当前激活的字段
|
|
|
|
+ setActiveField(index) {
|
|
|
|
+ this.activeFieldIndex = index
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 拖拽结束事件
|
|
|
|
+ handleDragEnd() {
|
|
|
|
+ console.log('字段排序已更新----')
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 拖拽结束事件
|
|
|
|
+ handleOptionDragEnd() {
|
|
|
|
+ console.log('选项排序已更新----')
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 表单验证
|
|
|
|
+ validateForm() {
|
|
|
|
+ if (this.formFields.length === 0) {
|
|
|
|
+ this.$message.error('请至少添加一个字段')
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (let i = 0; i < this.formFields.length; i++) {
|
|
|
|
+ const field = this.formFields[i]
|
|
|
|
+ if (!field.label.trim()) {
|
|
|
|
+ this.activeFieldIndex = i
|
|
|
|
+ this.$message.error('字段名称不能为空')
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // // 验证必填字段
|
|
|
|
+ // if (field.required && field.type !== 'checkbox' && !field.multiple && !field.value && field.value !== 0 || field.required && field.type === 'checkbox' && field.options.length === 0) {
|
|
|
|
+ // this.activeFieldIndex = i
|
|
|
|
+ // this.$message.error(`“${field.label}”为必填项,请补充`)
|
|
|
|
+ // return false
|
|
|
|
+ // }
|
|
|
|
+ //
|
|
|
|
+ // // 验证文本字段长度限制
|
|
|
|
+ // if (field.type === 'text' && field.required) {
|
|
|
|
+ // const valueLength = (field.value || '').length
|
|
|
|
+ // if (field.minLength !== null && valueLength < field.minLength) {
|
|
|
|
+ // this.$message.error(`“${field.label}”长度不能小于${field.minLength}个字符`)
|
|
|
|
+ // return false
|
|
|
|
+ // }
|
|
|
|
+ // if (field.maxLength !== null && valueLength > field.maxLength) {
|
|
|
|
+ // this.$message.error(`“${field.label}”长度不能大于${field.maxLength}个字符`)
|
|
|
|
+ // return false
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 提交表单配置
|
|
|
|
+ submitForm() {
|
|
|
|
+ if (!this.validateForm()) return
|
|
|
|
+ // 数据过滤
|
|
|
|
+ const formData = this.formFields.map(field => {
|
|
|
|
+ const multiple = field.multiple ? 1 : 0
|
|
|
|
+ const required = field.required ? 1 : 0
|
|
|
|
+ const {
|
|
|
|
+ componentId,
|
|
|
|
+ label,
|
|
|
|
+ type,
|
|
|
|
+ value,
|
|
|
|
+ options,
|
|
|
|
+ maxLength,
|
|
|
|
+ minLength
|
|
|
|
+ } = field
|
|
|
|
+
|
|
|
|
+ const result = {
|
|
|
|
+ componentId,
|
|
|
|
+ label,
|
|
|
|
+ type,
|
|
|
|
+ required,
|
|
|
|
+ value,
|
|
|
|
+ maxLength,
|
|
|
|
+ minLength,
|
|
|
|
+ multiple
|
|
|
|
+ }
|
|
|
|
+ if (options) {
|
|
|
|
+ result.options = options.join(',')
|
|
|
|
+ }
|
|
|
|
+ return result
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ saveTemplate({ templateId: this.templateId, templateFieldList: formData }).then(response => {
|
|
|
|
+ if (response.code === 200) {
|
|
|
|
+ this.$message.success('保存成功!')
|
|
|
|
+ }
|
|
|
|
+ this.getTemplateField(this.templateId)
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 重置表单
|
|
|
|
+ resetForm() {
|
|
|
|
+ this.formFields = []
|
|
|
|
+ this.activeFieldIndex = 0
|
|
|
|
+ this.$message.info('已重置表单配置')
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获取自定义数据列表
|
|
|
|
+ * **/
|
|
|
|
+ getTemplateField(templateId) {
|
|
|
|
+ this.templateId = templateId
|
|
|
|
+
|
|
|
|
+ getTemplateField(templateId).then(response => {
|
|
|
|
+ if (response.data.length > 0) {
|
|
|
|
+ //处理数据处理
|
|
|
|
+ this.formFields = response.data.map(item => {
|
|
|
|
+ const multiple = item.multiple === 1
|
|
|
|
+ const required = item.required === 1
|
|
|
|
+ const multiples = []
|
|
|
|
+ const {
|
|
|
|
+ componentId,
|
|
|
|
+ label,
|
|
|
|
+ type,
|
|
|
|
+ value,
|
|
|
|
+ options,
|
|
|
|
+ maxLength,
|
|
|
|
+ minLength
|
|
|
|
+ } = item
|
|
|
|
+
|
|
|
|
+ const result = {
|
|
|
|
+ componentId,
|
|
|
|
+ label,
|
|
|
|
+ type,
|
|
|
|
+ required,
|
|
|
|
+ value,
|
|
|
|
+ maxLength,
|
|
|
|
+ minLength,
|
|
|
|
+ multiple,
|
|
|
|
+ multiples
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (options) {
|
|
|
|
+ result.options = options.split(',').map(item => item.trim())
|
|
|
|
+ }
|
|
|
|
+ return result
|
|
|
|
+ })
|
|
|
|
+ this.activeFieldIndex = this.formFields.length - 1
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style scoped>
|
|
|
|
+.form-builder {
|
|
|
|
+ padding: 15px;
|
|
|
|
+ background-color: #f5f7fa;
|
|
|
|
+ min-height: calc(94vh - 30px);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.main-container {
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.field-selector {
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ border-radius: 6px;
|
|
|
|
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
|
|
|
+ padding: 15px !important;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.panel-title {
|
|
|
|
+ font-size: 15px;
|
|
|
|
+ color: #1f2329;
|
|
|
|
+ margin: 0 0 15px;
|
|
|
|
+ padding-left: 4px;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.field-list {
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
+ gap: 10px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.field-item {
|
|
|
|
+ width: 100px;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.field-item .el-button {
|
|
|
|
+ width: 100%;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* 中间表单预览区 */
|
|
|
|
+.form-preview {
|
|
|
|
+ padding: 0 10px !important;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.empty-tip {
|
|
|
|
+ height: 60px;
|
|
|
|
+ line-height: 60px;
|
|
|
|
+ text-align: center;
|
|
|
|
+ border: 1px dashed #dcdfe6;
|
|
|
|
+ color: #8c8c8c;
|
|
|
|
+ border-radius: 6px;
|
|
|
|
+ margin-top: 10px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.form-field-item {
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ border: 1px solid #e5e6eb;
|
|
|
|
+ border-radius: 6px;
|
|
|
|
+ padding: 12px 15px;
|
|
|
|
+ margin-bottom: 12px;
|
|
|
|
+ transition: all 0.2s;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.form-field-item:hover {
|
|
|
|
+ border-color: #c0c4cc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.form-field-active {
|
|
|
|
+ border-color: #409eff;
|
|
|
|
+ background-color: #f0f7ff;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.field-header {
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.field-label {
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ color: #1f2329;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.required-mark {
|
|
|
|
+ color: #ff4d4f;
|
|
|
|
+ margin-right: 4px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.field-operation {
|
|
|
|
+ color: #8c8c8c;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.field-operation:hover {
|
|
|
|
+ color: #ff4d4f;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.field-configurator {
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ border-radius: 6px;
|
|
|
|
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
|
|
|
+ padding: 15px !important;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.config-form .el-form-item {
|
|
|
|
+ margin-bottom: 12px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.config-form .el-form-item__label {
|
|
|
|
+ font-size: 13px;
|
|
|
|
+ color: #4e5969;
|
|
|
|
+ padding: 0 0 6px;
|
|
|
|
+ line-height: 1;
|
|
|
|
+ width: 100%;
|
|
|
|
+ text-align: left;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.option-item {
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ width: 100%;
|
|
|
|
+ margin: 0 !important;
|
|
|
|
+ padding: 4px 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.option-drag {
|
|
|
|
+ color: #c9cdD4;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.option-delete {
|
|
|
|
+ color: #8c8c8c;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.option-delete:hover {
|
|
|
|
+ color: #ff4d4f;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.action-bar {
|
|
|
|
+ text-align: center;
|
|
|
|
+ padding: 10px 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.action-bar .el-button {
|
|
|
|
+ margin: 0 5px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.empty-tip {
|
|
|
|
+ height: 60px;
|
|
|
|
+ line-height: 60px;
|
|
|
|
+ text-align: center;
|
|
|
|
+ border: 1px dashed #dcdfe6;
|
|
|
|
+ color: #8c8c8c;
|
|
|
|
+ border-radius: 6px;
|
|
|
|
+ margin-top: 10px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+@media (max-width: 1200px) {
|
|
|
|
+ .field-selector,
|
|
|
|
+ .field-configurator {
|
|
|
|
+ padding: 10px !important;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.option-container {
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
+ align-items: flex-start;
|
|
|
|
+ gap: 16px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.template-title {
|
|
|
|
+ text-align: center;
|
|
|
|
+ margin: 0;
|
|
|
|
+ line-height: 50px;
|
|
|
|
+}
|
|
|
|
+</style>
|