代码生成器五步向导交互设计

作者:忆笙智云官方 | 发布时间:2026-06-07 14:00 | 更新时间:2026-07-07 14:00

代码生成器五步向导交互设计

引言

代码生成器是低代码平台的核心能力之一,它将数据库表结构转化为可运行的业务代码,大幅减少重复劳动。然而,代码生成器的交互设计直接影响用户体验——步骤过多会让用户迷失,步骤过少则缺乏灵活性。

本文分享一种五步向导式代码生成器交互设计方案:选择数据源 → 选择数据表 → 选择模板集 → 配置字段 → 预览与生成。每一步聚焦一个决策维度,通过自动填充规则减少用户输入,通过在线预览让用户确认结果,最终一键生成高质量的业务代码。

核心内容

一、五步向导整体流程

flowchart LR
    A[步骤一
选择数据源] --> B[步骤二
选择数据表]
    B --> C[步骤三
选择模板集]
    C --> D[步骤四
配置字段]
    D --> E[步骤五
预览与生成]

    style A fill:#4CAF50,color:#fff
    style B fill:#2196F3,color:#fff
    style C fill:#FF9800,color:#fff
    style D fill:#9C27B0,color:#fff
    style E fill:#F44336,color:#fff

二、步骤一:选择数据源

企业级应用通常有多个数据源(主库、从库、业务库等),代码生成器需要支持多数据源切换。

flowchart TB
    A[进入代码生成器] --> B[加载数据源列表]
    B --> C{有数据源?}
    C -->|是| D[展示数据源下拉列表]
    C -->|否| E[引导用户配置数据源]
    D --> F[用户选择数据源]
    F --> G[测试连接]
    G --> H{连接成功?}
    H -->|是| I[进入下一步]
    H -->|否| J[提示连接失败原因]

2.1 数据源选择组件

<template>
  <div class="step-datasource">
    <el-form :model="form" label-width="100px">
      <el-form-item label="数据源">
        <el-select
          v-model="form.datasourceId"
          placeholder="请选择数据源"
          @change="onDatasourceChange"
        >
          <el-option
            v-for="ds in datasourceList"
            :key="ds.id"
            :label="ds.name"
            :value="ds.id"
          >
            <span>{{ ds.name }}</span>
            <el-tag size="small" :type="ds.status ? 'success' : 'danger'">
              {{ ds.status ? '正常' : '异常' }}
            </el-tag>
          </el-option>
        </el-select>
      </el-form-item>

      <!-- 数据源连接信息预览 -->
      <el-descriptions v-if="currentDatasource" :column="2" border>
        <el-descriptions-item label="数据库类型">
          {{ currentDatasource.dbType }}
        </el-descriptions-item>
        <el-descriptions-item label="主机地址">
          {{ currentDatasource.host }}:{{ currentDatasource.port }}
        </el-descriptions-item>
        <el-descriptions-item label="数据库名">
          {{ currentDatasource.database }}
        </el-descriptions-item>
      </el-descriptions>
    </el-form>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'

const form = ref({ datasourceId: null })
const datasourceList = ref([])

const currentDatasource = computed(() =>
  datasourceList.value.find(d => d.id === form.value.datasourceId)
)

const onDatasourceChange = (id) => {
  // 切换数据源时重置后续步骤的数据
  emit('datasource-changed', id)
}
</script>

三、步骤二:选择数据表

选定数据源后,加载该数据源下所有表,支持搜索过滤和批量选择。

flowchart TB
    A[选择数据源完成] --> B[加载表列表]
    B --> C[展示表名+注释+行数]
    C --> D[搜索过滤]
    D --> E[勾选目标表]
    E --> F{选择多表?}
    F -->|单表| G[直接进入下一步]
    F -->|多表| H[展示表关联关系]
    H --> G

3.1 表选择组件

<template>
  <div class="step-table-select">
    <!-- 搜索栏 -->
    <el-input
      v-model="searchKeyword"
      placeholder="搜索表名或注释"
      prefix-icon="Search"
      clearable
    />

    <!-- 表列表 -->
    <el-table
      :data="filteredTables"
      @selection-change="onSelectionChange"
      height="400"
    >
      <el-table-column type="selection" width="50" />
      <el-table-column prop="tableName" label="表名" sortable />
      <el-table-column prop="tableComment" label="表注释" />
      <el-table-column prop="columnCount" label="字段数" width="80" />
      <el-table-column prop="rowCount" label="数据量" width="100" />
    </el-table>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'

const searchKeyword = ref('')
const tableList = ref([])
const selectedTables = ref([])

const filteredTables = computed(() => {
  if (!searchKeyword.value) return tableList.value
  const keyword = searchKeyword.value.toLowerCase()
  return tableList.value.filter(t =>
    t.tableName.toLowerCase().includes(keyword) ||
    t.tableComment.includes(keyword)
  )
})

const onSelectionChange = (selection) => {
  selectedTables.value = selection
}
</script>

四、步骤三:选择模板集

模板集决定了生成代码的技术栈和分层结构。不同业务场景可能需要不同的模板集。

flowchart TB
    A[选择数据表完成] --> B[加载模板集列表]
    B --> C[展示模板集卡片]

    C --> D[单表CRUD模板集]
    C --> E[主子表模板集]
    C --> F[树形结构模板集]

    D --> D1[Controller + Service + Mapper + Vue页面]
    E --> E1[主表CRUD + 子表关联操作]
    F --> F1[树形数据 + 递归查询 + 拖拽排序]

    D1 --> G[用户选择模板集]
    E1 --> G
    F1 --> G

4.1 模板集选择组件

<template>
  <div class="step-template">
    <el-radio-group v-model="selectedTemplateSet">
      <div class="template-cards">
        <el-card
          v-for="tpl in templateSets"
          :key="tpl.id"
          class="template-card"
          :class="{ active: selectedTemplateSet === tpl.id }"
          @click="selectedTemplateSet = tpl.id"
        >
          <template #header>
            <el-radio :value="tpl.id">
              {{ tpl.name }}
            </el-radio>
          </template>
          <p>{{ tpl.description }}</p>
          <div class="template-tags">
            <el-tag v-for="tag in tpl.tags" :key="tag" size="small">
              {{ tag }}
            </el-tag>
          </div>
          <!-- 模板包含的文件预览 -->
          <div class="template-files">
            <span v-for="file in tpl.files" :key="file" class="file-item">
              {{ file }}
            </span>
          </div>
        </el-card>
      </div>
    </el-radio-group>
  </div>
</template>

五、步骤四:配置字段

字段配置是五步向导中最核心也最复杂的步骤。关键设计原则:自动填充为主,手动调整为辅

flowchart TB
    A[选择模板集完成] --> B[读取表字段元数据]
    B --> C[自动填充字段配置]
    C --> D[用户手动调整]
    D --> E[确认配置]

    subgraph 自动填充规则
        C --> C1[Java类型映射]
        C --> C2[字段注释→标签]
        C --> C3[主键字段→必填+只读]
        C --> C4[创建时间→隐藏新增表单]
        C --> C5[逻辑删除→隐藏列表]
        C --> C6[字典类型推断]
    end

    subgraph 用户可调整项
        D --> D1[是否在列表展示]
        D --> D2[是否在表单展示]
        D --> D3[表单控件类型]
        D --> D4[校验规则]
        D --> D5[字典编码]
        D --> D6[查询方式]
    end

5.1 自动填充规则

/**
 * 字段配置自动填充规则
 * 根据数据库字段元数据自动推断生成配置
 */

// 数据库类型 → Java 类型映射
const typeMapping = {
  'bigint':    'Long',
  'int':       'Integer',
  'tinyint':   'Integer',
  'smallint':  'Integer',
  'varchar':   'String',
  'char':      'String',
  'text':      'String',
  'longtext':  'String',
  'datetime':  'LocalDateTime',
  'date':      'LocalDate',
  'decimal':   'BigDecimal',
  'float':     'Double',
  'double':    'Double'
}

/**
 * 自动推断字段配置
 * @param {Object} column 数据库字段元数据
 * @returns {Object} 自动填充的字段配置
 */
function autoFillConfig(column) {
  const config = {
    fieldName: toCamelCase(column.columnName),
    fieldType: typeMapping[column.dataType] || 'String',
    label: column.columnComment || toLabel(column.columnName),
    listShow: true,
    formShow: true,
    formType: inferFormType(column),
    required: column.isNullable === 'NO' && !column.isPrimaryKey,
    queryType: inferQueryType(column),
    dictCode: inferDictCode(column)
  }

  // 特殊字段规则覆盖
  applySpecialRules(config, column)

  return config
}

/**
 * 特殊字段自动规则
 */
function applySpecialRules(config, column) {
  const name = column.columnName.toLowerCase()

  // 主键字段
  if (column.isPrimaryKey) {
    config.listShow = false
    config.formShow = false
    config.required = false
  }

  // 创建/更新时间
  if (['create_time', 'update_time'].includes(name)) {
    config.formShow = false
    config.formType = 'datetime'
  }

  // 逻辑删除字段
  if (['del_flag', 'is_deleted'].includes(name)) {
    config.listShow = false
    config.formShow = false
  }

  // 创建人/更新人
  if (['create_by', 'update_by'].includes(name)) {
    config.formShow = false
  }

  // 备注字段使用文本域
  if (['remark', 'description', 'memo'].includes(name)) {
    config.formType = 'textarea'
  }

  // 状态字段推断为下拉选择
  if (name.endsWith('_status') || name === 'status') {
    config.formType = 'select'
  }
}

/**
 * 推断表单控件类型
 */
function inferFormType(column) {
  const type = column.dataType
  if (type.includes('datetime') || type.includes('timestamp')) return 'datetime'
  if (type.includes('date')) return 'date'
  if (type === 'text' || type === 'longtext') return 'textarea'
  if (type === 'tinyint' && column.columnComment?.includes('是')) return 'switch'
  if (column.columnName.endsWith('_image') || column.columnName.endsWith('_file')) return 'upload'
  return 'input'
}

5.2 字段配置表格

<template>
  <div class="step-field-config">
    <el-table :data="fieldConfigs" border>
      <!-- 字段名 -->
      <el-table-column prop="fieldName" label="字段名" width="140" />

      <!-- 字段标签(可编辑) -->
      <el-table-column label="标签" width="120">
        <template #default="{ row }">
          <el-input v-model="row.label" size="small" />
        </template>
      </el-table-column>

      <!-- Java类型(可编辑) -->
      <el-table-column label="Java类型" width="130">
        <template #default="{ row }">
          <el-select v-model="row.fieldType" size="small">
            <el-option v-for="t in javaTypes" :key="t" :label="t" :value="t" />
          </el-select>
        </template>
      </el-table-column>

      <!-- 表单控件类型 -->
      <el-table-column label="控件类型" width="120">
        <template #default="{ row }">
          <el-select v-model="row.formType" size="small">
            <el-option label="输入框" value="input" />
            <el-option label="文本域" value="textarea" />
            <el-option label="下拉选择" value="select" />
            <el-option label="日期" value="date" />
            <el-option label="日期时间" value="datetime" />
            <el-option label="开关" value="switch" />
            <el-option label="上传" value="upload" />
          </el-select>
        </template>
      </el-table-column>

      <!-- 列表展示 -->
      <el-table-column label="列表" width="60" align="center">
        <template #default="{ row }">
          <el-checkbox v-model="row.listShow" />
        </template>
      </el-table-column>

      <!-- 表单展示 -->
      <el-table-column label="表单" width="60" align="center">
        <template #default="{ row }">
          <el-checkbox v-model="row.formShow" />
        </template>
      </el-table-column>

      <!-- 必填 -->
      <el-table-column label="必填" width="60" align="center">
        <template #default="{ row }">
          <el-checkbox v-model="row.required" />
        </template>
      </el-table-column>

      <!-- 查询方式 -->
      <el-table-column label="查询" width="100">
        <template #default="{ row }">
          <el-select v-model="row.queryType" size="small" clearable>
            <el-option label="精确" value="eq" />
            <el-option label="模糊" value="like" />
            <el-option label="范围" value="between" />
          </el-select>
        </template>
      </el-table-column>

      <!-- 字典编码 -->
      <el-table-column label="字典" width="130">
        <template #default="{ row }">
          <el-select v-model="row.dictCode" size="small" clearable filterable>
            <el-option
              v-for="dict in dictList"
              :key="dict.code"
              :label="dict.name"
              :value="dict.code"
            />
          </el-select>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

六、步骤五:预览与生成

在最终生成前,提供在线代码预览功能,让用户确认生成结果。

flowchart TB
    A[字段配置完成] --> B[提交生成请求]
    B --> C[后端渲染模板]
    C --> D[返回生成结果]

    D --> E[代码预览面板]
    E --> F{用户确认}

    F -->|需要调整| G[返回步骤四修改]
    F -->|确认生成| H[选择生成方式]

    H --> I[下载ZIP包]
    H --> J[直接写入项目目录]

    I --> K[生成完成]
    J --> K

6.1 代码预览组件

<template>
  <div class="step-preview">
    <!-- 文件树 -->
    <div class="file-tree">
      <el-tree
        :data="fileTree"
        :props="{ label: 'name', children: 'children' }"
        @node-click="onFileClick"
      />
    </div>

    <!-- 代码预览区 -->
    <div class="code-preview">
      <div class="file-header">
        <span>{{ currentFile.path }}</span>
        <el-button size="small" @click="copyCode">复制代码</el-button>
      </div>
      <CodeHighlight
        :code="currentFile.content"
        :language="getLanguage(currentFile.path)"
      />
    </div>

    <!-- 底部操作栏 -->
    <div class="actions">
      <el-button @click="prevStep">上一步</el-button>
      <el-button type="primary" @click="downloadZip">下载代码包</el-button>
      <el-button type="success" @click="generateToProject">生成到项目</el-button>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const fileTree = ref([])
const currentFile = ref({ path: '', content: '' })

/** 根据文件扩展名推断语言 */
const getLanguage = (path) => {
  if (path.endsWith('.java')) return 'java'
  if (path.endsWith('.vue')) return 'vue'
  if (path.endsWith('.xml')) return 'xml'
  if (path.endsWith('.sql')) return 'sql'
  if (path.endsWith('.js')) return 'javascript'
  return 'plaintext'
}
</script>

七、向导状态管理

五步向导涉及多个步骤间的数据传递和状态同步,使用 Pinia 统一管理:

/**
 * 代码生成器向导状态管理
 */
import { defineStore } from 'pinia'

export const useGeneratorStore = defineStore('generator', {
  state: () => ({
    currentStep: 0,

    // 步骤一:数据源
    datasourceId: null,

    // 步骤二:数据表
    selectedTables: [],

    // 步骤三:模板集
    templateSetId: null,

    // 步骤四:字段配置
    fieldConfigs: {},  // key: tableName, value: FieldConfig[]

    // 步骤五:预览结果
    previewResult: {}
  }),

  getters: {
    /** 是否可以进入下一步 */
    canNext: (state) => {
      switch (state.currentStep) {
        case 0: return !!state.datasourceId
        case 1: return state.selectedTables.length > 0
        case 2: return !!state.templateSetId
        case 3: return Object.keys(state.fieldConfigs).length > 0
        case 4: return true
        default: return false
      }
    }
  },

  actions: {
    /** 重置向导状态 */
    reset() {
      this.$reset()
    },

    /** 切换数据源时清除后续步骤数据 */
    clearAfterDatasource() {
      this.selectedTables = []
      this.templateSetId = null
      this.fieldConfigs = {}
      this.previewResult = {}
    }
  }
})

八、完整交互流程

sequenceDiagram
    participant U as 用户
    participant W as 向导组件
    participant API as 后端API
    participant DB as 数据库

    U->>W: 进入代码生成器
    W->>API: 获取数据源列表
    API-->>W: 返回数据源列表
    U->>W: 选择数据源
    W->>API: 获取表列表(datasourceId)
    API->>DB: 查询表元数据
    DB-->>API: 表信息
    API-->>W: 返回表列表
    U->>W: 选择数据表
    W->>API: 获取模板集列表
    API-->>W: 返回模板集
    U->>W: 选择模板集
    W->>API: 获取字段配置(tableName)
    API->>DB: 查询字段元数据
    DB-->>API: 字段信息
    API-->>W: 返回自动填充的配置
    U->>W: 调整字段配置
    U->>W: 点击预览
    W->>API: 提交生成预览请求
    API-->>W: 返回生成代码
    U->>W: 确认并下载
    W->>API: 下载代码包
    API-->>U: ZIP文件下载

结论与建议

核心要点

  1. 五步向导降低认知负担:每一步只做一个决策,用户不会迷失在复杂表单中
  2. 自动填充减少手动输入:根据数据库元数据自动推断 80% 以上的配置项
  3. 在线预览提升信心:生成前可预览代码,避免生成后才发现问题
  4. 状态隔离保证数据一致性:切换数据源时自动清除后续步骤数据

最佳实践建议

建议 说明
自动填充优先 能自动推断的配置不要让用户手动填写
支持批量生成 多表同时生成时保持配置一致性
模板可扩展 支持自定义模板集,满足不同项目规范
生成记录可追溯 记录每次生成的配置快照,方便回溯
增量生成 支持只生成变化的文件,避免覆盖手动修改
预览即所见 预览代码与最终生成代码完全一致

相关资源