|
|
|
|
<!--
|
|
|
|
|
@ 作者: 秦东
|
|
|
|
|
@ 时间: 2023-05-26 10:35:30
|
|
|
|
|
@ 备注:
|
|
|
|
|
-->
|
|
|
|
|
<script lang='ts' setup>
|
|
|
|
|
import '@/assets/scss/element-var.scss'
|
|
|
|
|
import '@/assets/scss/index.scss'
|
|
|
|
|
import '@/assets/iconfont/iconfont.css'
|
|
|
|
|
|
|
|
|
|
import { useDesignFormStore } from '@/store/DesignForm/designForm'
|
|
|
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
|
|
|
import {
|
|
|
|
|
json2string,
|
|
|
|
|
objToStringify,
|
|
|
|
|
string2json,
|
|
|
|
|
stringToObj
|
|
|
|
|
} from '@/utils/DesignForm/form'
|
|
|
|
|
|
|
|
|
|
import { getRequest } from '@/api/DesignForm'
|
|
|
|
|
import { afterResponse, beforeRequest, onChange } from '@/api/DesignForm/utils'
|
|
|
|
|
|
|
|
|
|
//引入页面
|
|
|
|
|
import DragControl from '@/components/DesignForm/dragControl.vue';
|
|
|
|
|
import HeadTools from '@/components/DesignForm/public/headTools.vue';
|
|
|
|
|
import FormDesign from '@/components/DesignForm/public/form/form.vue'
|
|
|
|
|
|
|
|
|
|
const store = useDesignFormStore()
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
const route: any = useRoute().query || {}
|
|
|
|
|
const vueFileEl = ref()
|
|
|
|
|
|
|
|
|
|
const state = reactive({
|
|
|
|
|
formData: {
|
|
|
|
|
list: [],
|
|
|
|
|
form: {
|
|
|
|
|
size: 'default'
|
|
|
|
|
},
|
|
|
|
|
config: {},
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
editor: {},
|
|
|
|
|
loading: false,
|
|
|
|
|
formDataPreview: {},
|
|
|
|
|
previewVisible: false, // 预览窗口
|
|
|
|
|
designType: route.type, // 当前页面设计类型,有效值search
|
|
|
|
|
formDict: {},
|
|
|
|
|
formOtherData: {
|
|
|
|
|
source: route.source || '',
|
|
|
|
|
formName: '未命名表单'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
const drawer = reactive({
|
|
|
|
|
visible: false,
|
|
|
|
|
type: '',
|
|
|
|
|
title: '',
|
|
|
|
|
codeType: '',
|
|
|
|
|
direction: undefined, //弹出方向rtl / ltr
|
|
|
|
|
callback: '',
|
|
|
|
|
content:{}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const headToolClick = (type: string) => {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case 'del':
|
|
|
|
|
state.formData.list = []
|
|
|
|
|
store.setActiveKey('')
|
|
|
|
|
store.setControlAttr({})
|
|
|
|
|
break
|
|
|
|
|
case 'eye':
|
|
|
|
|
// 打开预览窗口
|
|
|
|
|
store.setActiveKey('')
|
|
|
|
|
store.setControlAttr({})
|
|
|
|
|
state.previewVisible = true
|
|
|
|
|
// eslint-disable-next-line no-case-declarations
|
|
|
|
|
let stringPreview = objToStringify(state.formData) // 防止预览窗口数据修改影响
|
|
|
|
|
// eslint-disable-next-line no-case-declarations
|
|
|
|
|
const formName = state.formData.form.name
|
|
|
|
|
// eslint-disable-next-line no-case-declarations
|
|
|
|
|
const reg = new RegExp(`get${formName}ControlByName`, 'g')
|
|
|
|
|
stringPreview = stringPreview.replace(
|
|
|
|
|
reg,
|
|
|
|
|
`getPreview${formName}ControlByName`
|
|
|
|
|
)
|
|
|
|
|
state.formDataPreview = stringToObj(stringPreview)
|
|
|
|
|
state.formDataPreview.form.name = `Preview${formName}` // 修改下表单名
|
|
|
|
|
break
|
|
|
|
|
case 'json':
|
|
|
|
|
// 生成脚本预览
|
|
|
|
|
openAceEditDrawer({
|
|
|
|
|
direction: 'rtl',
|
|
|
|
|
content: state.formData,
|
|
|
|
|
title: '可编辑修改或将已生成的脚本粘贴进来'
|
|
|
|
|
})
|
|
|
|
|
break
|
|
|
|
|
case 'save':
|
|
|
|
|
saveData()
|
|
|
|
|
break
|
|
|
|
|
case 'vue':
|
|
|
|
|
vueFileEl.value.open(state.formData)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 将数据保存在服务端
|
|
|
|
|
const saveData = () => {
|
|
|
|
|
// 添加校验,没有选择数据源时则必须要配置接口url
|
|
|
|
|
const { addUrl, editUrl, requestUrl } = state.formData.config
|
|
|
|
|
if (
|
|
|
|
|
!state.formOtherData.source &&
|
|
|
|
|
(!addUrl || !editUrl || !requestUrl) &&
|
|
|
|
|
state.designType !== 'search'
|
|
|
|
|
) {
|
|
|
|
|
ElMessage.error('请选择数据源或配置接口url地址,否则表单无法提交保存')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
let params: any = {
|
|
|
|
|
data: objToStringify(state.formData),
|
|
|
|
|
source: state.formOtherData.source, // 数据源允许在表单属性设置里修改的
|
|
|
|
|
name: state.formOtherData.formName, // 表单名称,用于在显示所有已创建的表单列表里显示
|
|
|
|
|
type: 1, // 1表单 2列表
|
|
|
|
|
dict: json2string(state.formDict)
|
|
|
|
|
}
|
|
|
|
|
let apiKey = 'designSave'
|
|
|
|
|
if (route.id) {
|
|
|
|
|
// 编辑状态 当前记录id
|
|
|
|
|
Object.assign(params, { id: route.id })
|
|
|
|
|
apiKey = 'designEdit'
|
|
|
|
|
}
|
|
|
|
|
// 列表搜索模式下只有修改
|
|
|
|
|
if (state.designType === 'search') {
|
|
|
|
|
params = {
|
|
|
|
|
data: objToStringify(state.formData),
|
|
|
|
|
dict: json2string(state.formDict),
|
|
|
|
|
id: route.id
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
state.loading = true
|
|
|
|
|
getRequest(apiKey, params)
|
|
|
|
|
.then((res: any) => {
|
|
|
|
|
ElMessage({
|
|
|
|
|
message: res.message || '保存成功!',
|
|
|
|
|
type: 'success'
|
|
|
|
|
})
|
|
|
|
|
// 根据不同情况跳转到不同地址
|
|
|
|
|
const path = route.redirect || '/design/form/list'
|
|
|
|
|
const query: any = {}
|
|
|
|
|
if (route.redirect && route.redirect.indexOf('?') !== -1) {
|
|
|
|
|
// 带有问号参数时,放在path传是有问题的,将id=1转为{id:1}
|
|
|
|
|
const p = route.redirect.split('?')[1]
|
|
|
|
|
const pSplit = p.split('&')
|
|
|
|
|
pSplit.forEach((item: string) => {
|
|
|
|
|
const splitItem = item.split('=')
|
|
|
|
|
query[splitItem[0]] = splitItem[1]
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
router.push({ path: path, query: query })
|
|
|
|
|
state.loading = false
|
|
|
|
|
})
|
|
|
|
|
.catch((res: any) => {
|
|
|
|
|
ElMessage.error(res.message || '保存异常')
|
|
|
|
|
state.loading = false
|
|
|
|
|
})
|
|
|
|
|
// 清空右侧内容管理菜单存在session的内容,刷新时可重新加载新菜单
|
|
|
|
|
if (!route.id) {
|
|
|
|
|
// 新增时
|
|
|
|
|
window.sessionStorage.removeItem('formMenuList')
|
|
|
|
|
}
|
|
|
|
|
// 清空右侧栏信息
|
|
|
|
|
store.setActiveKey('')
|
|
|
|
|
store.setControlAttr({})
|
|
|
|
|
}
|
|
|
|
|
const openAceEditDrawer = (params: any) => {
|
|
|
|
|
const { type, direction, codeType, title, callback, content } = params
|
|
|
|
|
drawer.direction = direction // 窗口位置ltr/rtl
|
|
|
|
|
drawer.type = type // 作为窗口唯一标识,在窗口关闭时可根据type作不同处理
|
|
|
|
|
drawer.codeType = codeType || '' // 显示代码类型
|
|
|
|
|
drawer.title = title ? `提示:${title}` : ''
|
|
|
|
|
drawer.visible = true
|
|
|
|
|
drawer.callback = callback
|
|
|
|
|
let editData =
|
|
|
|
|
codeType === 'json'
|
|
|
|
|
? json2string(content, true)
|
|
|
|
|
: objToStringify(content, true)
|
|
|
|
|
switch (type) {
|
|
|
|
|
case 'css':
|
|
|
|
|
editData = state.formData.config?.style || ''
|
|
|
|
|
break
|
|
|
|
|
case 'dict':
|
|
|
|
|
// 格式化一下
|
|
|
|
|
editData = json2string(state.formDict, true)
|
|
|
|
|
break
|
|
|
|
|
case 'beforeRequest':
|
|
|
|
|
case 'beforeSubmit':
|
|
|
|
|
case 'afterResponse':
|
|
|
|
|
case 'afterSubmit':
|
|
|
|
|
case 'change':
|
|
|
|
|
// eslint-disable-next-line no-case-declarations
|
|
|
|
|
const beforeData = state.formData.events || {}
|
|
|
|
|
if (beforeData[type]) {
|
|
|
|
|
editData = objToStringify(beforeData[type], true)
|
|
|
|
|
} else {
|
|
|
|
|
if (['afterResponse', 'afterSubmit'].includes(type)) {
|
|
|
|
|
editData = afterResponse
|
|
|
|
|
} else if (type === 'change') {
|
|
|
|
|
editData = onChange
|
|
|
|
|
} else {
|
|
|
|
|
editData = beforeRequest
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
// case 'afterResponse':
|
|
|
|
|
// case 'afterSubmit':
|
|
|
|
|
// const newData = state.formData.events || {}
|
|
|
|
|
// if (newData[type]) {
|
|
|
|
|
// editData = objToStringify(newData[type], true)
|
|
|
|
|
// } else {
|
|
|
|
|
// editData = afterResponse
|
|
|
|
|
// }
|
|
|
|
|
// break
|
|
|
|
|
|
|
|
|
|
case 'optionsParams':
|
|
|
|
|
if (!content) {
|
|
|
|
|
editData = beforeRequest
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
case 'optionsResult':
|
|
|
|
|
if (!content) {
|
|
|
|
|
editData = afterResponse
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
drawer.content = editData
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
<template>
|
|
|
|
|
<div class="design-container">
|
|
|
|
|
<DragControl />
|
|
|
|
|
<div class="main-body">
|
|
|
|
|
<HeadTools @click="headToolClick" />
|
|
|
|
|
<div class="main-form" v-loading="state.loading">
|
|
|
|
|
<div class="empty-tips" v-if="state.formData.list.length === 0">
|
|
|
|
|
从左侧拖拽来添加字段
|
|
|
|
|
</div>
|
|
|
|
|
<FormDesign
|
|
|
|
|
:type="5"
|
|
|
|
|
:formData="state.formData"
|
|
|
|
|
:dict="state.formDict"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<style lang='scss' scoped>
|
|
|
|
|
|
|
|
|
|
</style>
|