12 changed files with 3442 additions and 1477 deletions
@ -0,0 +1,31 @@ |
|||
import request from '@/utils/request'; |
|||
import { AxiosPromise } from 'axios'; |
|||
import { |
|||
customerFormCont, |
|||
CustomerFormPageResult, |
|||
SearchForm, |
|||
customerFormConfig |
|||
} from './type'; |
|||
//自定义表单列表
|
|||
export function getCustomerFormList(queryParams: SearchForm): AxiosPromise<CustomerFormPageResult> { |
|||
return request({ |
|||
url: '/systemapi/customer_form/customer_form_list', |
|||
method: 'post', |
|||
params: queryParams |
|||
}); |
|||
} |
|||
//生成表单基本信息
|
|||
export function getProductionMarkForm(): AxiosPromise<customerFormConfig> { |
|||
return request({ |
|||
url: '/systemapi/customer_form/production_mark_form', |
|||
method: 'post', |
|||
}); |
|||
} |
|||
|
|||
export function saveProductionForm(data: any) { |
|||
return request({ |
|||
url: '/systemapi/customer_form/save_customer_form', |
|||
method: 'post', |
|||
data: data |
|||
}); |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
//搜索表单
|
|||
export interface SearchForm extends PageQuery{ |
|||
keywords?: string; |
|||
classify?:number; |
|||
} |
|||
//自定义表单列表内容
|
|||
export interface customerFormCont{ |
|||
id:string; |
|||
name:string; |
|||
tablename:string; |
|||
states:number; |
|||
classify:number; |
|||
creatername:string; |
|||
creatertime:string; |
|||
} |
|||
|
|||
export type CustomerFormPageResult = PageResult<customerFormCont[]>; |
|||
|
|||
//初始化表单基本信息
|
|||
export interface customerFormConfig{ |
|||
formname:string; |
|||
formlogo:string; |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,562 @@ |
|||
<!-- |
|||
@ 作者: 秦东 |
|||
@ 时间: 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 'element-plus/dist/index.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' |
|||
import FormControlAttr from '@/components/DesignForm/formControlAttr.vue'; |
|||
import VueFile from '@/components/DesignForm/vueFile.vue' |
|||
import AceDrawer from '@/components/DesignForm/aceDrawer.vue' |
|||
|
|||
import { ref, reactive, provide, onMounted } from 'vue' |
|||
import { ElMessage } from 'element-plus' |
|||
import { useLayoutStore } from '@/store/DesignForm/layout' |
|||
import { FormData,formStruct,DrawerStruct } from '@/api/DesignForm/types' |
|||
|
|||
import { saveProductionForm } from '@/api/DesignForm/requestapi' |
|||
|
|||
const isSave = ref(false) |
|||
|
|||
const props = defineProps({ |
|||
draweropenclose:{ |
|||
type:Boolean, |
|||
default:true |
|||
}, |
|||
formconfigcont:{ |
|||
type:Object, |
|||
default(){ |
|||
return {} |
|||
} |
|||
} |
|||
}); |
|||
const emits = defineEmits(["update:draweropenclose","handlequery"]); |
|||
|
|||
/** |
|||
* 弹窗显示控制 |
|||
*/ |
|||
const openShow = computed({ |
|||
get: () => props.draweropenclose, |
|||
set: (val) => { |
|||
emits("update:draweropenclose", val); |
|||
}, |
|||
}); |
|||
|
|||
const layoutStore = useLayoutStore() |
|||
layoutStore.changeBreadcrumb([{ label: '系统工具' }, { label: '表单设计' }]) |
|||
|
|||
const store = useDesignFormStore() |
|||
const router = useRouter() |
|||
const route: any = useRoute().query || {} |
|||
const state = reactive<formStruct>({ |
|||
formData: { |
|||
list: [], |
|||
form: { |
|||
size: 'default', |
|||
name:'', |
|||
formName: props.formconfigcont.formName |
|||
}, |
|||
config: {} |
|||
}, |
|||
editor: {}, |
|||
loading: false, |
|||
formDataPreview: {}, |
|||
previewVisible: false, // 预览窗口 |
|||
designType: route.type, // 当前页面设计类型,有效值search |
|||
formDict: {}, |
|||
formOtherData: { |
|||
source: route.source || '', |
|||
formName: props.formconfigcont.formName |
|||
} |
|||
}) |
|||
const drawer = reactive<DrawerStruct>({ |
|||
visible: false, |
|||
type: '', |
|||
title: '', |
|||
codeType: '', |
|||
direction: undefined, //弹出方向rtl / ltr |
|||
callback: '' |
|||
}) |
|||
const vueFileEl = ref() |
|||
const formControlAttrEl = ref() |
|||
// 当前表单设计类型,供各子组件调用以展示不同页面,统一方式不需要每个组件都从路由中取 |
|||
provide('formDesignType', state.designType) |
|||
const getInitData = () => { |
|||
const id = route.id // 当前记录保存的id |
|||
if (id) { |
|||
// 获取初始表单数据 |
|||
state.loading = true |
|||
getRequest('designById', { id: id }) |
|||
.then(res => { |
|||
const result = res.data |
|||
// 初始设计搜索时res.data='' |
|||
if (result.data) { |
|||
state.formData = stringToObj(result.data) |
|||
} |
|||
state.formDict = string2json(result.dict) |
|||
// 恢复表单名称 |
|||
state.formOtherData.source = result.source |
|||
state.formOtherData.formName = result.name |
|||
if (result.source && state.designType !== 'search') { |
|||
// 加载属性侧边栏的字段标识,搜索时不需要请求 |
|||
formControlAttrEl.value.getFormFieldBySource(result.source) |
|||
} |
|||
state.loading = false |
|||
}) |
|||
.catch((res: any) => { |
|||
// console.log(res) |
|||
ElMessage.error(res.message || '加载异常') |
|||
state.loading = false |
|||
}) |
|||
} |
|||
} |
|||
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(); |
|||
saveDataNew(); |
|||
break |
|||
case 'vue': |
|||
vueFileEl.value.open(state.formData) |
|||
emits("update:draweropenclose", false); |
|||
break |
|||
case 'close': |
|||
console.log("关闭") |
|||
if(isSave.value){ |
|||
emits("update:draweropenclose", false); |
|||
}else{ |
|||
ElMessageBox.confirm( |
|||
'表单已做设计或修改!请问是否保存?', |
|||
'温馨提示!', |
|||
{ |
|||
confirmButtonText: '保存', |
|||
cancelButtonText: '不保存', |
|||
type: 'warning', |
|||
draggable: true, |
|||
}) |
|||
.then(() => { |
|||
saveDataNew(); |
|||
}) |
|||
.catch(() => { |
|||
emits("update:draweropenclose", false); |
|||
}) |
|||
} |
|||
|
|||
break |
|||
} |
|||
} |
|||
// 弹窗确认 |
|||
const dialogConfirm = (editVal: string) => { |
|||
// 生成脚本预览和导入json,都是将编辑器内容更新至state.formData |
|||
try { |
|||
if (typeof drawer.callback === 'function') { |
|||
// callback |
|||
const newObj = |
|||
drawer.codeType === 'json' |
|||
? string2json(editVal) |
|||
: stringToObj(editVal) |
|||
drawer.callback(newObj) |
|||
} else { |
|||
switch (drawer.type) { |
|||
case 'css': |
|||
// 表单属性-编辑表单样式 |
|||
if (!state.formData.config) { |
|||
state.formData.config = {} |
|||
} |
|||
state.formData.config.style = editVal |
|||
break |
|||
case 'dict': |
|||
state.formDict = string2json(editVal) |
|||
break |
|||
case 'beforeRequest': |
|||
case 'beforeSubmit': |
|||
case 'afterResponse': |
|||
case 'afterSubmit': |
|||
case 'change': |
|||
if (!state.formData.events) { |
|||
state.formData.events = {} |
|||
} |
|||
state.formData.events[drawer.type] = stringToObj(editVal) |
|||
break |
|||
default: |
|||
state.formData = stringToObj(editVal) |
|||
} |
|||
} |
|||
dialogCancel() |
|||
} catch (res) { |
|||
// console.log(res.message) |
|||
//ElMessage.error(res.message) |
|||
} |
|||
} |
|||
//讲数据保存到服务端(新版) |
|||
const saveDataNew = () => { |
|||
isSave.value = true |
|||
let params: any = { |
|||
jsondata:JSON.stringify(state.formData), |
|||
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 |
|||
|
|||
saveProductionForm(params) |
|||
.then((res: any) => { |
|||
console.log("数据保存", res) |
|||
if(res.code == 0){ |
|||
ElMessage({ |
|||
message: res.message || '保存成功!', |
|||
type: 'success' |
|||
}) |
|||
emits("handlequery"); |
|||
emits("update:draweropenclose", false); |
|||
// 清空右侧栏信息 |
|||
store.setActiveKey('') |
|||
store.setControlAttr({}) |
|||
}else{ |
|||
ElMessage({ |
|||
message: res.msg || '保存失败!', |
|||
type: 'error' |
|||
}) |
|||
} |
|||
|
|||
}) |
|||
.finally(() => { |
|||
state.loading=false; |
|||
}) |
|||
.catch((res: any) => { |
|||
ElMessage.error(res.message || '保存异常') |
|||
state.loading = false |
|||
}) |
|||
|
|||
} |
|||
// 将数据保存在服务端 |
|||
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 = { |
|||
jsondata:JSON.stringify(state.formData), |
|||
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 |
|||
} |
|||
const drawerBeforeClose = () => { |
|||
dialogCancel() |
|||
} |
|||
const dialogCancel = () => { |
|||
drawer.visible = false |
|||
drawer.type = '' |
|||
drawer.title = '' |
|||
drawer.codeType = '' |
|||
drawer.callback = '' |
|||
drawer.content = '' |
|||
} |
|||
// 预览窗口提交测试 |
|||
const previewForm = ref() |
|||
const previewSubmit = () => { |
|||
previewForm.value.validate((valid: boolean, fields: any) => { |
|||
if (valid) { |
|||
// alert('校验通过') |
|||
ElMessage.success('校验通过') |
|||
console.log(fields) |
|||
} else { |
|||
// alert('校验不通过') |
|||
// console.log('error submit!', fields) |
|||
ElMessage.error('校验不通过') |
|||
return false |
|||
} |
|||
}) |
|||
} |
|||
// 选择模板 |
|||
const selectTemplate = (data: FormData) => { |
|||
|
|||
state.formData = stringToObj(objToStringify(data)) |
|||
} |
|||
// 搜索设计时左侧快速添加字段 |
|||
const searchCheckField = (data: FormData) => { |
|||
state.formData.list.push(data) |
|||
} |
|||
getInitData() |
|||
// 从数据源点创建表单过来时,带有参数source |
|||
onMounted(() => { |
|||
if (route.source) { |
|||
formControlAttrEl.value.getFormFieldBySource(route.source) |
|||
} |
|||
}) |
|||
onMounted(() => { |
|||
console.log("监听数据",route.type,props.formconfigcont.formname,props.formconfigcont.formlogo,state) |
|||
state.formOtherData.formName = props.formconfigcont.formname |
|||
state.formData.form.name = props.formconfigcont.formlogo |
|||
state.formData.form.formName = props.formconfigcont.formname |
|||
}) |
|||
/** |
|||
* 监听数据 |
|||
*/ |
|||
watch(() => props.draweropenclose,() => { |
|||
console.log("监听数据",props.draweropenclose,state) |
|||
if(props.draweropenclose){ |
|||
state.formOtherData.formName = props.formconfigcont.formName |
|||
state.formData.form.name = props.formconfigcont.formlogo |
|||
state.formData.form.formName = props.formconfigcont.formName |
|||
}else{ |
|||
state.formOtherData.formName = "未命名表单" |
|||
state.formData.form.name = props.formconfigcont.formlogo |
|||
state.formData.form.formName = "未命名表单" |
|||
} |
|||
|
|||
}); |
|||
|
|||
</script> |
|||
<template> |
|||
<div class="design-container"> |
|||
<DragControl |
|||
:formid="state.formOtherData.source" |
|||
@click-check="searchCheckField" |
|||
@click="selectTemplate" |
|||
/> |
|||
<div class="main-body"> |
|||
|
|||
<HeadTools @click="headToolClick" /> |
|||
<div v-loading="state.loading" class="main-form"> |
|||
<div v-if="state.formData.list.length === 0" class="empty-tips"> |
|||
从左侧拖拽来添加组件 |
|||
</div> |
|||
<FormDesign |
|||
v-model:issave="isSave" |
|||
:type="5" |
|||
:form-data="state.formData" |
|||
:dict="state.formDict" |
|||
|
|||
/> |
|||
</div> |
|||
</div> |
|||
<!--面版右侧--> |
|||
<form-control-attr |
|||
ref="formControlAttrEl" |
|||
v-model:formOtherData="state.formOtherData" |
|||
:form-data="state.formData.form" |
|||
:form-config="state.formData.config" |
|||
@open-dialog="openAceEditDrawer" |
|||
/> |
|||
<ace-drawer |
|||
v-model="drawer.visible" |
|||
:title="drawer.title" |
|||
:direction="drawer.direction" |
|||
:content="drawer.content" |
|||
:code-type="drawer.codeType" |
|||
@before-close="drawerBeforeClose" |
|||
@confirm="dialogConfirm" |
|||
/> |
|||
<vue-file v-if="!['search'].includes(state.designType)" ref="vueFileEl" /> |
|||
<el-dialog v-model="state.previewVisible" title="预览" :fullscreen="true"> |
|||
<form-design |
|||
v-if="state.previewVisible" |
|||
ref="previewForm" |
|||
:form-data="state.formDataPreview" |
|||
:dict="state.formDict" |
|||
:type="1" |
|||
/> |
|||
<template #footer> |
|||
<div class="dialog-footer"> |
|||
<el-button size="small" type="primary" @click="previewSubmit"> |
|||
提交 |
|||
</el-button> |
|||
<el-button size="small" @click="state.previewVisible = false"> |
|||
取消 |
|||
</el-button> |
|||
</div> |
|||
</template> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
<style lang='scss' scoped> |
|||
.design-container{ |
|||
padding: 0; |
|||
} |
|||
</style> |
|||
@ -1,423 +1,185 @@ |
|||
<!-- |
|||
@ 作者: 秦东 |
|||
@ 时间: 2023-05-26 10:35:30 |
|||
@ 备注: |
|||
@ 时间: 2023-08-28 14:47:07 |
|||
@ 备注: 表单设计 |
|||
--> |
|||
<script lang='ts' setup> |
|||
import '@/assets/scss/element-var.scss' |
|||
import '@/assets/scss/index.scss' |
|||
import '@/assets/iconfont/iconfont.css' |
|||
import 'element-plus/dist/index.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 { SearchForm,customerFormCont,customerFormConfig } from "@/api/DesignForm/type"; |
|||
import { getCustomerFormList,getProductionMarkForm } from '@/api/DesignForm/requestapi' |
|||
//引入页面 |
|||
import DragControl from '@/components/DesignForm/dragControl.vue'; |
|||
import HeadTools from '@/components/DesignForm/public/headTools.vue'; |
|||
import FormDesign from '@/components/DesignForm/public/form/form.vue' |
|||
import FormControlAttr from '@/components/DesignForm/formControlAttr.vue'; |
|||
import VueFile from '@/components/DesignForm/vueFile.vue' |
|||
import AceDrawer from '@/components/DesignForm/aceDrawer.vue' |
|||
|
|||
import { ref, reactive, provide, onMounted } from 'vue' |
|||
import { ElMessage } from 'element-plus' |
|||
import { useLayoutStore } from '@/store/DesignForm/layout' |
|||
import { FormData,formStruct,DrawerStruct } from '@/api/DesignForm/types' |
|||
import CreateForm from '@/views/sysworkflow/codepage/createform.vue' |
|||
|
|||
const layoutStore = useLayoutStore() |
|||
layoutStore.changeBreadcrumb([{ label: '系统工具' }, { label: '表单设计' }]) |
|||
|
|||
const store = useDesignFormStore() |
|||
const router = useRouter() |
|||
const route: any = useRoute().query || {} |
|||
const state = reactive<formStruct>({ |
|||
formData: { |
|||
list: [], |
|||
form: { |
|||
size: 'default', |
|||
name:'' |
|||
}, |
|||
config: {} |
|||
}, |
|||
editor: {}, |
|||
loading: false, |
|||
formDataPreview: {}, |
|||
previewVisible: false, // 预览窗口 |
|||
designType: route.type, // 当前页面设计类型,有效值search |
|||
formDict: {}, |
|||
formOtherData: { |
|||
source: route.source || '', |
|||
formName: '未命名表单' |
|||
} |
|||
const queryParams = reactive<SearchForm>({ |
|||
page: 1, |
|||
pagesize:15 |
|||
}); |
|||
const ids = ref<number[]>([]); //记录总数 |
|||
const loading =ref(false); //加载表单 |
|||
const drawerOpenOrClose = ref(false); |
|||
const total = ref(0); //记录总数 |
|||
const contList = ref<customerFormCont[]>() |
|||
const drawerWith = ref<number>(0); |
|||
const formConfigCont = reactive<customerFormConfig>({ |
|||
formname:"", |
|||
formlogo:"" |
|||
}) |
|||
const drawer = reactive<DrawerStruct>({ |
|||
visible: false, |
|||
type: '', |
|||
title: '', |
|||
codeType: '', |
|||
direction: undefined, //弹出方向rtl / ltr |
|||
callback: '' |
|||
}) |
|||
const vueFileEl = ref() |
|||
const formControlAttrEl = ref() |
|||
// 当前表单设计类型,供各子组件调用以展示不同页面,统一方式不需要每个组件都从路由中取 |
|||
provide('formDesignType', state.designType) |
|||
const getInitData = () => { |
|||
const id = route.id // 当前记录保存的id |
|||
if (id) { |
|||
// 获取初始表单数据 |
|||
state.loading = true |
|||
getRequest('designById', { id: id }) |
|||
.then(res => { |
|||
const result = res.data |
|||
// 初始设计搜索时res.data='' |
|||
if (result.data) { |
|||
state.formData = stringToObj(result.data) |
|||
} |
|||
state.formDict = string2json(result.dict) |
|||
// 恢复表单名称 |
|||
state.formOtherData.source = result.source |
|||
state.formOtherData.formName = result.name |
|||
if (result.source && state.designType !== 'search') { |
|||
// 加载属性侧边栏的字段标识,搜索时不需要请求 |
|||
formControlAttrEl.value.getFormFieldBySource(result.source) |
|||
} |
|||
state.loading = false |
|||
//搜索表单 |
|||
function handleQuery(){ |
|||
getCustomerFormList(queryParams) |
|||
.then(({ data }) => { |
|||
console.log("搜索表单-->",data); |
|||
total.value = data.total |
|||
contList.value = data.list |
|||
}) |
|||
.catch((res: any) => { |
|||
// console.log(res) |
|||
ElMessage.error(res.message || '加载异常') |
|||
state.loading = false |
|||
.finally(() => {}) |
|||
} |
|||
//重置搜索条件 |
|||
function resetQuery(){} |
|||
//新增表单 |
|||
function openDialog(){ |
|||
getProductionMarkForm() |
|||
.then(({data})=>{ |
|||
formConfigCont.formlogo = data.formlogo |
|||
formConfigCont.formname = data.formname |
|||
console.log("新增表单",formConfigCont) |
|||
}) |
|||
} |
|||
} |
|||
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: '可编辑修改或将已生成的脚本粘贴进来' |
|||
.finally(()=>{ |
|||
drawerOpenOrClose.value = true; |
|||
}) |
|||
break |
|||
case 'save': |
|||
saveData() |
|||
break |
|||
case 'vue': |
|||
vueFileEl.value.open(state.formData) |
|||
break |
|||
} |
|||
} |
|||
// 弹窗确认 |
|||
const dialogConfirm = (editVal: string) => { |
|||
// 生成脚本预览和导入json,都是将编辑器内容更新至state.formData |
|||
try { |
|||
if (typeof drawer.callback === 'function') { |
|||
// callback |
|||
const newObj = |
|||
drawer.codeType === 'json' |
|||
? string2json(editVal) |
|||
: stringToObj(editVal) |
|||
drawer.callback(newObj) |
|||
} else { |
|||
switch (drawer.type) { |
|||
case 'css': |
|||
// 表单属性-编辑表单样式 |
|||
if (!state.formData.config) { |
|||
state.formData.config = {} |
|||
} |
|||
state.formData.config.style = editVal |
|||
break |
|||
case 'dict': |
|||
state.formDict = string2json(editVal) |
|||
break |
|||
case 'beforeRequest': |
|||
case 'beforeSubmit': |
|||
case 'afterResponse': |
|||
case 'afterSubmit': |
|||
case 'change': |
|||
if (!state.formData.events) { |
|||
state.formData.events = {} |
|||
} |
|||
state.formData.events[drawer.type] = stringToObj(editVal) |
|||
break |
|||
default: |
|||
state.formData = stringToObj(editVal) |
|||
} |
|||
} |
|||
dialogCancel() |
|||
} catch (res) { |
|||
// console.log(res.message) |
|||
//ElMessage.error(res.message) |
|||
} |
|||
} |
|||
// 将数据保存在服务端 |
|||
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 |
|||
} |
|||
const drawerBeforeClose = () => { |
|||
dialogCancel() |
|||
} |
|||
const dialogCancel = () => { |
|||
drawer.visible = false |
|||
drawer.type = '' |
|||
drawer.title = '' |
|||
drawer.codeType = '' |
|||
drawer.callback = '' |
|||
drawer.content = '' |
|||
} |
|||
// 预览窗口提交测试 |
|||
const previewForm = ref() |
|||
const previewSubmit = () => { |
|||
previewForm.value.validate((valid: boolean, fields: any) => { |
|||
if (valid) { |
|||
// alert('校验通过') |
|||
ElMessage.success('校验通过') |
|||
console.log(fields) |
|||
} else { |
|||
// alert('校验不通过') |
|||
// console.log('error submit!', fields) |
|||
ElMessage.error('校验不通过') |
|||
return false |
|||
} |
|||
}) |
|||
} |
|||
// 选择模板 |
|||
const selectTemplate = (data: FormData) => { |
|||
} |
|||
//删除表单 |
|||
function handleDelete(){} |
|||
/** |
|||
* 行checkbox change事件 |
|||
*/ |
|||
function handleSelectionChange(selection: any) { |
|||
ids.value = selection.map((item: any) => item.id); |
|||
} |
|||
//设置自定义表单 |
|||
function setupCustomerForm(cont:customerFormCont){ |
|||
|
|||
} |
|||
onMounted(()=>{ |
|||
handleQuery(); |
|||
drawerWith.value = window.innerWidth - 220 |
|||
}); |
|||
window.addEventListener("resize", function(){ |
|||
drawerWith.value = window.innerWidth -220 |
|||
console.log("搜索表单-->",window.innerWidth); |
|||
}) |
|||
//监听屏幕宽度变化 |
|||
|
|||
state.formData = stringToObj(objToStringify(data)) |
|||
} |
|||
// 搜索设计时左侧快速添加字段 |
|||
const searchCheckField = (data: FormData) => { |
|||
state.formData.list.push(data) |
|||
} |
|||
getInitData() |
|||
// 从数据源点创建表单过来时,带有参数source |
|||
onMounted(() => { |
|||
if (route.source) { |
|||
formControlAttrEl.value.getFormFieldBySource(route.source) |
|||
} |
|||
}) |
|||
</script> |
|||
<template> |
|||
<div class="design-container"> |
|||
<DragControl |
|||
:formid="state.formOtherData.source" |
|||
@click-check="searchCheckField" |
|||
@click="selectTemplate" |
|||
/> |
|||
<div class="main-body"> |
|||
|
|||
<HeadTools @click="headToolClick" /> |
|||
<div v-loading="state.loading" class="main-form"> |
|||
<div v-if="state.formData.list.length === 0" class="empty-tips"> |
|||
从左侧拖拽来添加组件 |
|||
</div> |
|||
<FormDesign |
|||
:type="5" |
|||
:form-data="state.formData" |
|||
:dict="state.formDict" |
|||
<div class="app-container"> |
|||
<div class="search"> |
|||
<el-form ref="queryFormRef" :model="queryParams" :inline="true"> |
|||
<el-form-item label="关键字" prop="keywords"> |
|||
<el-input |
|||
v-model="queryParams.keywords" |
|||
placeholder="表单名称" |
|||
clearable |
|||
@keyup.enter="handleQuery" |
|||
/> |
|||
</el-form-item> |
|||
<el-form-item> |
|||
<el-button type="primary" @click="handleQuery" |
|||
><template #icon><i-ep-search /></template>搜索</el-button |
|||
> |
|||
<el-button @click="resetQuery"> |
|||
<template #icon><i-ep-refresh /></template> |
|||
重置</el-button |
|||
> |
|||
</el-form-item> |
|||
</el-form> |
|||
</div> |
|||
</div> |
|||
<!--面版右侧--> |
|||
<form-control-attr |
|||
ref="formControlAttrEl" |
|||
v-model:formOtherData="state.formOtherData" |
|||
:form-data="state.formData.form" |
|||
:form-config="state.formData.config" |
|||
@open-dialog="openAceEditDrawer" |
|||
/> |
|||
<ace-drawer |
|||
v-model="drawer.visible" |
|||
:title="drawer.title" |
|||
:direction="drawer.direction" |
|||
:content="drawer.content" |
|||
:code-type="drawer.codeType" |
|||
@before-close="drawerBeforeClose" |
|||
@confirm="dialogConfirm" |
|||
/> |
|||
<vue-file v-if="!['search'].includes(state.designType)" ref="vueFileEl" /> |
|||
<el-dialog v-model="state.previewVisible" title="预览" :fullscreen="true"> |
|||
<form-design |
|||
v-if="state.previewVisible" |
|||
ref="previewForm" |
|||
:form-data="state.formDataPreview" |
|||
:dict="state.formDict" |
|||
:type="1" |
|||
/> |
|||
<template #footer> |
|||
<div class="dialog-footer"> |
|||
<el-button size="small" type="primary" @click="previewSubmit"> |
|||
提交 |
|||
<el-card shadow="never"> |
|||
<template #header> |
|||
<el-button type="success" @click="openDialog()"><i-ep-plus />新增表单</el-button> |
|||
<el-button |
|||
type="danger" |
|||
:disabled="ids.length === 0" |
|||
@click="handleDelete()" |
|||
> |
|||
<i-ep-delete />删除表单 |
|||
</el-button> |
|||
<el-button size="small" @click="state.previewVisible = false"> |
|||
取消 |
|||
</el-button> |
|||
</div> |
|||
</template> |
|||
</el-dialog> |
|||
<el-table |
|||
v-loading="loading" |
|||
highlight-current-row |
|||
:data="contList" |
|||
border |
|||
@selection-change="handleSelectionChange" |
|||
> |
|||
<el-table-column fixed type="selection" width="55" align="center" /> |
|||
<el-table-column fixed label="表单名称" prop="name" /> |
|||
<el-table-column label="分类" align="center" width="150"> |
|||
<template #default="scope"> |
|||
<el-tag v-if="scope.row.classify === 1" effect="plain">表单</el-tag> |
|||
<el-tag v-else effect="plain">流程表单</el-tag> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="状态" align="center" width="100"> |
|||
<template #default="scope"> |
|||
<el-tag v-if="scope.row.states === 1" type="success">启用</el-tag> |
|||
<el-tag v-else type="info">禁用</el-tag> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="创建人" prop="creatername" width="140" /> |
|||
<el-table-column label="创建时间" prop="creatertime" /> |
|||
<el-table-column fixed="right" label="操作" align="center" width="280"> |
|||
<template #default="scope"> |
|||
<el-button |
|||
type="success" |
|||
link |
|||
size="small" |
|||
@click.stop="setupCustomerForm(scope.row)" |
|||
><i-ep-Setting />设置</el-button |
|||
> |
|||
<el-button |
|||
type="warning" |
|||
link |
|||
size="small" |
|||
@click.stop="setupCustomerForm(scope.row)" |
|||
><i-ep-MessageBox />数据结构</el-button |
|||
> |
|||
<el-button |
|||
|
|||
type="primary" |
|||
link |
|||
size="small" |
|||
|
|||
><i-ep-edit />编辑</el-button |
|||
> |
|||
<el-button |
|||
|
|||
type="danger" |
|||
link |
|||
size="small" |
|||
|
|||
><i-ep-delete />删除</el-button |
|||
> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
<pagination |
|||
v-if="total > 0" |
|||
v-model:total="total" |
|||
v-model:page="queryParams.page" |
|||
v-model:limit="queryParams.pagesize" |
|||
@pagination="handleQuery" |
|||
/> |
|||
</el-card> |
|||
</div> |
|||
<el-drawer v-model="drawerOpenOrClose" title="I am the title" :with-header="false" :close-on-click-modal="false" :close-on-press-escape="false" :destroy-on-close="true" :size="drawerWith" class="drawerClass"> |
|||
<CreateForm v-model:draweropenclose="drawerOpenOrClose" :formconfigcont="formConfigCont" @handlequery="handleQuery" /> |
|||
</el-drawer> |
|||
</template> |
|||
<style lang='scss' scoped> |
|||
|
|||
.drawerClass{ |
|||
.el-drawer__body{ |
|||
padding: 0; |
|||
} |
|||
} |
|||
</style> |
|||
|
|||
Loading…
Reference in new issue