Vue3 重构:重构工作流的表单

This commit is contained in:
YunaiV 2023-03-23 22:50:48 +08:00
parent 6f8499c4d0
commit abbaeabc3a
7 changed files with 262 additions and 276 deletions

View File

@ -11,7 +11,7 @@ export type FormVO = {
} }
// 创建工作流的表单定义 // 创建工作流的表单定义
export const createFormApi = async (data: FormVO) => { export const createForm = async (data: FormVO) => {
return await request.post({ return await request.post({
url: '/bpm/form/create', url: '/bpm/form/create',
data: data data: data
@ -19,7 +19,7 @@ export const createFormApi = async (data: FormVO) => {
} }
// 更新工作流的表单定义 // 更新工作流的表单定义
export const updateFormApi = async (data: FormVO) => { export const updateForm = async (data: FormVO) => {
return await request.put({ return await request.put({
url: '/bpm/form/update', url: '/bpm/form/update',
data: data data: data
@ -27,21 +27,21 @@ export const updateFormApi = async (data: FormVO) => {
} }
// 删除工作流的表单定义 // 删除工作流的表单定义
export const deleteFormApi = async (id: number) => { export const deleteForm = async (id: number) => {
return await request.delete({ return await request.delete({
url: '/bpm/form/delete?id=' + id url: '/bpm/form/delete?id=' + id
}) })
} }
// 获得工作流的表单定义 // 获得工作流的表单定义
export const getFormApi = async (id: number) => { export const getForm = async (id: number) => {
return await request.get({ return await request.get({
url: '/bpm/form/get?id=' + id url: '/bpm/form/get?id=' + id
}) })
} }
// 获得工作流的表单定义分页 // 获得工作流的表单定义分页
export const getFormPageApi = async (params) => { export const getFormPage = async (params) => {
return await request.get({ return await request.get({
url: '/bpm/form/page', url: '/bpm/form/page',
params params
@ -49,7 +49,7 @@ export const getFormPageApi = async (params) => {
} }
// 获得动态表单的精简列表 // 获得动态表单的精简列表
export const getSimpleFormsApi = async () => { export const getSimpleFormList = async () => {
return await request.get({ return await request.get({
url: '/bpm/form/list-all-simple' url: '/bpm/form/list-all-simple'
}) })

View File

@ -225,14 +225,14 @@ const remainingRouter: AppRouteRecordRaw[] = [
children: [ children: [
{ {
path: '/manager/form/edit', path: '/manager/form/edit',
component: () => import('@/views/bpm/form/formEditor.vue'), component: () => import('@/views/bpm/form/FormEditor.vue'),
name: 'bpmFormEditor', name: 'bpmFormEditor',
meta: { meta: {
noCache: true, noCache: true,
hidden: true, hidden: true,
canTo: true, canTo: true,
title: '设计流程表单', title: '设计流程表单',
activeMenu: 'bpm/manager/form/formEditor' activeMenu: '/bpm/manager/form'
} }
}, },
{ {

View File

@ -0,0 +1,108 @@
<template>
<ContentWrap>
<!-- 表单设计器 -->
<fc-designer ref="designer" height="780px">
<template #handle>
<el-button round size="small" type="primary" @click="handleSave">
<Icon icon="ep:plus" class="mr-5px" /> 保存
</el-button>
</template>
</fc-designer>
</ContentWrap>
<!-- 表单保存的弹窗 -->
<Dialog title="保存表单" v-model="modelVisible" width="600">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
<el-form-item label="表单名" prop="name">
<el-input v-model="formData.name" placeholder="请输入表单名" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="modelVisible = false"> </el-button>
</div>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants'
import * as FormApi from '@/api/bpm/form'
import { encodeConf, encodeFields, setConfAndFields } from '@/utils/formCreate'
const { t } = useI18n() //
const message = useMessage() //
const { query } = useRoute() //
const designer = ref() //
const modelVisible = ref(false) //
const formLoading = ref(false) //
const formData = ref({
name: '',
status: CommonStatusEnum.ENABLE,
remark: ''
})
const formRules = reactive({
name: [{ required: true, message: '表单名不能为空', trigger: 'blur' }],
status: [{ required: true, message: '开启状态不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 处理保存按钮 */
const handleSave = () => {
modelVisible.value = true
}
/** 提交表单 */
const submitForm = async () => {
//
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
//
formLoading.value = true
try {
const data = formData.value as FormApi.FormVO
data.conf = encodeConf(designer) //
data.fields = encodeFields(designer) //
if (!data.id) {
await FormApi.createForm(data)
message.success(t('common.createSuccess'))
} else {
await FormApi.updateForm(data)
message.success(t('common.updateSuccess'))
}
modelVisible.value = false
} finally {
formLoading.value = false
}
}
/** 初始化 **/
onMounted(async () => {
//
const id = query.id as unknown as number
if (!id) {
return
}
//
const data = await FormApi.getForm(id)
formData.value = data
setConfAndFields(designer, data.conf, data.fields)
})
</script>

View File

@ -1,43 +0,0 @@
import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
const { t } = useI18n() // 国际化
// 表单校验
export const rules = reactive({
name: [required]
})
// CrudSchema
const crudSchemas = reactive<VxeCrudSchema>({
primaryKey: 'id',
primaryType: 'id',
primaryTitle: '表单编号',
action: true,
columns: [
{
title: '表单名',
field: 'name',
isSearch: true
},
{
title: t('common.status'),
field: 'status',
dictType: DICT_TYPE.COMMON_STATUS,
dictClass: 'number'
},
{
title: '备注',
field: 'remark'
},
{
title: t('common.createTime'),
field: 'createTime',
formatter: 'formatDate',
isForm: false,
table: {
width: 180
}
}
]
})
export const { allSchemas } = useVxeCrudSchemas(crudSchemas)

View File

@ -1,157 +0,0 @@
<template>
<ContentWrap>
<!-- 表单设计器 -->
<fc-designer ref="designer" height="780px">
<template #handle>
<XButton type="primary" title="生成JSON" @click="showJson" />
<XButton type="primary" title="生成Options" @click="showOption" />
<XButton type="primary" :title="t('action.save')" @click="handleSave" />
</template>
</fc-designer>
<Dialog :title="dialogTitle" v-model="dialogVisible1" maxHeight="600">
<div ref="editor" v-if="dialogVisible1">
<XTextButton style="float: right" :title="t('common.copy')" @click="copy(formValue)" />
<el-scrollbar height="580">
<pre>
{{ formValue }}
</pre>
</el-scrollbar>
</div>
</Dialog>
<!-- 表单保存的弹窗 -->
<XModal v-model="dialogVisible" title="保存表单">
<el-form ref="formRef" :model="formValues" :rules="formRules" label-width="80px">
<el-form-item label="表单名" prop="name">
<el-input v-model="formValues.name" placeholder="请输入表单名" />
</el-form-item>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formValues.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formValues.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-form>
<!-- 操作按钮 -->
<template #footer>
<!-- 按钮保存 -->
<XButton
type="primary"
:title="t('action.save')"
:loading="dialogLoading"
@click="submitForm"
/>
<!-- 按钮关闭 -->
<XButton :title="t('dialog.close')" @click="dialogVisible = false" />
</template>
</XModal>
</ContentWrap>
</template>
<script setup lang="ts" name="BpmFormEditor">
import { FormInstance } from 'element-plus'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants'
import * as FormApi from '@/api/bpm/form'
import { encodeConf, encodeFields, setConfAndFields } from '@/utils/formCreate'
import { useClipboard } from '@vueuse/core'
const { t } = useI18n() //
const message = useMessage() //
const { query } = useRoute() //
const designer = ref() //
const type = ref(-1)
const formValue = ref('')
const dialogTitle = ref('')
const dialogVisible = ref(false) //
const dialogVisible1 = ref(false) //
const dialogLoading = ref(false) //
const formRef = ref<FormInstance>()
const formRules = reactive({
name: [{ required: true, message: '表单名不能为空', trigger: 'blur' }],
status: [{ required: true, message: '开启状态不能为空', trigger: 'blur' }]
})
const formValues = ref({
name: '',
status: CommonStatusEnum.ENABLE,
remark: ''
})
//
const handleSave = () => {
dialogVisible.value = true
}
//
const submitForm = async () => {
//
const elForm = unref(formRef)
if (!elForm) return
const valid = await elForm.validate()
if (!valid) return
//
dialogLoading.value = true
try {
const data = formValues.value as FormApi.FormVO
data.conf = encodeConf(designer) //
data.fields = encodeFields(designer) //
if (!data.id) {
await FormApi.createFormApi(data)
message.success(t('common.createSuccess'))
} else {
await FormApi.updateFormApi(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
} finally {
dialogLoading.value = false
}
}
const showJson = () => {
openModel('生成JSON')
type.value = 0
formValue.value = designer.value.getRule()
}
const showOption = () => {
openModel('生成Options')
type.value = 1
formValue.value = designer.value.getOption()
}
const openModel = (title: string) => {
dialogVisible1.value = true
dialogTitle.value = title
}
/** 复制 **/
const copy = async (text: string) => {
const { copy, copied, isSupported } = useClipboard({ source: text })
if (!isSupported) {
message.error(t('common.copyError'))
} else {
await copy()
if (unref(copied)) {
message.success(t('common.copySuccess'))
}
}
}
// ========== ==========
onMounted(() => {
//
const id = query.id as unknown as number
if (!id) {
return
}
//
FormApi.getFormApi(id).then((data) => {
formValues.value = data
setConfAndFields(designer, data.conf, data.fields)
})
})
</script>

View File

@ -1,93 +1,171 @@
<template> <template>
<ContentWrap> <content-wrap>
<!-- 列表 --> <!-- 搜索工作栏 -->
<XTable @register="registerTable"> <el-form
<!-- 操作新增 --> class="-mb-15px"
<template #toolbar_buttons> :model="queryParams"
<XButton ref="queryFormRef"
type="primary" :inline="true"
preIcon="ep:zoom-in" label-width="68px"
:title="t('action.add')" >
v-hasPermi="['system:post:create']" <el-form-item label="表单名" prop="name">
@click="handleCreate()" <el-input
v-model="queryParams.name"
placeholder="请输入表单名"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/> />
</template> </el-form-item>
<template #actionbtns_default="{ row }"> <el-form-item>
<!-- 操作修改 --> <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<XTextButton <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
preIcon="ep:edit" <el-button type="primary" @click="openForm()" v-hasPermi="['bpm:form:create']">
:title="t('action.edit')" <Icon icon="ep:plus" class="mr-5px" /> 新增
v-hasPermi="['bpm:form:update']" </el-button>
@click="handleUpdate(row.id)" </el-form-item>
/> </el-form>
<!-- 操作详情 --> </content-wrap>
<XTextButton
preIcon="ep:view" <!-- 列表 -->
:title="t('action.detail')" <content-wrap>
v-hasPermi="['bpm:form:query']" <el-table v-loading="loading" :data="list">
@click="handleDetail(row.id)" <el-table-column label="编号" align="center" prop="id" />
/> <el-table-column label="表单名" align="center" prop="name" />
<!-- 操作删除 --> <el-table-column label="状态" align="center" prop="status">
<XTextButton <template #default="scope">
preIcon="ep:delete" <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
:title="t('action.del')" </template>
v-hasPermi="['bpm:form:delete']" </el-table-column>
@click="deleteData(row.id)" <el-table-column label="备注" align="center" prop="remark" />
/> <el-table-column
</template> label="创建时间"
</XTable> align="center"
<!-- 表单详情的弹窗 --> prop="createTime"
<XModal v-model="detailOpen" width="800" title="表单详情"> :formatter="dateFormatter"
<form-create :rule="detailPreview.rule" :option="detailPreview.option" v-if="detailOpen" /> />
</XModal> <el-table-column label="操作" align="center">
</ContentWrap> <template #default="scope">
<el-button
link
type="primary"
@click="openForm(scope.row.id)"
v-hasPermi="['bpm:form:update']"
>
编辑
</el-button>
<el-button link @click="openDetail(scope.row.id)" v-hasPermi="['bpm:form:query']">
详情
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['bpm:form:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</content-wrap>
<!-- 表单详情的弹窗 -->
<Dialog title="表单详情" v-model="detailVisible" width="800">
<form-create :rule="detailData.rule" :option="detailData.option" />
</Dialog>
</template> </template>
<script setup lang="ts" name="BpmForm"> <script setup lang="ts" name="Form">
// import import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import * as FormApi from '@/api/bpm/form' import * as FormApi from '@/api/bpm/form'
import { allSchemas } from './form.data'
// import
import { setConfAndFields2 } from '@/utils/formCreate' import { setConfAndFields2 } from '@/utils/formCreate'
const message = useMessage() //
const { t } = useI18n() // const { t } = useI18n() //
const { push } = useRouter() // const { push } = useRouter() //
// const loading = ref(true) //
const [registerTable, { deleteData }] = useXTable({ const total = ref(0) //
allSchemas: allSchemas, const list = ref([]) //
getListApi: FormApi.getFormPageApi, const queryParams = reactive({
deleteApi: FormApi.deleteFormApi pageNo: 1,
pageSize: 10,
name: null
}) })
const queryFormRef = ref() //
// /** 查询参数列表 */
const handleCreate = () => { const getList = async () => {
push({ loading.value = true
name: 'bpmFormEditor' try {
}) const data = await FormApi.getFormPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
} }
// /** 搜索按钮操作 */
const handleUpdate = async (rowId: number) => { const handleQuery = () => {
await push({ queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const openForm = (id?: number) => {
push({
name: 'bpmFormEditor', name: 'bpmFormEditor',
query: { query: {
id: rowId id
} }
}) })
} }
// /** 删除按钮操作 */
const detailOpen = ref(false) const handleDelete = async (id: number) => {
const detailPreview = ref({ try {
//
await message.delConfirm()
//
await FormApi.deleteForm(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 详情操作 */
const detailVisible = ref(false)
const detailData = ref({
rule: [], rule: [],
option: {} option: {}
}) })
const handleDetail = async (rowId: number) => { const openDetail = async (rowId: number) => {
// //
const data = await FormApi.getFormApi(rowId) const data = await FormApi.getForm(rowId)
setConfAndFields2(detailPreview, data.conf, data.fields) setConfAndFields2(detailData, data.conf, data.fields)
// //
detailOpen.value = true detailVisible.value = true
} }
/** 初始化 **/
onMounted(() => {
getList()
})
</script> </script>

View File

@ -374,7 +374,7 @@ const formDetailPreview = ref({
const handleFormDetail = async (row) => { const handleFormDetail = async (row) => {
if (row.formType == 10) { if (row.formType == 10) {
// //
const data = await FormApi.getFormApi(row.formId) const data = await FormApi.getForm(row.formId)
setConfAndFields2(formDetailPreview, data.conf, data.fields) setConfAndFields2(formDetailPreview, data.conf, data.fields)
// //
formDetailVisible.value = true formDetailVisible.value = true
@ -588,7 +588,7 @@ const uploadClose = () => {
// ========== ========== // ========== ==========
onMounted(() => { onMounted(() => {
// //
FormApi.getSimpleFormsApi().then((data) => { FormApi.getSimpleFormList().then((data) => {
forms.value = data forms.value = data
}) })
}) })