Pre Merge pull request !205 from 愿丶/dev-df

This commit is contained in:
愿丶 2025-05-16 13:00:55 +00:00 committed by Gitee
commit b7f712a969
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
11 changed files with 1260 additions and 1 deletions

View File

@ -30,6 +30,7 @@
"crypto-js": "4.2.0", "crypto-js": "4.2.0",
"echarts": "5.6.0", "echarts": "5.6.0",
"element-plus": "2.9.8", "element-plus": "2.9.8",
"epic-designer": "^1.0.1",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"highlight.js": "11.9.0", "highlight.js": "11.9.0",
"image-conversion": "2.1.1", "image-conversion": "2.1.1",

View File

@ -0,0 +1,91 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { FormDefinitionVO, FormDefinitionForm, FormDefinitionQuery } from '@/api/workflow/formDefinition/types';
/**
*
* @param query
* @returns {*}
*/
export const listFormDefinition = (query?: FormDefinitionQuery): AxiosPromise<FormDefinitionVO[]> => {
return request({
url: '/workflow/formDefinition/list',
method: 'get',
params: query
});
};
/**
*
* @param id
*/
export const getFormDefinition = (id: string | number): AxiosPromise<FormDefinitionVO> => {
return request({
url: '/workflow/formDefinition/' + id,
method: 'get'
});
};
/**
*
* @param data
*/
export const addFormDefinition = (data: FormDefinitionForm) => {
return request({
url: '/workflow/formDefinition',
method: 'post',
data: data
});
};
/**
*
* @param data
*/
export const updateFormDefinition = (data: FormDefinitionForm) => {
return request({
url: '/workflow/formDefinition',
method: 'put',
data: data
});
};
/**
*
* @param data
*/
export const updateFormSchema = (data: FormDefinitionForm) => {
return request({
url: '/workflow/formDefinition/editFormSchema',
method: 'put',
data: data
});
};
/**
*
* @param id
*/
export const delFormDefinition = (id: string | number | Array<string | number>) => {
return request({
url: '/workflow/formDefinition/' + id,
method: 'delete'
});
};
/**
*
* @param data
*/
export const updateFormDefinitionStatus = (id: string | number, status: string) => {
const data = {
id,
status
};
return request({
url: '/workflow/formDefinition/changeStatus',
method: 'post',
data: data
});
};

View File

@ -0,0 +1,101 @@
export interface FormDefinitionVO {
/**
*
*/
id: string | number;
/**
*
*/
formKey: string;
/**
*
*/
formName: string;
/**
*
*/
version: number;
/**
*
*/
formSchema: string;
/**
*
*/
status: string;
/**
*
*/
remark: string;
}
export interface FormDefinitionForm extends BaseEntity {
/**
*
*/
id?: string | number;
/**
*
*/
formKey?: string;
/**
*
*/
formName?: string;
/**
*
*/
version?: number;
/**
*
*/
formSchema?: string;
/**
*
*/
status?: string;
/**
*
*/
remark?: string;
}
export interface FormDefinitionQuery extends PageQuery {
/**
*
*/
formKey?: string;
/**
*
*/
formName?: string;
/**
*
*/
status?: string;
/**
*
*/
params?: any;
}

View File

@ -0,0 +1,63 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { FormInstanceVO, FormInstanceForm, FormInstanceQuery } from '@/api/workflow/formInstance/types';
/**
*
* @param query
* @returns {*}
*/
export const listFormInstance = (query?: FormInstanceQuery): AxiosPromise<FormInstanceVO[]> => {
return request({
url: '/workflow/formInstance/list',
method: 'get',
params: query
});
};
/**
*
* @param id
*/
export const getFormInstance = (id: string | number): AxiosPromise<FormInstanceVO> => {
return request({
url: '/workflow/formInstance/' + id,
method: 'get'
});
};
/**
*
* @param data
*/
export const addFormInstance = (data: FormInstanceForm) => {
return request({
url: '/workflow/formInstance',
method: 'post',
data: data
});
};
/**
*
* @param data
*/
export const updateFormInstance = (data: FormInstanceForm) => {
return request({
url: '/workflow/formInstance',
method: 'put',
data: data
});
};
/**
*
* @param id
*/
export const delFormInstance = (id: string | number | Array<string | number>) => {
return request({
url: '/workflow/formInstance/' + id,
method: 'delete'
});
};

View File

@ -0,0 +1,90 @@
export interface FormInstanceVO {
/**
*
*/
id: string | number;
/**
* ID
*/
definitionId: string | number;
/**
*
*/
formKey: string;
/**
*
*/
formSchema: string;
/**
*
*/
formData: string;
/**
*
*/
status: string;
/**
*
*/
remark: string;
}
export interface FormInstanceForm extends BaseEntity {
/**
*
*/
id?: string | number;
/**
* ID
*/
definitionId?: string | number;
/**
*
*/
formKey?: string;
/**
*
*/
formSchema?: string;
/**
*
*/
formData?: string;
/**
*
*/
status?: string;
/**
*
*/
remark?: string;
}
export interface FormInstanceQuery extends PageQuery {
/**
* ID
*/
definitionId?: string | number;
/**
*
*/
status?: string;
/**
*
*/
params?: any;
}

View File

@ -38,6 +38,12 @@ VXETable.setConfig({
zIndex: 999999 zIndex: 999999
}); });
// epic designer
import 'epic-designer/dist/style.css';
import { setupElementPlus } from 'epic-designer/dist/ui/elementPlus';
// 注册Element UI
setupElementPlus();
// 修改 el-dialog 默认点击遮照为不关闭 // 修改 el-dialog 默认点击遮照为不关闭
import { ElDialog } from 'element-plus'; import { ElDialog } from 'element-plus';
ElDialog.props.closeOnClickModal.default = false; ElDialog.props.closeOnClickModal.default = false;

View File

@ -190,7 +190,36 @@ export const dynamicRoutes: RouteRecordRaw[] = [
meta: { title: '流程设计', activeMenu: '/workflow/processDefinition', noCache: true } meta: { title: '流程设计', activeMenu: '/workflow/processDefinition', noCache: true }
} }
] ]
} },
// 电子表单设计路由
{
path: '/workflow/formDesign',
component: Layout,
hidden: true,
permissions: ['workflow:formDefinition:edit'],
children: [
{
path: 'index',
component: () => import('@/views/workflow/formDefinition/design.vue'),
name: 'formDesign',
meta: { title: '表单设计', activeMenu: '/workflow/formDefinition', noCache: true }
}
]
},
{
path: '/workflow/dynFormEdit',
component: Layout,
hidden: true,
permissions: ['workflow:formInstance:edit'],
children: [
{
path: 'index/:definitionId(\\d+)',
component: () => import('@/views/workflow/formInstance/edit.vue'),
name: 'dynFormEdit',
meta: { title: '表单实例', activeMenu: '/workflow/formInstance', noCache: true }
}
]
},
]; ];
/** /**

View File

@ -0,0 +1,86 @@
<script setup lang="ts">
import { EDesigner, type PageSchema } from 'epic-designer';
import { getFormDefinition, updateFormSchema } from '@/api/workflow/formDefinition';
import { FormDefinitionForm } from '@/api/workflow/formDefinition/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
type DefinitionRouteVo = {
definitionId: string;
};
const loading = ref(false);
const routeParams = ref<DefinitionRouteVo>({
definitionId: ''
});
const formData = ref<FormDefinitionForm>({});
/** 表单设计器实例 */
const eDesignerRef = useTemplateRef<typeof EDesigner>('eDesignerRef');
/** 加载数据 */
const loadData = async () => {
loading.value = true;
const res = await getFormDefinition(routeParams.value.definitionId);
Object.assign(formData.value, res.data);
if (res.data && res.data.formSchema) {
//
const schema = JSON.parse(res.data.formSchema);
const flag = eDesignerRef.value?.setData(schema);
if (flag) {
proxy?.$modal.msgError('表单设计器数据解析失败');
}
}
};
/** 保存事件 */
const handleSubmit = async (e: PageSchema) => {
// json
formData.value.formSchema = JSON.stringify(e);
await updateFormSchema(formData.value);
proxy?.$modal.msgSuccess('保存成功');
proxy.$tab.closePage(proxy.$route);
proxy.$router.go(-1);
};
/** 下一步 */
const handleNextSubmit = () => {};
/** 返回 */
const handleBack = () => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.go(-1);
};
/** 清除事件, 如果有默认的schema则不会 */
const handleReset = () => {
eDesignerRef.value?.reset();
};
onMounted(() => {
routeParams.value = proxy.$route.query;
loadData();
});
</script>
<template>
<div class="epic-designer-container">
<e-designer v-loading="loading" ref="eDesignerRef" :form-mode="true" @save="handleSubmit" @reset="handleReset">
<!-- 通过该插槽修改logo -->
<!-- <template #header-prefix></template>-->
<template #header-title> {{ formData.formName }} - 表单设计器 </template>
<!-- <template #header-right-prefix></template>-->
<template #header-right-suffix>
<el-button icon="Back" size="small" class="ml-2" @click="handleBack">
返回
</el-button>
</template>
</e-designer>
</div>
</template>
<style scoped lang="scss">
.epic-designer-container {
width: 100%;
height: 800px;
}
</style>

View File

@ -0,0 +1,315 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="表单标识" prop="formKey">
<el-input v-model="queryParams.formKey" placeholder="请输入表单标识" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="表单名称" prop="formName">
<el-input v-model="queryParams.formName" placeholder="请输入表单名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option v-for="dict in wf_form_definition_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['workflow:formDefinition:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['workflow:formDefinition:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['workflow:formDefinition:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="formDefinitionList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="编号" align="center" prop="id">
<template #header>
<span>
<el-tooltip content="编号需要复制到流程定义的路由地址上" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
编号
</span>
</template>
</el-table-column>
<el-table-column label="表单名称" align="center" prop="formName" />
<el-table-column label="表单标识" align="center" prop="formKey">
<template #header>
<span>
<el-tooltip content="点击标识列自动复制表单标识" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
表单标识
</span>
</template>
<template #default="{ row }">
<span :key="row.id" v-copyText="row.formKey" v-copyText:callback="() => proxy.$modal.msgSuccess('复制成功!')" class="pointer">{{
row.formKey
}}</span>
</template>
</el-table-column>
<el-table-column label="版本号" align="center" prop="version">
<template #default="{ row }"> v{{ row.version }}.0 </template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="wf_form_definition_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="220px">
<template #default="scope">
<el-tooltip content="表单设计" placement="top">
<el-button link type="primary" icon="Pointer" @click="handleDesign(scope.row)" v-hasPermi="['workflow:formDefinition:edit']"
>表单设计</el-button
>
</el-tooltip>
<el-tooltip content="发布表单" placement="top">
<el-button link type="primary" icon="Edit" @click="handleChangeStatus(scope.row, '1')" v-hasPermi="['workflow:formDefinition:edit']"
>发布表单</el-button
>
</el-tooltip>
<el-tooltip content="停用表单" placement="top">
<el-button link type="primary" icon="Edit" @click="handleChangeStatus(scope.row, '2')" v-hasPermi="['workflow:formDefinition:edit']"
>停用表单</el-button
>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['workflow:formDefinition:remove']"
>删除表单</el-button
>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改表单定义对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="formDefinitionFormRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="表单名称" prop="formName">
<el-input v-model="form.formName" placeholder="请输入表单名称" maxlength="50" show-word-limit />
</el-form-item>
<el-form-item label="表单标识" prop="formKey">
<template #label>
<span>
<el-tooltip content="要求与流程定义KEY保持一致标识前缀默认为dyn_form_由系统自动补充" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
表单标识
</span>
</template>
<el-input v-model="form.formKey" placeholder="请输入表单标识" maxlength="50" show-word-limit>
<template #prefix>dyn_form_</template>
</el-input>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" maxlength="500" show-word-limit />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="FormDefinition" lang="ts">
import {
listFormDefinition,
getFormDefinition,
delFormDefinition,
addFormDefinition,
updateFormDefinition,
updateFormDefinitionStatus
} from '@/api/workflow/formDefinition';
import { FormDefinitionVO, FormDefinitionQuery, FormDefinitionForm } from '@/api/workflow/formDefinition/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { wf_form_definition_status } = toRefs<any>(proxy?.useDict('wf_form_definition_status'));
const formDefinitionList = ref<FormDefinitionVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const formDefinitionFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const fromKeyPrefix = 'dyn_form_';
const initFormData: FormDefinitionForm = {
id: undefined,
formKey: undefined,
formName: undefined,
version: undefined,
formSchema: undefined,
status: '0',
remark: undefined
};
const data = reactive<PageData<FormDefinitionForm, FormDefinitionQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
formKey: undefined,
formName: undefined,
status: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键不能为空', trigger: 'blur' }],
formKey: [{ required: true, message: '表单标识不能为空', trigger: 'blur' }],
formName: [{ required: true, message: '表单名称不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询表单定义列表 */
const getList = async () => {
loading.value = true;
const res = await listFormDefinition(queryParams.value);
formDefinitionList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
formDefinitionFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: FormDefinitionVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加表单定义';
};
/** 修改按钮操作 */
const handleUpdate = async (row?: FormDefinitionVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getFormDefinition(_id);
Object.assign(form.value, res.data);
form.value.formKey = form.value.formKey.substring(fromKeyPrefix.length, form.value.formKey.length);
dialog.visible = true;
dialog.title = '修改表单定义';
};
/** 提交按钮 */
const submitForm = () => {
formDefinitionFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateFormDefinition(form.value).finally(() => (buttonLoading.value = false));
} else {
await addFormDefinition(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: FormDefinitionVO) => {
const _ids = row?.id || ids.value;
const defList = formDefinitionList.value.filter((x) => _ids.indexOf(x.id) != -1).map((x) => x.formKey);
await proxy?.$modal.confirm('是否确认删除表单定义标识为:【' + defList + '】的数据?').finally(() => (loading.value = false));
await delFormDefinition(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 设计按钮操作 */
const handleDesign = (row?: FormDefinitionVO) => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.push({
path: `/workflow/formDesign/index`,
query: {
definitionId: row.id,
disabled: false
}
});
};
/** 状态变更操作 */
const handleChangeStatus = async (row: FormDefinitionVO, status: string) => {
await proxy?.$modal.confirm('是否确认' + ('1' === status ? '发布' : '停用') + '表单定义标识为' + row.formKey + '的数据?');
loading.value = true;
await updateFormDefinitionStatus(row.id, status).finally(() => (loading.value = false));
proxy?.$modal.msgSuccess('操作成功');
await getList();
};
onMounted(() => {
getList();
});
</script>

View File

@ -0,0 +1,226 @@
<template>
<div class="p-2">
<el-card shadow="never">
<div style="display: flex; justify-content: space-between">
<div>
<el-button v-if="submitButtonShow" :loading="buttonLoading" type="info" @click="submitForm('draft')">暂存</el-button>
<el-button v-if="submitButtonShow" :loading="buttonLoading" type="primary" @click="submitForm('submit')"> </el-button>
<el-button v-if="approvalButtonShow" :loading="buttonLoading" type="primary" @click="approvalVerifyOpen">审批</el-button>
<el-button v-if="form && form.id && form.status !== 'draft'" type="primary" @click="handleApprovalRecord">流程进度</el-button>
</div>
<div>
<el-button style="float: right" @click="goBack()">返回</el-button>
</div>
</div>
</el-card>
<el-card shadow="never" style="height: 78vh; overflow-y: auto" class="mt-1">
<el-skeleton :loading="loading" animated :rows="5" />
<el-form
v-if="!loading && formSchema"
ref="formInstanceFormRef"
:disabled="routeParams.type === 'view'"
:model="form"
:rules="rules"
label-width="100px"
>
<!-- 动态表单构建 -->
<EBuilder ref="eBuilderRef" :pageSchema="formSchema" :disabled="routeParams.type === 'view'" />
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入内容"></el-input>
</el-form-item>
</el-form>
</el-card>
<!-- 提交组件 -->
<submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
<!-- 审批记录 -->
<approvalRecord ref="approvalRecordRef" />
</div>
</template>
<script setup lang="ts">
import { EBuilder, type PageSchema } from 'epic-designer';
import { startWorkFlow } from '@/api/workflow/task';
import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import { AxiosResponse } from 'axios';
import { StartProcessBo } from '@/api/workflow/workflowCommon/types';
import { FormInstanceForm, FormInstanceVO } from '@/api/workflow/formInstance/types';
import { addFormInstance, getFormInstance, updateFormInstance } from '@/api/workflow/formInstance';
import { getFormDefinition } from '@/api/workflow/formDefinition';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const loading = ref(false);
const buttonLoading = ref(false);
//
const routeParams = ref<Record<string, any>>({});
const flowCode = ref<string>('');
//
const formSchema = ref<PageSchema>(undefined);
const initFormData: FormInstanceForm = {
id: undefined,
definitionId: undefined,
formSchema: undefined,
formData: undefined,
status: 'draft',
remark: undefined
};
const form = ref<FormInstanceForm>({ ...initFormData });
const rules = ref({});
const formInstanceFormRef = ref<ElFormInstance>();
const eBuilderRef = useTemplateRef<typeof EBuilder>('eBuilderRef');
/** 获取数据 */
const getInfo = () => {
loading.value = true;
buttonLoading.value = false;
nextTick(async () => {
//
if (routeParams.value.type === 'add') {
const defRef = await getFormDefinition(routeParams.value.definitionId);
if (!defRef.data.formSchema) {
proxy?.$modal.msgError('未获取到表单结构,请检查!');
return;
}
formSchema.value = JSON.parse(defRef.data.formSchema);
flowCode.value = defRef.data.formKey;
}
if (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
const res = await getFormInstance(routeParams.value.id);
Object.assign(form.value, res.data);
//
if (res.data && res.data.formSchema) {
//
formSchema.value = JSON.parse(res.data.formSchema);
}
if (res.data && res.data.formData) {
setTimeout(() => {
eBuilderRef.value.setData(JSON.parse(res.data.formData));
}, 100);
}
}
loading.value = false;
buttonLoading.value = false;
});
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
formInstanceFormRef.value?.resetFields();
};
// =============== =================
const dialogVisible = reactive<DialogOption>({
visible: false,
title: '流程定义'
});
//
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
//
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
const submitFormData = ref<StartProcessBo>({
businessId: '',
flowCode: '',
variables: {}
});
const taskVariables = ref<Record<string, any>>({});
const submitForm = (status: string) => {
try {
formInstanceFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
const eFormData = { ...(await eBuilderRef.value.validate()) };
form.value.formSchema = JSON.stringify(formSchema.value);
form.value.formData = JSON.stringify(eFormData);
form.value.formKey = routeParams.value.formKey;
form.value.definitionId = routeParams.value.definitionId;
let res: AxiosResponse<FormInstanceVO>;
if (form.value.id) {
res = await updateFormInstance(form.value);
} else {
res = await addFormInstance(form.value);
}
form.value = res.data;
if (status === 'draft') {
buttonLoading.value = false;
proxy?.$modal.msgSuccess('暂存成功');
proxy.$tab.closePage(proxy.$route);
proxy.$router.go(-1);
} else {
await handleStartWorkFlow(res.data);
}
proxy?.$modal.msgSuccess('操作成功');
}
});
} finally {
}
buttonLoading.value = false;
};
//
const handleStartWorkFlow = async (data: FormInstanceForm) => {
try {
submitFormData.value.flowCode = data.formKey;
submitFormData.value.businessId = data.id;
// #TODO :
taskVariables.value = JSON.parse(data.formData);
submitFormData.value.variables = taskVariables.value;
const resp = await startWorkFlow(submitFormData.value);
if (submitVerifyRef.value) {
buttonLoading.value = false;
submitVerifyRef.value.openDialog(resp.data.taskId);
}
} finally {
buttonLoading.value = false;
}
};
//
const handleApprovalRecord = () => {
approvalRecordRef.value.init(form.value.id);
};
//
const submitCallback = async () => {
await proxy.$tab.closePage(proxy.$route);
proxy.$router.go(-1);
};
//
const goBack = () => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.go(-1);
};
//
const approvalVerifyOpen = () => {
submitVerifyRef.value.openDialog(routeParams.value.taskId);
};
//
const submitButtonShow = computed(() => {
return (
routeParams.value.type === 'add' ||
(routeParams.value.type === 'update' &&
form.value.status &&
(form.value.status === 'draft' || form.value.status === 'cancel' || form.value.status === 'back'))
);
});
//
const approvalButtonShow = computed(() => {
return routeParams.value.type === 'approval' && form.value.status && form.value.status === 'waiting';
});
onMounted(() => {
nextTick(async () => {
routeParams.value = { ...proxy.$route.query, ...proxy.$route.params };
reset();
getInfo();
loading.value = false;
});
});
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,251 @@
<template>
<div class="p-2">
<el-row :gutter="15">
<el-col :span="6">
<el-card shadow="never">
<el-table v-loading="loading" :data="formDefinitionList">
<el-table-column label="表单名称" align="center" prop="formName" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="新增表单实例" placement="top">
<el-button link type="primary" icon="Pointer" @click="handleAdd(scope.row)" v-hasPermi="['workflow:formInstance:add']"
>新增表单实例</el-button
>
</el-tooltip>
</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
<el-col :span="18">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option v-for="dict in wf_business_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete()"
v-hasPermi="['workflow:formInstance:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['workflow:formInstance:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="formInstanceList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="编号" align="center" prop="id" v-if="true" width="160">
<template #default="scope">
<el-link type="primary" :underline="false" @click="handleView(scope.row)">{{ scope.row.id }}</el-link>
</template>
</el-table-column>
<el-table-column label="表单定义ID" align="center" prop="definitionId" v-if="false" />
<el-table-column label="表单名称" align="center" prop="formName" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="wf_business_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="申请人" align="center" prop="createName" />
<el-table-column label="申请时间" align="center" prop="createTime" width="180">
<template #default="scope">
{{ proxy.parseTime(scope.row.createTime) }}
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['workflow:formInstance:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['workflow:formInstance:remove']"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup name="FormInstance" lang="ts">
import { listFormInstance, delFormInstance } from '@/api/workflow/formInstance';
import { FormInstanceVO, FormInstanceQuery, FormInstanceForm } from '@/api/workflow/formInstance/types';
import { listFormDefinition } from '@/api/workflow/formDefinition';
import { FormDefinitionVO } from '@/api/workflow/formDefinition/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
const formDefinitionList = ref<FormDefinitionVO[]>([]);
const formInstanceList = ref<FormInstanceVO[]>([]);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const data = reactive<PageData<FormInstanceForm, FormInstanceQuery>>({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
definitionId: undefined,
status: undefined,
params: {}
},
rules: {}
});
const { queryParams } = toRefs(data);
const defTotal = ref(0);
const defQueryParams = ref({
pageNum: 1,
pageSize: 10,
formKey: undefined,
formName: undefined,
status: undefined,
params: {}
});
const getDefList = async () => {
defQueryParams.value.status = '1';
const res = await listFormDefinition(defQueryParams.value);
formDefinitionList.value = res.rows;
defTotal.value = res.total;
};
/** 查询表单实例列表 */
const getList = async () => {
loading.value = true;
const res = await listFormInstance(queryParams.value);
formInstanceList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: FormInstanceVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 删除按钮操作 */
const handleDelete = async (row?: FormInstanceVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除表单实例编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delFormInstance(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'workflow/formInstance/export',
{
...queryParams.value
},
`formInstance_${new Date().getTime()}.xlsx`
);
};
const handleAdd = (row: FormDefinitionVO) => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.push({
path: `/workflow/dynFormEdit/index/` + row.id,
query: {
type: 'add',
formKey: row.formKey
}
});
};
/** 表单保存实例 */
const handleUpdate = (row: FormInstanceVO) => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.push({
path: `/workflow/dynFormEdit/index/` + row.definitionId,
query: {
type: 'update',
id: row.id,
formKey: row.formKey
}
});
};
const handleView = (row: FormInstanceVO) => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.push({
path: `/workflow/dynFormEdit/index/` + row.definitionId,
query: {
type: 'view',
id: row.id,
formKey: row.formKey
}
});
};
onMounted(() => {
getDefList();
getList();
});
</script>