This commit is contained in:
zhang zhuo 2025-12-12 15:38:34 +08:00
parent bfba89daba
commit 7a907ad314
1 changed files with 156 additions and 26 deletions

View File

@ -1,24 +1,162 @@
{% macro renderProps(props) %}
{% autoescape false %}
{% for key, val in props %}
{% if val is same as(true) %}
{{- ' ' ~ key -}}
{% elseif val is same as(false) or val is null %}
{% elseif val is iterable %}
{% elseif (val ~ '') matches '/^-?\\d+(\\.\\d+)?$/' %}
{{- ' :' ~ key ~ '="' ~ val ~ '"' -}}
{% elseif val is not null and val != "" %}
{{- ' ' ~ key ~ '="' ~ val ~ '"' -}}
{% endif %}
{% endfor %}
{% endautoescape %}
{% endmacro %}
{% macro renderField(field, config, _self) %}
{% if field.name == 'layout' %}
<el-row :gutter="{{ field.props.gutter|default(0) }}">
{% for child in field.children %}
<el-col :span="{{ child.span|default(24) }}">
{{ _self.renderField(child, config, _self) -}}
</el-col>
{% endfor %}
</el-row>
{% else %}
<el-form-item label="{{ field.title }}" prop="{{ field.field_name }}">
{% if field.name in ['text', 'textarea', 'password'] %}
<el-input v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}{% if field.width %} style="width: {{ field.width }}"{% endif %}/>
{% elseif field.name == 'number' %}
<el-input-number v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}{% if field.width %} style="width: {{ field.width }}"{% endif %}/>
{% elseif field.name == 'select' %}
<el-select v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}{% if field.width %} style="width: {{ field.width }}"{% endif %}>
{% for item in field.options %}
<el-option label="{{ item.label }}" value="{{ item.value }}"></el-option>
{% endfor %}
</el-select>
{% elseif field.name == 'cascader' %}
<el-cascader v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}{% if field.props.props %} :props="{{ field.props.props | json_encode | replace({'"': "'"}) | raw }}"{% endif %}{% if field.width %} style="width: {{ field.width }}"{% endif %}/>
{% elseif field.name == 'radio' %}
<el-radio-group v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}>
{% for item in field.options %}
{% if field.style == 'button' %}
<el-radio-button label="{{ item.label }}" value="{{ item.value }}"/>
{% else %}
<el-radio label="{{ item.label }}" value="{{ item.value }}"/>
{% endif %}
{% endfor %}
</el-radio-group>
{% elseif field.name == 'checkbox' %}
<el-checkbox-group v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}>
{% for item in field.options %}
{% if field.style == 'button' %}
<el-checkbox-button label="{{ item.label }}" value="{{ item.value }}"/>
{% else %}
<el-checkbox label="{{ item.label }}" value="{{ item.value }}"/>
{% endif %}
{% endfor %}
</el-checkbox-group>
{% elseif field.name == 'switch' %}
<el-switch v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}/>
{% elseif field.name == 'slider' %}
<el-slider v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}/>
{% elseif field.name == 'time' %}
<el-time-picker v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}/>
{% elseif field.name == 'timerange' %}
<el-time-picker v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}/>
{% elseif field.name == 'date' %}
<el-date-picker v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}/>
{% elseif field.name == 'daterange' %}
<el-date-picker v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}/>
{% elseif field.name == 'rate' %}
<el-rate v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}/>
{% elseif field.name == 'color' %}
<el-color-picker v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}/>
{% elseif field.name == 'upload' %}
<el-upload v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}>
{% if field.props.listType == 'text' or field.props.listType == 'picture' %}
<template #trigger>
<el-button type="primary" icon="pi-icon-upload-file">
{{ field.btnText }}
</el-button>
</template>
{% else %}
<template #trigger>
<el-icon>
<component :is="'el-icon-plus'"/>
</el-icon>
</template>
{% endif %}
{% if field.tip %}
<template #tip>
<div class="el-upload__tip">
{{ field.tip }}
</div>
</template>
{% endif %}
</el-upload>
{% elseif field.name == 'button' %}
<el-button v-model="{{ config.model }}.{{ field.field_name }}"{{ _self.renderProps(field.props) }}>
{% if field.btnText %}
<template #default>
{{ field.btnText }}
</template>
{% endif %}
</el-button>
{% endif %}
</el-form-item>
{% endif %}
{% endmacro %}
{% macro renderFormDefaults(fields) %}
{% for field in fields %}
{# 如果是容器,递归 children #}
{% if field.children is defined and field.children is iterable %}
{{ _self.renderFormDefaults(field.children) }}
{% elseif field.field_name is defined %}
{% set val = field.value is defined ? field.value : null %}
{{ field.field_name }}: {{ val is null ? 'null' : val }},
{% endif %}
{% endfor %}
{% endmacro %}
{% macro js_object(rule) %}
{ {% for k, v in rule %}
{{ k }}: '{{ v }}'
{%- if not loop.last %}, {% endif %}
{% endfor %} }
{% endmacro %}
{% macro renderRules(fields) %}
{% for field in fields %}
{% if field.children is defined and field.children is iterable %}
{{- _self.renderRules(field.children) -}}
{% elseif field.field_name is defined %}
{% if (field.rules is defined and field.rules|length > 0) or field.required|default(false) == true %}
{{ field.field_name }}: [
{# 输出规则数组 #}
{% if field.required|default(false) == true %}
{ required: true, message: '该项必填', trigger: 'blur' },
{% endif %}
{% if field.rules is defined and field.rules|length > 0 %}
{% for rule in field.rules %}
{{ _self.js_object(rule) }}
{% endfor %}
{% endif %}],
{% endif %}
{% endif %}
{% endfor %}
{% endmacro %}
<template>
<el-dialog :title="titleMap[mode]" v-model="visible" :width="800" destroy-on-close @closed="$emit('closed')">
<pi-dialog :title="titleMap[mode]" v-model="visible" :width="800" destroy-on-close @closed="$emit('closed')">
<el-form :model="{{ config.model }}" :rules="{{ config.rules }}" :disabled="mode==='show'" ref="{{ config.ref }}"
label-width="{{ config.labelWidth }}" label-position="{{ config.labelPosition }}" size="{{ config.size }}">
{% for field in fields %}
<el-form-item label="{{ field.title }}" prop="{{ field.field_name }}">
{% if field.name == 'text' %}
<el-input v-model="{{ config.model }}.{{ field.field_name }}"{% if field.props.placeholder %} placeholder="{{ field.props.placeholder }}"{% endif %}
{% if field.props.minlength %} :minlength="{{ field.props.minlength }}"{% endif %}{% if field.props.maxlength %} :maxlength="{{ field.props.maxlength }}"{% endif %}
{% if field.props.showWordLimit %} showWordLimit{% endif %}{% if field.props.prefixIcon %} prefixIcon="{{ field.props.prefixIcon }}"{% endif %}
{% if field.props.suffixIcon %} suffixIcon="{{ field.props.suffixIcon }}"{% endif %}{% if field.props.clearable %} clearable{% endif %}
{% if field.props.readonly %} readonly{% endif %}{% if field.props.disabled %} disabled{% endif %}{% if field.width %} style="width: {{ field.width }}"{% endif %}/>
{% endif %}
</el-form-item>
{{ _self.renderField(field, config, _self) -}}
{% endfor %}
</el-form>
<template #footer>
<el-button @click="visible=false">取 消</el-button>
<el-button v-if="mode!=='show'" type="primary" :loading="isSaveing" @click="submit()">保 存</el-button>
</template>
</el-dialog>
</pi-dialog>
</template>
<script setup>
@ -29,7 +167,7 @@
open
})
const emit = defineEmits(['success', 'closed'])
const formRef = ref(null)
const {{ config.ref }} = ref(null)
const {proxy} = getCurrentInstance()
let mode = ref('add')
@ -40,36 +178,28 @@
})
let visible = ref(false)
let isSaveing = ref(false)
let form = ref({
dict_id: null,
dict_name: null,
dict_type: null,
remark: null
let {{ config.model }} = ref({
{{ _self.renderFormDefaults(fields) }}
})
const rules = ref({
dict_name: [
{required: true, message: '请填写字典名称'}
],
dict_type: [
{required: true, message: '请填写字典类型'}
]
{{- _self.renderRules(fields) -}}
})
function open(m = 'add', data = null) {
mode.value = m
visible.value = true
Object.assign(form.value, data)
Object.assign({{ config.model }}.value, data)
}
async function submit() {
// 校验登录
const validate = await formRef.value.validate().catch(() => {
const validate = await {{ config.ref }}.value.validate().catch(() => {
});
if (!validate) {
return false
}
isSaveing.value = true;
const res = form.value.dict_id ? await api.system.dict.edit(form.value) : await api.system.dict.add(form.value);
const res = {{ config.model }}.value.id ? await api.edit({{ config.model }}.value) : await api.add({{ config.model }}.value)
isSaveing.value = false;
emit('success')
visible.value = false;