Files
DjangoAdmin_Django_EleVue/public/templates/ui2/edit.vue.tpl
T
2026-09-11 11:39:07 +08:00

367 lines
12 KiB
Smarty
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- file name: ui/edit_tree.vue.tpl -->
<template>
<el-dialog
v-model="props.visible"
:title="props.{{ primary_key }} ? '编辑{{ module_comment }}' : '新增{{ module_comment }}'"
width="500"
:close-on-click-modal="false"
:before-close="dialogClose"
>
<!-- 表单 -->
<el-form class="ls-form" ref="formRef" :model="formData" label-width="80px">
{% for field in form_fields %}
{% if field.camel_name == parent_id_field %}
<!-- {{ field.comment }}(树形选择器) -->
<el-form-item
label="{{ field.label }}"
prop="{{ field.camel_name }}"
{% if field.required %}
:rules="{ required: true, message: '请选择{{ field.comment }}', trigger: 'change' }"
{% endif %}
>
<el-tree-select
v-model="formData.{{ field.camel_name }}"
:data="treeOptions"
clearable
node-key="{{ primary_key }}"
:props="{
label: '{{ display_field_camel }}',
}"
:default-expand-all="true"
placeholder="请选择{{ field.comment }}"
check-strictly
/>
</el-form-item>
{% elif field.is_image %}
<!-- {{ field.comment }}(图片上传) -->
<el-form-item
label="{{ field.label }}"
prop="{{ field.camel_name }}"
{% if field.required %}
:rules="{ required: true, message: '请上传{{ field.comment }}', trigger: 'change' }"
{% endif %}
>
<UploadImg
@changeFileName="(name) => (formData.{{ field.camel_name }}ImgName = name)"
:fileType="['image/jpeg', 'image/png', 'image/jpg', 'image/gif', 'image/webp']"
name="{{ app_name }}"
:fileSize="20"
v-model:image-url="formData.{{ field.camel_name }}"
>
<template #tip>支持扩展名: jpg png jpeg gif webp; 文件大小不超过20M</template>
</UploadImg>
</el-form-item>
{% elif field.type == 'CharField' and ('备注' in field.comment or '介绍' in field.comment or '描述' in field.comment or '说明' in field.comment) %}
<!-- {{ field.comment }}(多行文本) -->
<el-form-item
label="{{ field.label }}"
prop="{{ field.camel_name }}"
{% if field.required %}
:rules="{ required: true, message: '请输入{{ field.comment }}', trigger: 'blur' }"
{% endif %}
>
<el-input type="textarea" v-model="formData.{{ field.camel_name }}" placeholder="请输入{{ field.comment }}" :rows="3" clearable />
</el-form-item>
{% elif field.type == 'CharField' %}
<!-- {{ field.comment }} -->
<el-form-item
label="{{ field.label }}"
prop="{{ field.camel_name }}"
{% if field.required %}
:rules="{ required: true, message: '请输入{{ field.comment }}', trigger: 'blur' }"
{% endif %}
>
<el-input class="ls-input" v-model="formData.{{ field.camel_name }}" placeholder="请输入{{ field.comment }}" clearable />
</el-form-item>
{% elif field.type == 'IntegerField' and field.choices %}
<!-- {{ field.comment }}({% if field.choices|length <= 2 %}单选{% else %}下拉选择{% endif %}) -->
<el-form-item
label="{{ field.label }}"
prop="{{ field.camel_name }}"
{% if field.required %}
:rules="{ required: true, message: '请选择{{ field.comment }}', trigger: 'change' }"
{% endif %}
>
{% if field.choices|length <= 2 %}
<el-radio-group v-model="formData.{{ field.camel_name }}">
{% for choice in field.choices %}
<el-radio :value="{{ choice.value }}">{{ choice.label }}</el-radio>
{% endfor %}
</el-radio-group>
{% else %}
<el-select
v-model="formData.{{ field.camel_name }}"
placeholder="请选择{{ field.comment }}"
clearable
filterable
>
<el-option
v-for="item in optionsData.{{ field.camel_name }}List"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
{% endif %}
</el-form-item>
{% elif field.type == 'IntegerField' and not field.choices %}
<!-- {{ field.comment }}(数字输入) -->
<el-form-item
label="{{ field.label }}"
prop="{{ field.camel_name }}"
{% if field.required %}
:rules="{ required: true, message: '请输入{{ field.comment }}', trigger: 'blur' }"
{% endif %}
>
<el-input-number v-model="formData.{{ field.camel_name }}" :min="{{ field.min_value or 0 }}" :max="{{ field.max_value or 99999 }}" />
</el-form-item>
{% elif field.type == 'BooleanField' %}
<!-- {{ field.comment }}(开关) -->
<el-form-item label="{{ field.label }}" prop="{{ field.camel_name }}">
<el-switch v-model="formData.{{ field.camel_name }}" :active-value="1" :inactive-value="0" />
</el-form-item>
{% elif field.type == 'DateField' %}
<!-- {{ field.comment }}(日期选择) -->
<el-form-item
label="{{ field.label }}"
prop="{{ field.camel_name }}"
{% if field.required %}
:rules="{ required: true, message: '请选择{{ field.comment }}', trigger: 'change' }"
{% endif %}
>
<el-date-picker
v-model="formData.{{ field.camel_name }}"
type="date"
placeholder="请选择{{ field.comment }}"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
/>
</el-form-item>
{% elif field.type == 'DateTimeField' %}
<!-- {{ field.comment }}(日期时间选择) -->
<el-form-item
label="{{ field.label }}"
prop="{{ field.camel_name }}"
{% if field.required %}
:rules="{ required: true, message: '请选择{{ field.comment }}', trigger: 'change' }"
{% endif %}
>
<el-date-picker
v-model="formData.{{ field.camel_name }}"
type="datetime"
placeholder="请选择{{ field.comment }}"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
{% elif field.type == 'TextField' %}
<!-- {{ field.comment }}(文本域) -->
<el-form-item
label="{{ field.label }}"
prop="{{ field.camel_name }}"
{% if field.required %}
:rules="{ required: true, message: '请输入{{ field.comment }}', trigger: 'blur' }"
{% endif %}
>
<el-input type="textarea" v-model="formData.{{ field.camel_name }}" placeholder="请输入{{ field.comment }}" :rows="3" />
</el-form-item>
{% elif field.type == 'FloatField' or field.type == 'DecimalField' %}
<!-- {{ field.comment }}(数字输入) -->
<el-form-item
label="{{ field.label }}"
prop="{{ field.camel_name }}"
{% if field.required %}
:rules="{ required: true, message: '请输入{{ field.comment }}', trigger: 'blur' }"
{% endif %}
>
<el-input-number
v-model="formData.{{ field.camel_name }}"
:min="{{ field.min_value or 0 }}"
:max="{{ field.max_value or 999999 }}"
:precision="2"
:step="0.1"
/>
</el-form-item>
{% endif %}
{% endfor %}
</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{{ model_class_name }}List, get{{ model_class_name }}Detail, {{ model_class_name_camel }}Add, {{ model_class_name_camel }}Update } from '@/api/{{ api_path }}';
import { onMounted, reactive, shallowRef, watch, ref } from 'vue';
import { message, buildTree } from '@/utils/auth';
import { useLockFn } from '@/utils/useLockFn';
{% if has_image_field %}
import UploadImg from '@/components/Upload/Image.vue';
{% endif %}
// 定义事件
const emit = defineEmits(['success', 'update:visible']);
// 表单引用
const formRef = shallowRef<FormInstance>();
// 树形选项数据
const treeOptions = ref<any[]>([]);
/**
* 定义选项数据
*/
const optionsData = reactive({
{% for field in form_fields %}
{% if field.type == 'IntegerField' and field.choices and field.choices|length > 2 %}
{{ field.camel_name }}List: [
{% for choice in field.choices %}
{
id: {% if choice.value_type == 'string' %}'{{ choice.value }}'{% else %}{{ choice.value }}{% endif %},
name: '{{ choice.label }}',
},
{% endfor %}
],
{% endif %}
{% endfor %}
});
/**
* 定义表单数据
* 初始化默认值
*/
const formData = reactive({
id: '', // ID字段,新增时为0
{% for field in form_fields %}
{{ field.camel_name }}: {% if field.type == 'CharField' %}''{% elif field.type == 'IntegerField' %}{{ field.default or 0 }}{% elif field.type == 'BooleanField' %}{{ field.default or 0 }}{% elif field.type == 'FloatField' %}{{ field.default or 0 }}{% else %}''{% endif %},
{% endfor %}
{% for field in form_fields %}
{% if field.is_image %}
{{ field.camel_name }}ImgName: '', // {{ field.comment }}文件名
{% endif %}
{% endfor %}
});
/**
* 定义接收的参数
*/
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
{{ primary_key }}: {
type: Number,
required: true,
default: 0,
},
// 新增时传入的父级ID(驼峰格式)
parentId: {
type: Number,
default: 0,
},
});
/**
* 获取树形数据
*/
const get{{ model_class_name }}Tree = async () => {
const data = await get{{ model_class_name }}List();
const tree: any = [{ id: 0, {{ display_field_camel }}: '顶级', children: [] }];
const lists = buildTree(data);
tree[0].children.push(...lists);
treeOptions.value = tree;
};
/**
* 执行提交表单
* 根据是否有ID判断是新增还是编辑
*/
const handleSubmit = async () => {
// 表单验证
await formRef.value?.validate();
// 调用接口
props.{{ primary_key }} ? await {{ model_class_name_camel }}Update(formData) : await {{ model_class_name_camel }}Add(formData);
message('操作成功');
emit('update:visible', false);
emit('success');
};
/**
* 关闭窗体
*/
const dialogClose = () => {
emit('update:visible', false);
};
// 防抖处理,防止重复提交
const { isLock: subLoading, lockFn: submit } = useLockFn(handleSubmit);
/**
* 设置表单数据
* 编辑时获取详情并填充表单
*/
const setFormData = async () => {
try {
const data = await get{{ model_class_name }}Detail(props.{{ primary_key }});
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
// @ts-ignore
formData[key] = data[key];
}
}
} catch (error) {
console.error('获取{{ module_comment }}详情失败', error);
message('获取数据失败', 'error');
}
};
/**
* 重置表单
*/
const resetForm = () => {
if (formRef.value) {
formRef.value.resetFields();
}
// 设置父级ID默认值(使用驼峰格式)
formData.{{ parent_id_field }} = props.parentId || 0;
};
/**
* 监听对话框打开
* 编辑时加载数据,新增时重置表单
*/
onMounted(() => {
get{{ model_class_name }}Tree();
if (props.{{ primary_key }}) {
setFormData();
} else {
resetForm();
}
});
// 监听visible变化,重新加载数据
watch(
() => props.visible,
(newVal) => {
if (newVal && props.{{ primary_key }}) {
setFormData();
} else if (newVal && !props.{{ primary_key }}) {
resetForm();
get{{ model_class_name }}Tree();
}
},
);
</script>
<style lang="scss" scoped></style>