签入版本
This commit is contained in:
@@ -0,0 +1,410 @@
|
||||
<template>
|
||||
<!-- [[$.ModuleComment]]新增/编辑弹窗 -->
|
||||
<el-dialog
|
||||
v-model="props.visible"
|
||||
:title="props.[[$.PrimaryPk]] ? '编辑[[$.ModuleComment]]' : '新增[[$.ModuleComment]]'"
|
||||
[[- if $.HasRichTextField]]
|
||||
width="850"
|
||||
[[- else]]
|
||||
width="500"
|
||||
[[- end]]
|
||||
:close-on-click-modal="false"
|
||||
:before-close="dialogClose"
|
||||
>
|
||||
<!-- 表单 -->
|
||||
<el-form class="ls-form" ref="formRef" :model="formData" label-width="80px">
|
||||
[[- range .FormFields]]
|
||||
[[- if .IsImage]]
|
||||
<!-- [[.Comment]](图片上传) -->
|
||||
<el-form-item
|
||||
label="[[.Label]]"
|
||||
prop="[[.CamelName]]"
|
||||
[[- if .Required]]
|
||||
:rules="{ required: true, message: '请上传[[.Comment]]', trigger: 'change' }"
|
||||
[[- end]]
|
||||
>
|
||||
<UploadImg
|
||||
@changeFileName="(name) => (formData.[[.CamelName]]ImgName = name)"
|
||||
:fileType="['image/jpeg', 'image/png', 'image/jpg', 'image/gif', 'image/webp']"
|
||||
name="[[$.AppName]]"
|
||||
:fileSize="20"
|
||||
v-model:image-url="formData.[[.CamelName]]"
|
||||
>
|
||||
<template #tip>支持扩展名: jpg png jpeg gif webp; 文件大小不超过20M</template>
|
||||
</UploadImg>
|
||||
</el-form-item>
|
||||
[[- else if .IsRichText]]
|
||||
<!-- [[.Comment]](富文本编辑器) -->
|
||||
<el-form-item
|
||||
label="[[.Label]]"
|
||||
prop="[[.CamelName]]"
|
||||
[[- if .Required]]
|
||||
:rules="{ required: true, message: '请输入[[.Comment]]', trigger: 'blur' }"
|
||||
[[- end]]
|
||||
>
|
||||
<div class="flex">
|
||||
<el-form-item class="flex-1" label-width="0">
|
||||
<Editor
|
||||
ref="[[.CamelName]]EditorRef"
|
||||
:height="editorHeight"
|
||||
class="flex-1"
|
||||
name="[[$.AppName]]"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form-item>
|
||||
[[- else if and (eq .Type "CharField") ((containsAny .Comment "备注" "介绍" "描述" "说明"))]]
|
||||
<!-- [[.Comment]](多行文本) -->
|
||||
<el-form-item
|
||||
label="[[.Label]]"
|
||||
prop="[[.CamelName]]"
|
||||
[[- if .Required]]
|
||||
:rules="{ required: true, message: '请输入[[.Comment]]', trigger: 'blur' }"
|
||||
[[- end]]
|
||||
>
|
||||
<el-input type="textarea" v-model="formData.[[.CamelName]]" placeholder="请输入[[.Comment]]" :rows="3" clearable />
|
||||
</el-form-item>
|
||||
[[- else if eq .Type "CharField"]]
|
||||
<!-- [[.Comment]](单行文本) -->
|
||||
<el-form-item
|
||||
label="[[.Label]]"
|
||||
prop="[[.CamelName]]"
|
||||
[[- if .Required]]
|
||||
:rules="{ required: true, message: '请输入[[.Comment]]', trigger: 'blur' }"
|
||||
[[- end]]
|
||||
>
|
||||
<el-input class="ls-input" v-model="formData.[[.CamelName]]" placeholder="请输入[[.Comment]]" clearable />
|
||||
</el-form-item>
|
||||
[[- else if and (eq .Type "IntegerField") (.Choices)]]
|
||||
<!-- [[.Comment]]([[if le (len .Choices) 3]]单选[[else]]下拉选择[[end]]) -->
|
||||
<el-form-item
|
||||
label="[[.Label]]"
|
||||
prop="[[.CamelName]]"
|
||||
[[- if .Required]]
|
||||
:rules="{ required: true, message: '请选择[[.Comment]]', trigger: 'change' }"
|
||||
[[- end]]
|
||||
>
|
||||
[[- if le (len .Choices) 3]]
|
||||
<el-radio-group v-model="formData.[[.CamelName]]">
|
||||
[[- range .Choices]]
|
||||
<el-radio :value="[[.Value]]">[[.Label]]</el-radio>
|
||||
[[- end]]
|
||||
</el-radio-group>
|
||||
[[- else]]
|
||||
<el-select
|
||||
v-model="formData.[[.CamelName]]"
|
||||
placeholder="请选择[[.Comment]]"
|
||||
clearable
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in optionsData.[[.CamelName]]List"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
[[- end]]
|
||||
</el-form-item>
|
||||
[[- else if and (eq .Type "IntegerField") (not .Choices)]]
|
||||
<!-- [[.Comment]](数字输入) -->
|
||||
<el-form-item
|
||||
label="[[.Label]]"
|
||||
prop="[[.CamelName]]"
|
||||
[[- if .Required]]
|
||||
:rules="{ required: true, message: '请输入[[.Comment]]', trigger: 'blur' }"
|
||||
[[- end]]
|
||||
>
|
||||
<el-input-number v-model="formData.[[.CamelName]]" :min="[[.MinValue]]" :max="[[.MaxValue]]" />
|
||||
</el-form-item>
|
||||
[[- else if eq .Type "BooleanField"]]
|
||||
<!-- [[.Comment]](开关) -->
|
||||
<el-form-item label="[[.Label]]" prop="[[.CamelName]]">
|
||||
<el-switch v-model="formData.[[.CamelName]]" :active-value="1" :inactive-value="0" />
|
||||
</el-form-item>
|
||||
[[- else if eq .Type "DateField"]]
|
||||
<!-- [[.Comment]](日期选择) -->
|
||||
<el-form-item
|
||||
label="[[.Label]]"
|
||||
prop="[[.CamelName]]"
|
||||
[[- if .Required]]
|
||||
:rules="{ required: true, message: '请选择[[.Comment]]', trigger: 'change' }"
|
||||
[[- end]]
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="formData.[[.CamelName]]"
|
||||
type="date"
|
||||
placeholder="请选择[[.Comment]]"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
[[- else if eq .Type "DateTimeField"]]
|
||||
<!-- [[.Comment]](日期时间选择) -->
|
||||
<el-form-item
|
||||
label="[[.Label]]"
|
||||
prop="[[.CamelName]]"
|
||||
[[- if .Required]]
|
||||
:rules="{ required: true, message: '请选择[[.Comment]]', trigger: 'change' }"
|
||||
[[- end]]
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="formData.[[.CamelName]]"
|
||||
type="datetime"
|
||||
placeholder="请选择[[.Comment]]"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
[[- else if eq .Type "TextField"]]
|
||||
<!-- [[.Comment]](文本域) -->
|
||||
<el-form-item
|
||||
label="[[.Label]]"
|
||||
prop="[[.CamelName]]"
|
||||
[[- if .Required]]
|
||||
:rules="{ required: true, message: '请输入[[.Comment]]', trigger: 'blur' }"
|
||||
[[- end]]
|
||||
>
|
||||
<el-input type="textarea" v-model="formData.[[.CamelName]]" placeholder="请输入[[.Comment]]" :rows="3" />
|
||||
</el-form-item>
|
||||
[[- else if or (eq .Type "FloatField") (eq .Type "DecimalField")]]
|
||||
<!-- [[.Comment]](小数输入) -->
|
||||
<el-form-item
|
||||
label="[[.Label]]"
|
||||
prop="[[.CamelName]]"
|
||||
[[- if .Required]]
|
||||
:rules="{ required: true, message: '请输入[[.Comment]]', trigger: 'blur' }"
|
||||
[[- end]]
|
||||
>
|
||||
<el-input-number
|
||||
v-model="formData.[[.CamelName]]"
|
||||
:min="[[.MinValue]]"
|
||||
:max="[[.MaxValue]]"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
/>
|
||||
</el-form-item>
|
||||
[[- end]]
|
||||
[[- end]]
|
||||
</el-form>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogClose">取消</el-button>
|
||||
<el-button :loading="subLoading" type="primary" @click="submit">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { FormInstance } from 'element-plus';
|
||||
import { get[[$.ModelClass]]Detail, [[$.ModuleCamel]]Add, [[$.ModuleCamel]]Update } from '@/api/[[$.ApiPath]]';
|
||||
import { onMounted, reactive, shallowRef, watch } from 'vue';
|
||||
import { message } from '@/utils/auth';
|
||||
import { useLockFn } from '@/utils/useLockFn';
|
||||
[[- if $.HasImageField]]
|
||||
import UploadImg from '@/components/Upload/Image.vue';
|
||||
[[- end]]
|
||||
[[- if $.HasRichTextField]]
|
||||
import Editor from '@/components/Editor/tinymce.vue';
|
||||
[[- end]]
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(['success', 'update:visible']);
|
||||
|
||||
// 表单引用
|
||||
const formRef = shallowRef<FormInstance>();
|
||||
|
||||
[[- if $.HasRichTextField]]
|
||||
// 富文本编辑器高度,按视口高度动态计算
|
||||
const editorHeight = document.body.clientHeight - 400;
|
||||
|
||||
// 富文本编辑器引用
|
||||
[[- range .FormFields]]
|
||||
[[- if .IsRichText]]
|
||||
const [[.CamelName]]EditorRef = ref();
|
||||
[[- end]]
|
||||
[[- end]]
|
||||
[[- end]]
|
||||
|
||||
/**
|
||||
* 下拉选项数据
|
||||
*
|
||||
* 仅当选项数超过 3 个时生成,供 el-select 使用;
|
||||
* 选项不超过 3 个的字段在模板中直接用 el-radio 渲染,不在此维护。
|
||||
*/
|
||||
const optionsData = reactive({
|
||||
[[- range .FormFields]]
|
||||
[[- if and (eq .Type "IntegerField") (.Choices) (gt (len .Choices) 3)]]
|
||||
[[.CamelName]]List: [
|
||||
[[- range .Choices]]
|
||||
{
|
||||
id: [[if eq .ValueType "string"]]'[[.Value]]'[[else]][[.Value]][[end]],
|
||||
name: '[[.Label]]',
|
||||
},
|
||||
[[- end]]
|
||||
],
|
||||
[[- end]]
|
||||
[[- end]]
|
||||
});
|
||||
|
||||
/**
|
||||
* 表单数据
|
||||
*
|
||||
* 字段与 form_fields 一一对应,按类型初始化默认值;
|
||||
* 图片字段额外维护一个 {字段名}ImgName,用于回显原始文件名。
|
||||
*/
|
||||
const formData = reactive({
|
||||
id: '', // ID字段,新增时为0
|
||||
[[- range .FormFields]]
|
||||
[[.CamelName]]: [[if or (eq .Type "IntegerField") (eq .Type "BooleanField") (eq .Type "FloatField") (eq .Type "DecimalField")]][[.Default]][[else]]''[[end]],
|
||||
[[- end]]
|
||||
[[- range .FormFields]]
|
||||
[[- if .IsImage]]
|
||||
[[.CamelName]]ImgName: '', // [[.Comment]]文件名
|
||||
[[- end]]
|
||||
[[- end]]
|
||||
});
|
||||
|
||||
/**
|
||||
* 组件接收的参数
|
||||
*
|
||||
* @property visible 弹窗是否显示,配合 update:visible 双向绑定
|
||||
* @property [[$.PrimaryPk]] [[$.ModuleComment]]ID,为 0 时表示新增
|
||||
*/
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
[[$.PrimaryPk]]: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* 提交表单
|
||||
*
|
||||
* 处理流程:
|
||||
* 1. 同步富文本编辑器内容到 formData;
|
||||
* 2. 触发表单校验,未通过则中断;
|
||||
* 3. 按主键是否存在决定调用新增或更新接口;
|
||||
* 4. 成功后提示并通知父组件刷新列表、关闭弹窗。
|
||||
*/
|
||||
const handleSubmit = async () => {
|
||||
// 获取富文本编辑器内容
|
||||
[[- range .FormFields]]
|
||||
[[- if .IsRichText]]
|
||||
if ([[.CamelName]]EditorRef.value) {
|
||||
formData.[[.CamelName]] = [[.CamelName]]EditorRef.value.myValue;
|
||||
}
|
||||
[[- end]]
|
||||
[[- end]]
|
||||
|
||||
// 表单验证
|
||||
await formRef.value?.validate();
|
||||
|
||||
// 调用接口
|
||||
props.[[$.PrimaryPk]] ? await [[$.ModuleCamel]]Update(formData) : await [[$.ModuleCamel]]Add(formData);
|
||||
|
||||
message('操作成功');
|
||||
emit('update:visible', false);
|
||||
emit('success');
|
||||
};
|
||||
|
||||
/**
|
||||
* 关闭弹窗
|
||||
*
|
||||
* 通过 update:visible 通知父组件隐藏。
|
||||
*/
|
||||
const dialogClose = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
// 防抖处理,防止重复提交
|
||||
const { isLock: subLoading, lockFn: submit } = useLockFn(handleSubmit);
|
||||
|
||||
/**
|
||||
* 加载详情数据
|
||||
*
|
||||
* 按主键请求详情,逐字段回填到 formData;
|
||||
* 同时把富文本内容同步到对应编辑器实例。
|
||||
* 请求失败时提示用户并输出控制台错误。
|
||||
*/
|
||||
const setFormData = async () => {
|
||||
try {
|
||||
const data = await get[[$.ModelClass]]Detail(props.[[$.PrimaryPk]]);
|
||||
for (const key in formData) {
|
||||
if (data[key] != null && data[key] != undefined) {
|
||||
// @ts-ignore
|
||||
formData[key] = data[key];
|
||||
}
|
||||
}
|
||||
// 设置富文本编辑器内容
|
||||
[[- range .FormFields]]
|
||||
[[- if .IsRichText]]
|
||||
if ([[.CamelName]]EditorRef.value && formData.[[.CamelName]]) {
|
||||
[[.CamelName]]EditorRef.value.myValue = formData.[[.CamelName]];
|
||||
}
|
||||
[[- end]]
|
||||
[[- end]]
|
||||
} catch (error) {
|
||||
console.error('获取[[$.ModuleComment]]详情失败', error);
|
||||
message('获取数据失败', 'error');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 重置表单
|
||||
*
|
||||
* 调用 el-form 的 resetFields 清空校验状态与字段值,
|
||||
* 并同步清空富文本编辑器内容。
|
||||
*/
|
||||
const resetForm = () => {
|
||||
if (formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
// 清空富文本编辑器内容
|
||||
[[- range .FormFields]]
|
||||
[[- if .IsRichText]]
|
||||
if ([[.CamelName]]EditorRef.value) {
|
||||
[[.CamelName]]EditorRef.value.myValue = '';
|
||||
}
|
||||
[[- end]]
|
||||
[[- end]]
|
||||
};
|
||||
|
||||
/**
|
||||
* 组件挂载后处理
|
||||
*
|
||||
* 编辑场景加载详情,新增场景重置表单。
|
||||
*/
|
||||
onMounted(() => {
|
||||
if (props.[[$.PrimaryPk]]) {
|
||||
setFormData();
|
||||
} else {
|
||||
resetForm();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 监听弹窗显示状态
|
||||
*
|
||||
* 显示时:编辑场景加载详情,新增场景重置表单。
|
||||
*/
|
||||
watch(
|
||||
() => props.visible,
|
||||
(newVal) => {
|
||||
if (newVal && props.[[$.PrimaryPk]]) {
|
||||
setFormData();
|
||||
} else if (newVal && !props.[[$.PrimaryPk]]) {
|
||||
resetForm();
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
Reference in New Issue
Block a user