<script setup lang="ts">
|
import { computed, ref, watch, nextTick } from 'vue';
|
import { Modal, message, FormItem } from 'ant-design-vue';
|
import { $t } from '@vben/locales';
|
import { templateAdd, templateUpdate, templateInfo } from '#/api/tool/template';
|
import { pageList } from '#/api/tool/page-designer';
|
import formCreate from '@form-create/element-ui';
|
|
interface ModalProps {
|
id?: number | string;
|
update: boolean;
|
pageDesignId?: string | number;
|
formJson?: any;
|
}
|
|
const emit = defineEmits<{ reload: [] }>();
|
|
const isUpdate = ref(false);
|
const title = computed(() => {
|
return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
|
});
|
|
const modalVisible = ref(false);
|
const modalLoading = ref(false);
|
const currentEditId = ref<string | number>('');
|
const dynamicFormRef = ref();
|
const dynamicFormRule = ref([]);
|
const dynamicFormOption = ref({
|
submitBtn: false,
|
resetBtn: false
|
});
|
const showOkBtn = ref(true);
|
const currentPageId = ref('');
|
const formApi = ref();
|
|
// 判断是否有提交按钮
|
type RuleItem = { type?: string };
|
const hasSubmitBtn = (rules: any[] = []) => {
|
return rules.some((item: RuleItem) => item.type === 'submit');
|
};
|
// 更彻底的递归移除所有 submit 按钮,支持 children、body、columns、list、options、tabs 等容器
|
function removeSubmitBtn(rules = []) {
|
return rules
|
.filter(item => item.type !== 'submit')
|
.map(item => {
|
if (item.children) item.children = removeSubmitBtn(item.children);
|
if (item.body) item.body = removeSubmitBtn(item.body);
|
if (item.columns) item.columns = item.columns.map(col => ({
|
...col,
|
list: removeSubmitBtn(col.list || [])
|
}));
|
if (item.list) item.list = removeSubmitBtn(item.list);
|
if (item.options && Array.isArray(item.options)) item.options = removeSubmitBtn(item.options);
|
if (item.tabs) item.tabs = item.tabs.map(tab => ({
|
...tab,
|
list: removeSubmitBtn(tab.list || [])
|
}));
|
return item;
|
});
|
}
|
|
// 打开弹窗
|
const open = async (params: ModalProps = { update: false }) => {
|
try {
|
console.log('打开弹窗,参数:', params);
|
modalVisible.value = true;
|
modalLoading.value = true;
|
isUpdate.value = params.update;
|
currentEditId.value = params.id || '';
|
currentPageId.value = params.pageId || params.pageDesignId || '';
|
|
// 设置动态表单字段,始终移除所有submit按钮
|
if (params.formJson) {
|
console.log('设置动态表单规则:', params.formJson);
|
dynamicFormRule.value = removeSubmitBtn(params.formJson);
|
showOkBtn.value = true; // 始终显示确定按钮
|
} else {
|
dynamicFormRule.value = [];
|
showOkBtn.value = true;
|
}
|
|
// 编辑模式
|
if (params.id && params.update) {
|
console.log('编辑模式,获取详情数据');
|
try {
|
// 获取详情数据
|
const record = await templateInfo(params.id);
|
console.log('获取到的记录数据:', record);
|
|
// 设置动态表单数据
|
if (record.formData) {
|
try {
|
const dynamicData = JSON.parse(record.formData);
|
console.log('解析后的表单数据:', dynamicData);
|
|
await nextTick();
|
if (formApi.value) {
|
console.log('准备设置表单数据到组件');
|
// 使用 form-create 的 API 设置值
|
Object.keys(dynamicData).forEach(key => {
|
formApi.value.setValue(key, dynamicData[key]);
|
});
|
console.log('表单数据设置完成');
|
} else {
|
console.warn('表单API未就绪');
|
message.error('表单未就绪,请重试');
|
}
|
} catch (error) {
|
console.error('解析动态字段数据失败:', error);
|
message.error('加载表单数据失败');
|
}
|
} else {
|
console.log('记录中没有 formData 数据');
|
}
|
} catch (error) {
|
console.error('处理表单数据失败:', error);
|
message.error('加载表单数据失败,请重试');
|
}
|
} else {
|
// 新增时重置数据
|
console.log('新增模式,重置表单');
|
await nextTick();
|
if (formApi.value) {
|
formApi.value.resetFields && formApi.value.resetFields();
|
}
|
}
|
} catch (error) {
|
console.error('打开弹窗失败:', error);
|
message.error('加载数据失败');
|
} finally {
|
modalLoading.value = false;
|
}
|
};
|
|
const close = () => {
|
modalVisible.value = false;
|
};
|
|
defineExpose({ open, close });
|
|
function onFormMounted(api) {
|
formApi.value = api;
|
}
|
|
// handleOk 只负责触发表单 submit
|
async function handleOk() {
|
await nextTick();
|
console.log('handleOk formApi:', formApi.value);
|
if (!dynamicFormRule.value || dynamicFormRule.value.length === 0) {
|
message.error('表单规则未加载,无法提交');
|
return;
|
}
|
if (!formApi.value) {
|
message.error('表单未渲染完成,请稍后重试');
|
return;
|
}
|
try {
|
modalLoading.value = true;
|
const valid = await formApi.value.validate();
|
if (!valid) {
|
modalLoading.value = false;
|
return;
|
}
|
const formData = formApi.value.formData();
|
await onFormSubmit(formData);
|
} catch (error) {
|
console.error('保存失败:', error);
|
message.error('保存失败');
|
modalLoading.value = false;
|
}
|
}
|
|
// form-create 的 submit 事件处理
|
async function onFormSubmit(dynamicData: any) {
|
try {
|
modalLoading.value = true;
|
// 构建保存数据
|
const finalData = {
|
pageId: currentPageId.value,
|
formData: Object.keys(dynamicData).length > 0 ? JSON.stringify(dynamicData) : undefined
|
};
|
if (isUpdate.value) {
|
finalData.id = currentEditId.value;
|
}
|
console.log(finalData)
|
await (isUpdate.value ? templateUpdate(finalData) : templateAdd(finalData));
|
emit('reload');
|
close();
|
message.success('保存成功');
|
} catch (error) {
|
console.error('保存失败:', error);
|
message.error('保存失败');
|
} finally {
|
modalLoading.value = false;
|
}
|
}
|
|
function handleCancel() {
|
close();
|
}
|
</script>
|
|
<template>
|
<a-modal
|
v-model:open="modalVisible"
|
:title="title"
|
:width="'80vw'"
|
:confirm-loading="modalLoading"
|
@ok="handleOk"
|
@cancel="handleCancel"
|
:bodyStyle="{ padding: '24px', minHeight: '60vh' }"
|
destroyOnClose
|
:ok-button-props="{ style: showOkBtn ? {} : { display: 'none' } }"
|
>
|
<!-- 动态表单区域 -->
|
<form-create
|
ref="dynamicFormRef"
|
:rule="dynamicFormRule"
|
:option="dynamicFormOption"
|
@submit="onFormSubmit"
|
@mounted="onFormMounted"
|
/>
|
</a-modal>
|
</template>
|