Files
AgileBoot-Front-End/src/views/system/codegen/components/ConfigForm.vue
2025-09-25 17:55:52 +08:00

322 lines
8.4 KiB
Vue

<script setup lang="ts">
import type { CodegenOptions } from "@/api/system/codegen";
interface Props {
modelValue: CodegenOptions;
dataTypeOptions: Array<{ label: string; value: string }>;
tinyintTransTypeOptions: Array<{ label: string; value: string }>;
timeTransTypeOptions: Array<{ label: string; value: string }>;
nameCaseTypeOptions: Array<{ label: string; value: string }>;
}
interface Emits {
(e: "update:modelValue", value: CodegenOptions): void;
}
const props = defineProps<Props>();
const emits = defineEmits<Emits>();
const updateValue = (key: keyof CodegenOptions, value: any) => {
emits("update:modelValue", {
...props.modelValue,
[key]: value
});
};
// 配置分组
const basicConfig = [
{ key: "dataType", label: "解析引擎", type: "select", options: "dataTypeOptions" },
{ key: "authorName", label: "作者", type: "input" },
{ key: "packageName", label: "包名", type: "input" }
];
const returnConfig = [
{ key: "returnUtilSuccess", label: "成功返回", type: "input" },
{ key: "returnUtilFailure", label: "失败返回", type: "input" },
{ key: "ignorePrefix", label: "忽略前缀", type: "input" }
];
const typeConfig = [
{ key: "tinyintTransType", label: "TinyInt转换", type: "select", options: "tinyintTransTypeOptions" },
{ key: "timeTransType", label: "时间类型", type: "select", options: "timeTransTypeOptions" },
{ key: "nameCaseType", label: "命名类型", type: "select", options: "nameCaseTypeOptions" }
];
const switchConfig = [
{ key: "isPackageType", label: "包装类型" },
{ key: "isSwagger", label: "Swagger UI" },
{ key: "isComment", label: "字段注释" },
{ key: "isAutoImport", label: "自动引包" },
{ key: "isWithPackage", label: "带包路径" },
{ key: "isLombok", label: "Lombok" }
];
</script>
<template>
<div class="config-form">
<!-- 基础配置 -->
<div class="config-section">
<h4 class="section-title">基础配置</h4>
<div class="form-grid">
<el-form-item
v-for="config in basicConfig"
:key="config.key"
:label="config.label"
>
<el-select
v-if="config.type === 'select'"
:model-value="modelValue[config.key]"
class="w-full"
@update:model-value="(val) => updateValue(config.key, val)"
>
<el-option
v-for="option in props[config.options]"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
<el-input
v-else
:model-value="modelValue[config.key]"
@update:model-value="(val) => updateValue(config.key, val)"
/>
</el-form-item>
</div>
</div>
<!-- 返回值配置 -->
<div class="config-section">
<h4 class="section-title">返回值配置</h4>
<div class="form-grid">
<el-form-item
v-for="config in returnConfig"
:key="config.key"
:label="config.label"
>
<el-input
:model-value="modelValue[config.key]"
@update:model-value="(val) => updateValue(config.key, val)"
/>
</el-form-item>
</div>
</div>
<!-- 类型转换配置 -->
<div class="config-section">
<h4 class="section-title">类型转换</h4>
<div class="form-grid">
<el-form-item
v-for="config in typeConfig"
:key="config.key"
:label="config.label"
>
<el-select
:model-value="modelValue[config.key]"
class="w-full"
@update:model-value="(val) => updateValue(config.key, val)"
>
<el-option
v-for="option in props[config.options]"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
</el-form-item>
</div>
</div>
<!-- 开关配置 -->
<div class="config-section">
<h4 class="section-title">功能开关</h4>
<div class="switch-grid">
<el-form-item
v-for="config in switchConfig"
:key="config.key"
:label="config.label"
class="switch-item"
>
<el-switch
:model-value="modelValue[config.key]"
@update:model-value="(val) => updateValue(config.key, val)"
/>
</el-form-item>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.config-form {
.config-section {
margin-bottom: 24px;
&:last-child {
margin-bottom: 0;
}
.section-title {
position: relative;
font-size: 15px;
font-weight: 600;
color: var(--el-color-primary);
margin-bottom: 16px;
padding-left: 12px;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 16px;
background: linear-gradient(135deg, var(--el-color-primary) 0%, var(--el-color-primary-light-3) 100%);
border-radius: 2px;
}
}
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 16px;
:deep(.el-form-item) {
margin-bottom: 0;
background: var(--el-bg-color);
padding: 16px;
border-radius: 8px;
border: 1px solid var(--el-border-color-lighter);
transition: all 0.3s ease;
&:hover {
border-color: var(--el-color-primary-light-5);
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
transform: translateY(-1px);
}
.el-form-item__label {
font-weight: 500;
color: var(--el-text-color-primary);
margin-bottom: 8px;
font-size: 14px;
}
.el-input, .el-select {
.el-input__wrapper {
border-radius: 8px;
transition: all 0.2s ease;
&:hover {
box-shadow: 0 0 0 1px var(--el-color-primary-light-7);
}
&.is-focus {
box-shadow: 0 0 0 1px var(--el-color-primary);
}
}
}
.el-select__wrapper {
border-radius: 8px;
}
}
}
.switch-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 12px;
.switch-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background: linear-gradient(135deg, var(--el-bg-color) 0%, var(--el-bg-color-page) 100%);
border-radius: 8px;
border: 1px solid var(--el-border-color-lighter);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, var(--el-color-primary-light-8) 0%, var(--el-color-primary-light-6) 100%);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.3s ease;
}
&:hover {
border-color: var(--el-color-primary-light-5);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
transform: translateY(-2px);
&::before {
transform: scaleX(1);
}
}
:deep(.el-form-item__label) {
margin-bottom: 0;
font-weight: 500;
color: var(--el-text-color-primary);
font-size: 14px;
}
:deep(.el-form-item__content) {
margin-left: 0;
}
:deep(.el-switch) {
.el-switch__core {
border-radius: 12px;
transition: all 0.2s ease;
&::after {
border-radius: 10px;
}
}
&.is-checked .el-switch__core {
background-color: var(--el-color-primary);
}
}
}
}
}
}
// 响应式设计
@media (max-width: 768px) {
.config-form {
.config-section {
.form-grid {
grid-template-columns: 1fr;
gap: 16px;
:deep(.el-form-item) {
padding: 12px;
}
}
.switch-grid {
grid-template-columns: 1fr;
gap: 10px;
.switch-item {
padding: 10px 14px;
}
}
}
}
}
</style>