<script lang="ts" setup>
|
import type { Ref } from 'vue';
|
|
import { nextTick, onMounted, onUnmounted, reactive, ref } from 'vue';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { BasicDrawer } from '@jnpf/ui/drawer';
|
import { BasicModal } from '@jnpf/ui/modal';
|
import { BasicPopup } from '@jnpf/ui/popup';
|
import { createAsyncComponent, getDateTimeUnit } from '@jnpf/utils';
|
|
import { useUserStore } from '@vben/stores';
|
|
import dayjs from 'dayjs';
|
import { cloneDeep } from 'lodash-es';
|
|
import { createModel, getConfigData, getModelInfo, updateModel } from '#/api/onlineDev/visualDev';
|
import FormExtraPanel from '#/components/FormExtraPanel/index.vue';
|
import { registerPendingAuditDisplayFields } from '#/components/FormGenerator/src/helper/auditDisplay';
|
import { buildDisplayOnlySubmitData } from '#/components/FormGenerator/src/helper/displayOnly';
|
import { vDisablePasswordAutofill } from '#/directives/disablePasswordAutofill';
|
import { $t } from '#/locales';
|
import { isElectronicSignatureModelId } from '#/utils/constants/electronicSignature';
|
import { onlineUtils } from '#/utils/jnpf';
|
import { processDetailData } from '#/views/common/dynamicModel/list/detail/detailData';
|
|
interface FormConfig {
|
modelId: string;
|
id?: string;
|
title?: string;
|
width?: string;
|
type?: 'drawer' | 'fullScreen' | 'modal';
|
params?: Record<string, any>;
|
submitMode?: 'custom' | 'default';
|
/**
|
* 字段映射配置,将 params 中的数据映射到表单字段
|
* key: 表单字段名
|
* value: params 中的字段路径,支持点号分隔(如 'user.name')
|
* @example { userName: 'user.name', age: 'info.age' }
|
*/
|
fieldMapping?: Record<string, string>;
|
/**
|
* 展示模式:detail(详情展示) | form(表单编辑),默认为 form
|
*/
|
mode?: 'detail' | 'form';
|
onConfirm?: (data: any) => void;
|
onCancel?: () => void;
|
onSubmit?: (data: any) => Promise<void> | void;
|
}
|
|
interface State {
|
formConf: any;
|
defaultFormConf: any;
|
formData: any;
|
config: FormConfig | null;
|
loading: boolean;
|
key: number;
|
dataForm: any;
|
title: string;
|
params: Record<string, any>;
|
mode: 'detail' | 'form';
|
open: boolean;
|
confirmLoading: boolean;
|
ready: boolean; // 配置加载完成,可以渲染组件
|
reviewPassed: boolean;
|
reviewVisible: boolean;
|
}
|
|
interface ModalInstance {
|
id: string;
|
config: FormConfig;
|
state: State;
|
popupType: string;
|
parserRef: any;
|
// 弹窗控制方法(已弃用,保留为空函数兼容)
|
registerPopup: any;
|
openPopup: any;
|
setPopupProps: any;
|
registerModal: any;
|
openModal: any;
|
setModalProps: any;
|
registerDrawer: any;
|
openDrawer: any;
|
setDrawerProps: any;
|
}
|
|
const emitter = onlineUtils.getEmitter();
|
const userStore = useUserStore();
|
const { createMessage } = useMessage();
|
|
// 弹窗栈:支持多层嵌套弹窗
|
const modalStack = ref<ModalInstance[]>([]);
|
// 存储每个弹窗的 parser ref,避免被 Vue 响应式解包
|
const parserRefMap = new Map<string, Ref<any>>();
|
|
// 动态导入 Parser 组件
|
const Parser = createAsyncComponent(() => import('#/components/FormGenerator/src/components/Parser.vue'));
|
// 动态导入 Detail Parser 组件(详情模式使用)
|
const DetailParser = createAsyncComponent(() => import('#/views/common/dynamicModel/list/detail/Parser.vue'));
|
|
// 生成唯一ID
|
function generateId(): string {
|
return `modal_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
}
|
|
// 获取映射值,支持点号路径(如 'user.name')
|
function getMappedValue(obj: any, path: string) {
|
if (!obj || !path) return undefined;
|
const keys = path.split('.');
|
let value = obj;
|
for (const key of keys) {
|
if (value === null || value === undefined) return undefined;
|
value = value[key];
|
}
|
return value;
|
}
|
|
// 填充表单数据
|
function fillFormData(form: any, data: any, state: State, isAdd = false, fieldMapping?: Record<string, string>) {
|
const userInfo = userStore.getUserInfo;
|
const currDate = new Date();
|
const loop = (list: any[]) => {
|
for (const item of list) {
|
if (item.__vModel__) {
|
let val: any;
|
// 优先使用 fieldMapping 映射的值
|
const mappedPath = fieldMapping?.[item.__vModel__];
|
if (mappedPath) {
|
val = getMappedValue(state.params, mappedPath);
|
}
|
// 其次使用原始数据中的值
|
if (val === undefined) {
|
val = Object.prototype.hasOwnProperty.call(data, item.__vModel__) ? data[item.__vModel__] : item.__config__.defaultValue;
|
}
|
if (!item.__config__.isSubTable) item.__config__.defaultValue = val;
|
if ((isAdd || item.__config__.isSubTable) && item.__config__.defaultCurrent) {
|
if (item.__config__.jnpfKey === 'datePicker') {
|
item.__config__.defaultValue = dayjs(currDate).startOf(getDateTimeUnit(item.format)).valueOf();
|
}
|
if (item.__config__.jnpfKey === 'timePicker') {
|
item.__config__.defaultValue = dayjs(currDate).format(item.format || 'HH:mm:ss');
|
}
|
if (item.__config__.jnpfKey === 'organizeSelect' && userInfo?.organizeIds?.length) {
|
item.__config__.defaultValue = item.multiple ? userInfo.organizeIds : userInfo.organizeId;
|
}
|
if (item.__config__.jnpfKey === 'userSelect' && userInfo?.userId) {
|
item.__config__.defaultValue = item.multiple ? [userInfo.userId] : userInfo.userId;
|
}
|
if (item.__config__.jnpfKey === 'usersSelect' && userInfo?.userId) {
|
item.__config__.defaultValue = [`${userInfo?.userId}--user`];
|
}
|
if (item.__config__.jnpfKey === 'posSelect' && userInfo?.positionIds?.length) {
|
item.__config__.defaultValue = item.multiple ? userInfo.positionIds : userInfo.positionId;
|
}
|
if (item.__config__.jnpfKey === 'sign' && userInfo?.signImg) {
|
item.__config__.defaultValue = userInfo.signImg;
|
}
|
}
|
}
|
if (item.__config__ && item.__config__.children && Array.isArray(item.__config__.children)) {
|
loop(item.__config__.children);
|
}
|
}
|
};
|
loop(form.fields);
|
form.formData = { ...data, ...form.formData };
|
}
|
|
// 创建新状态
|
function createState(): State {
|
return reactive<State>({
|
formConf: {},
|
defaultFormConf: {},
|
formData: {},
|
config: null,
|
loading: true,
|
key: Date.now(),
|
dataForm: {
|
id: '',
|
data: '',
|
},
|
title: '',
|
params: {},
|
mode: 'form',
|
open: false, // 弹窗初始关闭,配置加载后打开
|
confirmLoading: false,
|
ready: false, // 等待配置加载完成
|
reviewPassed: true,
|
reviewVisible: true,
|
});
|
}
|
|
// 初始化数据
|
function initData(instance: ModalInstance) {
|
const { state, config } = instance;
|
state.dataForm.id = config?.id || '';
|
if (config?.id) {
|
// 编辑模式,获取数据
|
getInfo(instance);
|
} else {
|
// 新增模式
|
state.formData = {};
|
setFormValue(instance, true).catch((error) => handleDetailDataError(instance, error));
|
}
|
}
|
|
// 获取表单数据
|
function getInfo(instance: ModalInstance) {
|
const { state, config } = instance;
|
if (!config) return;
|
changeLoading(instance, true);
|
getModelInfo(config.modelId, config.id!, '', { onlineUtilsOpen: true })
|
.then(async (res) => {
|
state.dataForm = res.data || {};
|
if (state.dataForm.data) {
|
state.formData = { ...JSON.parse(state.dataForm.data), id: state.dataForm.id };
|
}
|
await setFormValue(instance);
|
})
|
.catch((error) => handleDetailDataError(instance, error))
|
.finally(() => {
|
changeLoading(instance, false);
|
});
|
}
|
|
// 设置表单值
|
async function setFormValue(instance: ModalInstance, isAdd = false) {
|
const { state, config } = instance;
|
state.formConf = cloneDeep(state.defaultFormConf);
|
state.reviewVisible = !!state.formConf.hasReviewBtn && !state.formConf.reviewBtnConfig?.noShow;
|
state.reviewPassed = !state.reviewVisible || !!state.formConf.reviewBtnConfig?.biz_review_optional;
|
// 恢复 popupType,确保 setFormProps 判断正确
|
state.formConf.popupType = config?.type || state.defaultFormConf.popupType || 'modal';
|
if (state.mode === 'detail') state.formData = await processDetailData(state.formConf, state.formData, onlineUtils);
|
fillFormData(state.formConf, state.formData, state, isAdd, config?.fieldMapping);
|
await nextTick();
|
state.key = Date.now();
|
state.loading = false;
|
changeLoading(instance, false);
|
}
|
function handleDetailDataError(instance: ModalInstance, error: any) {
|
console.error('[GlobalFormModal] 自定义详情数据执行失败:', error);
|
createMessage.error(error?.message || '自定义详情数据执行失败');
|
closeModal(instance);
|
}
|
|
// 设置表单属性
|
function setFormProps(instance: ModalInstance, data: any) {
|
// 通过直接修改 state.open 来控制弹窗
|
if (Reflect.has(data, 'open')) {
|
instance.state.open = data.open;
|
}
|
if (Reflect.has(data, 'loading')) {
|
instance.state.loading = data.loading;
|
}
|
if (Reflect.has(data, 'confirmLoading')) {
|
instance.state.confirmLoading = data.confirmLoading;
|
}
|
}
|
|
// 改变加载状态
|
function changeLoading(instance: ModalInstance, loading: boolean) {
|
setFormProps(instance, { loading });
|
}
|
|
// 提交表单
|
async function submitForm(instance: ModalInstance, data: any, callback?: () => void, _scriptParameter = {}, auditDisplayFields = []) {
|
if (!data) return;
|
const { state, config } = instance;
|
const submitData = buildDisplayOnlySubmitData(state.formConf.fields, data);
|
|
// 自定义提交模式:验证通过后调用 onSubmit,不调用默认 API
|
if (config?.submitMode === 'custom') {
|
setFormProps(instance, { confirmLoading: true });
|
try {
|
if (!isElectronicSignatureModelId(config.modelId)) {
|
registerPendingAuditDisplayFields(auditDisplayFields);
|
}
|
await config?.onSubmit?.(submitData);
|
// onSubmit 执行成功(没有报错),关闭弹窗
|
setFormProps(instance, { confirmLoading: false });
|
closeModal(instance);
|
// 调用确认回调
|
config?.onConfirm?.({ success: true, data: submitData });
|
} catch {
|
// onSubmit 执行出错,保持弹窗打开
|
setFormProps(instance, { confirmLoading: false });
|
}
|
return;
|
}
|
|
// 默认提交模式:调用后端 API 保存数据
|
setFormProps(instance, { confirmLoading: true });
|
const formData = buildDisplayOnlySubmitData(state.formConf.fields, { ...state.formData, ...submitData });
|
state.dataForm.data = JSON.stringify(formData);
|
state.dataForm.auditDisplayFields = auditDisplayFields;
|
state.dataForm.onlineUtilsOpen = true;
|
const formMethod = state.dataForm.id ? updateModel : createModel;
|
formMethod(config!.modelId, state.dataForm)
|
.then((res) => {
|
createMessage.success(res.msg);
|
if (callback && typeof callback === 'function') callback();
|
setFormProps(instance, { confirmLoading: false });
|
closeModal(instance);
|
// 调用确认回调
|
config?.onConfirm?.({ success: true, data: res.data });
|
})
|
.catch(() => {
|
setFormProps(instance, { confirmLoading: false });
|
});
|
}
|
|
// 提交
|
async function handleSubmit(instance: ModalInstance) {
|
// detail 模式下直接关闭弹窗
|
if (instance.state.mode === 'detail') {
|
closeModal(instance);
|
return;
|
}
|
if (instance.state.loading) {
|
createMessage.warning('表单正在加载中,请稍后再试');
|
return;
|
}
|
// 从 Map 中获取 parserRef,避免 Vue 响应式解包问题
|
const parserRef = parserRefMap.get(instance.id);
|
if (!parserRef) {
|
console.error('[GlobalFormModal] parserRef not found in Map for id:', instance.id);
|
createMessage.warning('表单组件未就绪,请稍后再试');
|
return;
|
}
|
const parser = parserRef.value;
|
if (!parser) {
|
console.error('[GlobalFormModal] parser is null, parserRef:', parserRef);
|
createMessage.warning('表单正在初始化,请稍后再试');
|
return;
|
}
|
if (!parser.handleSubmit) {
|
console.error('[GlobalFormModal] parser.handleSubmit is not a function, parser:', parser);
|
return;
|
}
|
setFormProps(instance, { confirmLoading: true });
|
try {
|
const submitted = await parser.handleSubmit();
|
if (!submitted) setFormProps(instance, { confirmLoading: false });
|
} catch (error) {
|
setFormProps(instance, { confirmLoading: false });
|
console.error('[GlobalFormModal] handleSubmit error:', error);
|
// 验证失败或其他错误,不做额外处理
|
// Parser 组件内部已经处理了验证提示
|
}
|
}
|
|
function handleReview(instance: ModalInstance) {
|
parserRefMap.get(instance.id)?.value?.handleReview?.();
|
}
|
|
// 关闭回调
|
function handleClose(instance: ModalInstance) {
|
instance.config?.onCancel?.();
|
return Promise.resolve(true);
|
}
|
|
// 关闭单个弹窗
|
function closeModal(instance: ModalInstance) {
|
instance.state.open = false;
|
|
// 延迟从栈中移除,等待动画完成
|
setTimeout(() => {
|
const index = modalStack.value.findIndex((m) => m.id === instance.id);
|
if (index !== -1) {
|
modalStack.value.splice(index, 1);
|
}
|
// 清理 Map 中的引用
|
parserRefMap.delete(instance.id);
|
}, 300);
|
}
|
|
// 获取确定按钮文本
|
function getOkText(instance: ModalInstance): string {
|
const { state } = instance;
|
// detail 模式下不需要确定按钮
|
if (state.mode === 'detail') return '';
|
const text = state.formConf.confirmButtonTextI18nCode
|
? $t(state.formConf.confirmButtonTextI18nCode, state.formConf.confirmButtonText)
|
: state.formConf.confirmButtonText;
|
return text || $t('common.okText');
|
}
|
|
// 获取取消按钮文本
|
function getCancelText(instance: ModalInstance): string {
|
const { state } = instance;
|
// detail 模式下显示"关闭"
|
if (state.mode === 'detail') return $t('common.closeText');
|
const text = state.formConf.cancelButtonTextI18nCode
|
? $t(state.formConf.cancelButtonTextI18nCode, state.formConf.cancelButtonText)
|
: state.formConf.cancelButtonText;
|
return text || $t('common.cancelText');
|
}
|
|
function getReviewText(instance: ModalInstance): string {
|
const { state } = instance;
|
const text = state.formConf.reviewButtonTextI18nCode
|
? $t(state.formConf.reviewButtonTextI18nCode, state.formConf.reviewButtonText)
|
: state.formConf.reviewButtonText;
|
return text || $t('common.reviewText');
|
}
|
|
function isElectronicSignatureForm(instance: ModalInstance) {
|
return isElectronicSignatureModelId(instance.config.modelId);
|
}
|
|
function handleEnterSubmit(instance: ModalInstance, event: KeyboardEvent) {
|
const target = event.target as HTMLElement | null;
|
if (instance.state.confirmLoading || event.isComposing || event.repeat || target?.closest('textarea, [contenteditable="true"]')) {
|
return;
|
}
|
event.preventDefault();
|
void handleSubmit(instance);
|
}
|
|
// 获取 FormExtraPanel 绑定
|
function getFormExtraBind(instance: ModalInstance) {
|
const { state, config } = instance;
|
return {
|
showLog: state.formConf.dataLog,
|
modelId: config?.modelId,
|
formDataId: config?.id,
|
};
|
}
|
|
// 打开表单弹窗
|
async function handleOpenFormModal(config: FormConfig) {
|
if (!config.modelId) {
|
console.error('[GlobalFormModal] modelId is required');
|
return;
|
}
|
|
// 创建新的弹窗实例
|
const id = generateId();
|
const state = createState();
|
const parserRef = ref<any>(null);
|
// 存储到 Map 中,避免被 Vue 响应式解包
|
parserRefMap.set(id, parserRef);
|
|
const instance: ModalInstance = {
|
id,
|
config: config as FormConfig,
|
state,
|
popupType: 'modal', // 默认值,后面会更新
|
parserRef,
|
registerPopup: () => {},
|
openPopup: () => {},
|
setPopupProps: () => {},
|
registerModal: () => {},
|
openModal: () => {},
|
setModalProps: () => {},
|
registerDrawer: () => {},
|
openDrawer: () => {},
|
setDrawerProps: () => {},
|
};
|
|
// 添加到栈
|
modalStack.value.push(instance);
|
|
// 初始化状态
|
state.config = config;
|
state.params = config.params || {};
|
state.mode = config.mode || 'form';
|
state.loading = true;
|
|
try {
|
// 获取表单配置
|
const res = await getConfigData(config.modelId, { onlineUtilsOpen: true });
|
const { formData, webType, fullName } = res.data;
|
|
if (webType === 4) {
|
createMessage.warning('数据接口类型不支持弹窗打开');
|
modalStack.value = modalStack.value.filter((m) => m.id !== id);
|
return;
|
}
|
|
const parsedFormData = formData ? JSON.parse(formData) : {};
|
state.defaultFormConf = cloneDeep(parsedFormData);
|
state.formConf = cloneDeep(state.defaultFormConf);
|
state.title = config.title || fullName || '表单';
|
|
// 确定弹窗类型(注意:config.type 是 'fullScreen',parsedFormData.popupType 可能是 'fullscreen')
|
const popupType = config.type || parsedFormData.popupType || 'modal';
|
state.formConf.popupType = popupType;
|
instance.popupType = popupType;
|
|
// 标记配置加载完成,可以渲染弹窗组件
|
state.ready = true;
|
|
// 初始化数据
|
initData(instance);
|
|
// 在 nextTick 中打开弹窗,确保组件已渲染
|
nextTick(() => {
|
state.open = true;
|
});
|
} catch (error) {
|
console.error('[GlobalFormModal] Failed to open form modal:', error);
|
createMessage.error('打开表单失败');
|
modalStack.value = modalStack.value.filter((m) => m.id !== id);
|
}
|
}
|
|
// 监听事件
|
onMounted(() => {
|
emitter.on('OPEN_FORM_MODAL', handleOpenFormModal as any);
|
});
|
|
onUnmounted(() => {
|
emitter.off('OPEN_FORM_MODAL', handleOpenFormModal as any);
|
});
|
</script>
|
|
<template>
|
<template v-for="item in modalStack" :key="item.id">
|
<!-- 全屏弹窗 -->
|
<BasicPopup
|
v-if="item.state.ready && (item.popupType === 'fullScreen' || item.popupType === 'fullscreen')"
|
v-bind="$attrs"
|
:open="item.state.open"
|
destroy-on-close
|
:show-ok-btn="item.state.mode !== 'detail'"
|
:ok-text="getOkText(item)"
|
:cancel-text="getCancelText(item)"
|
:ok-button-props="{ disabled: item.state.reviewVisible && !item.state.reviewPassed }"
|
:confirm-loading="item.state.confirmLoading"
|
@ok="handleSubmit(item)"
|
:close-func="() => handleClose(item)"
|
class="global-form-popup">
|
<template #title>
|
<div class="text-[16px] font-medium">{{ item.state.title }}</div>
|
</template>
|
<template #insertToolbar>
|
<a-button v-if="item.state.mode !== 'detail' && item.state.reviewVisible" class="mr-[10px]" @click="handleReview(item)">
|
{{ getReviewText(item) }}
|
</a-button>
|
</template>
|
<div class="jnpf-common-form-wrapper">
|
<div class="jnpf-common-form-wrapper__main p-[10px]" :style="{ margin: '0 auto', width: item.state.formConf.fullscreenWidth || '100%' }">
|
<template v-if="!item.state.loading">
|
<!-- form 模式使用 Parser -->
|
<Parser
|
v-if="item.state.mode !== 'detail'"
|
:ref="
|
(el) => {
|
const ref = parserRefMap.get(item.id);
|
if (el && ref) ref.value = el;
|
}
|
"
|
:form-conf="item.state.formConf"
|
:model-id="item.config.modelId"
|
:params="item.state.params"
|
@review-status-change="item.state.reviewPassed = $event"
|
@review-visibility-change="item.state.reviewVisible = $event"
|
@submit="(data, callback, scriptParameter, auditDisplayFields) => submitForm(item, data, callback, scriptParameter, auditDisplayFields)"
|
:key="`form-${item.state.key}`" />
|
<!-- detail 模式使用 DetailParser -->
|
<DetailParser v-else :form-conf="item.state.formConf" :form-data="item.state.formData" :key="`detail-${item.state.key}`" />
|
</template>
|
</div>
|
<FormExtraPanel
|
v-bind="getFormExtraBind(item)"
|
v-if="item.state.dataForm.id && item.state.formConf.dataLog && !item.state.loading && item.state.mode !== 'detail'"
|
:key="item.state.key" />
|
</div>
|
</BasicPopup>
|
|
<!-- 居中弹窗 -->
|
<BasicModal
|
v-if="item.state.ready && (item.popupType === 'modal' || !item.popupType)"
|
v-bind="$attrs"
|
:open="item.state.open"
|
destroy-on-close
|
:ok-text="getOkText(item)"
|
:cancel-text="getCancelText(item)"
|
:show-ok-btn="item.state.mode !== 'detail'"
|
:ok-button-props="{ disabled: item.state.reviewVisible && !item.state.reviewPassed }"
|
:confirm-loading="item.state.confirmLoading"
|
@ok="handleSubmit(item)"
|
:close-func="() => handleClose(item)"
|
:min-height="100"
|
class="global-form-modal">
|
<template #title>
|
<div class="text-[16px] font-medium">{{ item.state.title }}</div>
|
</template>
|
<template #insertFooter>
|
<a-button v-if="item.state.mode !== 'detail' && item.state.reviewVisible" @click="handleReview(item)">{{ getReviewText(item) }}</a-button>
|
</template>
|
<div v-disable-password-autofill="isElectronicSignatureForm(item)" class="p-[10px]" @keydown.enter="handleEnterSubmit(item, $event)">
|
<template v-if="!item.state.loading">
|
<!-- form 模式使用 Parser -->
|
<Parser
|
v-if="item.state.mode !== 'detail'"
|
:ref="
|
(el) => {
|
const ref = parserRefMap.get(item.id);
|
if (el && ref) ref.value = el;
|
}
|
"
|
:form-conf="item.state.formConf"
|
:model-id="item.config.modelId"
|
:params="item.state.params"
|
@review-status-change="item.state.reviewPassed = $event"
|
@review-visibility-change="item.state.reviewVisible = $event"
|
@submit="(data, callback, scriptParameter, auditDisplayFields) => submitForm(item, data, callback, scriptParameter, auditDisplayFields)"
|
:key="`form-${item.state.key}`" />
|
<!-- detail 模式使用 DetailParser -->
|
<DetailParser v-else :form-conf="item.state.formConf" :form-data="item.state.formData" :key="`detail-${item.state.key}`" />
|
</template>
|
</div>
|
</BasicModal>
|
|
<!-- 抽屉弹窗 -->
|
<BasicDrawer
|
v-if="item.state.ready && item.popupType === 'drawer'"
|
v-bind="$attrs"
|
:open="item.state.open"
|
destroy-on-close
|
show-footer
|
:show-ok-btn="item.state.mode !== 'detail'"
|
:ok-text="getOkText(item)"
|
:cancel-text="getCancelText(item)"
|
:confirm-loading="item.state.confirmLoading"
|
:ok-button-props="{ disabled: item.state.reviewVisible && !item.state.reviewPassed }"
|
@ok="handleSubmit(item)"
|
:close-func="() => handleClose(item)"
|
class="global-form-drawer">
|
<template #title>
|
<div class="text-[16px] font-medium">{{ item.state.title }}</div>
|
</template>
|
<template #insertFooter>
|
<a-button v-if="item.state.mode !== 'detail' && item.state.reviewVisible" @click="handleReview(item)">{{ getReviewText(item) }}</a-button>
|
</template>
|
<div class="p-[10px]">
|
<template v-if="!item.state.loading">
|
<!-- form 模式使用 Parser -->
|
<Parser
|
v-if="item.state.mode !== 'detail'"
|
:ref="
|
(el) => {
|
const ref = parserRefMap.get(item.id);
|
if (el && ref) ref.value = el;
|
}
|
"
|
:form-conf="item.state.formConf"
|
:model-id="item.config.modelId"
|
:params="item.state.params"
|
@review-status-change="item.state.reviewPassed = $event"
|
@review-visibility-change="item.state.reviewVisible = $event"
|
@submit="(data, callback, scriptParameter, auditDisplayFields) => submitForm(item, data, callback, scriptParameter, auditDisplayFields)"
|
:key="`form-${item.state.key}`" />
|
<!-- detail 模式使用 DetailParser -->
|
<DetailParser v-else :form-conf="item.state.formConf" :form-data="item.state.formData" :key="`detail-${item.state.key}`" />
|
</template>
|
</div>
|
</BasicDrawer>
|
</template>
|
</template>
|