Bladeren bron

加入根据表的内容创建SeedData文件的功能

yzp 2 jaren geleden
bovenliggende
commit
00fb2e3367

+ 45 - 0
Admin.NET/Admin.NET.Core/Service/DataBase/Dto/CreateSeedDataInput.cs

@@ -0,0 +1,45 @@
+// 麻省理工学院许可证
+//
+// 版权所有 (c) 2021-2023 zuohuaijun,大名科技(天津)有限公司  联系电话/微信:18020030720  QQ:515096995
+//
+// 特此免费授予获得本软件的任何人以处理本软件的权利,但须遵守以下条件:在所有副本或重要部分的软件中必须包括上述版权声明和本许可声明。
+//
+// 软件按“原样”提供,不提供任何形式的明示或暗示的保证,包括但不限于对适销性、适用性和非侵权的保证。
+// 在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是因合同、侵权或其他方式引起的,与软件或其使用或其他交易有关。
+
+namespace Admin.NET.Core.Service;
+
+public class CreateSeedDataInput
+{
+    /// <summary>
+    /// 表名
+    /// </summary>
+    /// <example>student</example>
+    public string TableName { get; set; }
+    /// <summary>
+    /// SeedData对象名
+    /// </summary>
+    /// <example>Student</example>
+    public string EntityName { get; set; }
+    /// <summary>
+    /// SeedData对象名
+    /// </summary>
+    /// <example>Student</example>
+    public string SeedDataName { get; set; }
+    /// <summary>
+    /// 导出位置
+    /// </summary>
+    /// <example>Web.Application</example>
+    public string Position { get; set; }
+
+    /// <summary>
+    /// 库标识
+    /// </summary>
+    public string ConfigId { get; set; }
+
+    /// <summary>
+    /// 后缀
+    /// </summary>
+    /// <example>Web.Application</example>
+    public string Suffix { get; set; }
+}

+ 202 - 2
Admin.NET/Admin.NET.Core/Service/DataBase/SysDatabaseService.cs

@@ -7,6 +7,8 @@
 // 软件按“原样”提供,不提供任何形式的明示或暗示的保证,包括但不限于对适销性、适用性和非侵权的保证。
 // 在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是因合同、侵权或其他方式引起的,与软件或其使用或其他交易有关。
 
+using Magicodes.ExporterAndImporter.Core.Extension;
+
 namespace Admin.NET.Core.Service;
 
 /// <summary>
@@ -15,6 +17,24 @@ namespace Admin.NET.Core.Service;
 [ApiDescriptionSettings(Order = 250)]
 public class SysDatabaseService : IDynamicApiController, ITransient
 {
+    /// <summary>
+    /// 保存标注了 JsonIgnore 的Property的值信息
+    /// </summary>
+    public class JsonIgnoredPropertyData
+    {
+        /// <summary>
+        /// 对应的记录索引
+        /// </summary>
+        public int RecordIndex { get; set; }
+        /// <summary>
+        /// 属性名
+        /// </summary>
+        public string Name { get; set; }
+        /// <summary>
+        /// 属性值的字符串描述
+        /// </summary>
+        public string Value { get; set; }
+    }
     private readonly ISqlSugarClient _db;
     private readonly IViewEngine _viewEngine;
     private readonly CodeGenOptions _codeGenOptions;
@@ -202,8 +222,8 @@ public class SysDatabaseService : IDynamicApiController, ITransient
         var config = App.GetOptions<DbConnectionOptions>().ConnectionConfigs.FirstOrDefault(u => u.ConfigId == input.ConfigId);
         input.Position = string.IsNullOrWhiteSpace(input.Position) ? "Admin.NET.Application" : input.Position;
         input.EntityName = string.IsNullOrWhiteSpace(input.EntityName) ? (config.DbSettings.EnableUnderLine ? CodeGenUtil.CamelColumnName(input.TableName, null) : input.TableName) : input.EntityName;
-        string[] dbColumnNames = Array.Empty<string>();
-        // 允许创建没有基类的实体
+        string[] dbColumnNames = new string[0];
+        // Entity.cs.vm中是允许创建没有基类的实体的,所以这里也要做出相同的判断
         if (!string.IsNullOrWhiteSpace(input.BaseClassName))
         {
             _codeGenOptions.EntityBaseColumn.TryGetValue(input.BaseClassName, out dbColumnNames);
@@ -237,6 +257,163 @@ public class SysDatabaseService : IDynamicApiController, ITransient
         File.WriteAllText(targetPath, tResult, Encoding.UTF8);
     }
 
+    /// <summary>
+    /// 创建 SeedData
+    /// </summary>
+    /// <param name="input"></param>
+    [ApiDescriptionSettings(Name = "CreateSeedData"), HttpPost]
+    [DisplayName("创建 SeedData")]
+    public async void CreateSeedData(CreateSeedDataInput input)
+    {
+        var config = App.GetOptions<DbConnectionOptions>().ConnectionConfigs.FirstOrDefault(u => u.ConfigId == input.ConfigId);
+        input.Position = string.IsNullOrWhiteSpace(input.Position) ? "Admin.NET.Core" : input.Position;
+
+        var templatePath = GetSeedDataTemplatePath();
+        var db = _db.AsTenant().GetConnectionScope(input.ConfigId);
+        var tableInfo = db.DbMaintenance.GetTableInfoList(false).FirstOrDefault(u => u.Name == input.TableName);//表名
+        List<DbColumnInfo> dbColumnInfos = db.DbMaintenance.GetColumnInfosByTableName(input.TableName, false); //所有字段
+        IEnumerable<EntityInfo> entityInfos = await GetEntityInfos();
+        Type enityType = null;
+        foreach (var item in entityInfos)
+        {
+            if (tableInfo.Name.ToLower() != (config.DbSettings.EnableUnderLine ? UtilMethods.ToUnderLine(item.DbTableName) : item.DbTableName).ToLower()) continue;
+            enityType = item.Type;
+            break;
+        }
+
+        input.EntityName = enityType.Name;
+        input.SeedDataName = enityType.Name + "SeedData";
+        if (!string.IsNullOrWhiteSpace(input.Suffix))
+            input.SeedDataName += input.Suffix;
+        var targetPath = GetSeedDataTargetPath(input);
+
+        // 查询出所有数据
+        var query = db.QueryableByObject(enityType);
+        // 查询有没有合适的排序字段,有的话用来排序,保证SeedData的插入顺序合适
+        DbColumnInfo orderField = null;
+        // 优先用创建时间排序
+        orderField = dbColumnInfos.Where(u => u.DbColumnName.ToLower() == "create_time" || u.DbColumnName.ToLower() == "createtime").FirstOrDefault();
+        if (orderField != null)
+        {
+            query.OrderBy(orderField.DbColumnName);
+        }
+        // 其次用ID排充
+        orderField = dbColumnInfos.Where(u => u.DbColumnName.ToLower() == "id").FirstOrDefault();
+        if (orderField != null)
+        {
+            query.OrderBy(orderField.DbColumnName);
+        }
+        object records = query.ToList();
+        string recordsJSON = Newtonsoft.Json.JsonConvert.SerializeObject(records, Formatting.Indented);
+
+        //检查有没有 System.Text.Json.Serialization.JsonIgnore 的属性
+        var jsonIgnoreProperties = enityType.GetProperties().Where(p => 
+                p.GetAttribute<System.Text.Json.Serialization.JsonIgnoreAttribute>() != null ||
+                p.GetAttribute<Newtonsoft.Json.JsonIgnoreAttribute>() != null
+            ).ToList();
+        List<List<JsonIgnoredPropertyData>> jsonIgnoreInfo = new List<List<JsonIgnoredPropertyData>>();
+        if (jsonIgnoreProperties.Count > 0) {
+            int recordIndex = 0;
+            foreach (var r in (IEnumerable)records)
+            {
+                List<JsonIgnoredPropertyData> record = new List<JsonIgnoredPropertyData>();
+                foreach (var item in jsonIgnoreProperties)
+                {
+                    object v = item.GetValue(r);
+                    string strValue = "null";
+                    if (v != null)
+                    {
+                        strValue = v.ToString();
+                        if (v.GetType() == typeof(string))
+                            strValue = "\"" + strValue + "\"";
+                        else if (v.GetType() == typeof(DateTime))
+                            strValue = "DateTime.Parse(\"" + ((DateTime)v).ToString("yyyy/MM/dd HH:mm:ss") + "\")"; //这个日期方式不知道对不对
+                    }
+                    record.Add(new JsonIgnoredPropertyData { RecordIndex = recordIndex, Name = item.Name, Value = strValue });
+                }
+                recordIndex++;
+                jsonIgnoreInfo.Add(record);
+            }
+        }
+        // 目前为止 jsonIgnoreInfo 中保存了 JsonIgnore 的属性和值的对应关系
+
+        var tContent = File.ReadAllText(templatePath);
+        var data = new
+        {
+            NameSpace = $"{input.Position}.SeedData",
+            EntityNameSpace = enityType.Namespace,
+            input.TableName,
+            input.EntityName,
+            input.SeedDataName,
+            input.ConfigId,
+            tableInfo.Description,
+            JsonIgnoreInfo = jsonIgnoreInfo,
+            RecordsJSON = recordsJSON
+        }; 
+        var tResult = _viewEngine.RunCompile(tContent, data, builderAction: builder =>
+        {
+            builder.AddAssemblyReferenceByName("System.Linq");
+            builder.AddAssemblyReferenceByName("System.Collections");
+            builder.AddUsing("System.Collections.Generic");
+            builder.AddUsing("System.Linq");
+        });
+        File.WriteAllText(targetPath, tResult, Encoding.UTF8);
+    }
+
+    /// <summary>
+    /// 获取库表信息
+    /// </summary>
+    /// <returns></returns>
+    private async Task<IEnumerable<EntityInfo>> GetEntityInfos()
+    {
+        var entityInfos = new List<EntityInfo>();
+
+        var type = typeof(SugarTable);
+        var types = new List<Type>();
+        if (_codeGenOptions.EntityAssemblyNames != null)
+        {
+            foreach (var assemblyName in _codeGenOptions.EntityAssemblyNames)
+            {
+                Assembly asm = Assembly.Load(assemblyName);
+                types.AddRange(asm.GetExportedTypes().ToList());
+            }
+        }
+        bool IsMyAttribute(Attribute[] o)
+        {
+            foreach (Attribute a in o)
+            {
+                if (a.GetType() == type)
+                    return true;
+            }
+            return false;
+        }
+        Type[] cosType = types.Where(o =>
+        {
+            return IsMyAttribute(Attribute.GetCustomAttributes(o, true));
+        }
+        ).ToArray();
+
+        foreach (var c in cosType)
+        {
+            var sugarAttribute = c.GetCustomAttributes(type, true)?.FirstOrDefault();
+
+            var des = c.GetCustomAttributes(typeof(DescriptionAttribute), true);
+            var description = "";
+            if (des.Length > 0)
+            {
+                description = ((DescriptionAttribute)des[0]).Description;
+            }
+            entityInfos.Add(new EntityInfo()
+            {
+                EntityName = c.Name,
+                DbTableName = sugarAttribute == null ? c.Name : ((SugarTable)sugarAttribute).TableName,
+                TableDescription = description,
+                Type = c
+            });
+        }
+        return await Task.FromResult(entityInfos);
+    }
+
     /// <summary>
     /// 获取实体模板文件路径
     /// </summary>
@@ -247,6 +424,16 @@ public class SysDatabaseService : IDynamicApiController, ITransient
         return Path.Combine(templatePath, "Entity.cs.vm");
     }
 
+    /// <summary>
+    /// 获取SeedData模板文件路径
+    /// </summary>
+    /// <returns></returns>
+    private static string GetSeedDataTemplatePath()
+    {
+        var templatePath = Path.Combine(App.WebHostEnvironment.WebRootPath, "Template");
+        return Path.Combine(templatePath, "SeedData.cs.vm");
+    }
+
     /// <summary>
     /// 设置生成实体文件路径
     /// </summary>
@@ -259,4 +446,17 @@ public class SysDatabaseService : IDynamicApiController, ITransient
             Directory.CreateDirectory(backendPath);
         return Path.Combine(backendPath, input.EntityName + ".cs");
     }
+
+    /// <summary>
+    /// 设置生成SeedData文件路径
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    private static string GetSeedDataTargetPath(CreateSeedDataInput input)
+    {
+        var backendPath = Path.Combine(new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.FullName, input.Position, "SeedData");
+        if (!Directory.Exists(backendPath))
+            Directory.CreateDirectory(backendPath);
+        return Path.Combine(backendPath, input.SeedDataName + ".cs");
+    }
 }

+ 39 - 0
Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/SeedData.cs.vm

@@ -0,0 +1,39 @@
+using Admin.NET.Core;
+using @Model.EntityNameSpace;
+
+namespace @Model.NameSpace;
+
+/// <summary>
+/// @(Model.Description) 表种子数据
+/// </summary>
+public class @(Model.SeedDataName): ISqlSugarEntitySeedData<@(Model.EntityName)>
+{
+    /// <summary>
+    /// 种子数据
+    /// </summary>
+    /// <returns></returns>
+    public IEnumerable<@(Model.EntityName)> HasData()
+    {
+        string recordsJSON = @@"
+            @(Model.RecordsJSON.Replace("\"","\"\"").Replace("\n", "\n\t\t\t"))
+        ";
+        List<@(Model.EntityName)> records = Newtonsoft.Json.JsonConvert.DeserializeObject<List<@(Model.EntityName)>>(recordsJSON);
+        @if (Model.JsonIgnoreInfo.Count>0) {
+        @:
+        @:#region 处理 JsonIgnore 的Property
+        @:
+            @foreach (var jii in Model.JsonIgnoreInfo){
+                @foreach (var j in jii){
+        @:records[@j.RecordIndex].@(j.Name) = @(j.Value);
+                }
+                @:
+            }
+        @:#endregion
+        }
+        
+        // 后处理数据的特殊字段
+		//for (int i = 0; i < records.Count; i++) { }
+
+        return records;
+    }
+}

+ 74 - 0
Web/src/api-services/apis/sys-database-api.ts

@@ -20,6 +20,7 @@ import { AdminResultListDbColumnOutput } from '../models';
 import { AdminResultListDbTableInfo } from '../models';
 import { AdminResultListObject } from '../models';
 import { CreateEntityInput } from '../models';
+import { CreateSeedDataInput } from '../models';
 import { DbColumnInput } from '../models';
 import { DbTableInput } from '../models';
 import { DeleteDbColumnInput } from '../models';
@@ -231,6 +232,54 @@ export const SysDatabaseApiAxiosParamCreator = function (configuration?: Configu
                 options: localVarRequestOptions,
             };
         },
+        /**
+         * 
+         * @summary 创建实体
+         * @param {CreateEntityInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysDatabaseCreateSeedDataPost: async (body?: CreateEntityInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysDatabase/createSeedData`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
         /**
          * 
          * @summary 删除列
@@ -581,6 +630,20 @@ export const SysDatabaseApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 
+         * @summary 创建 SeedData
+         * @param {CreateSeedDataInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysDatabaseCreateSeedDataPost(body?: CreateSeedDataInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysDatabaseApiAxiosParamCreator(configuration).apiSysDatabaseCreateSeedDataPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
          * 
          * @summary 删除列
@@ -828,6 +891,17 @@ export class SysDatabaseApi extends BaseAPI {
     public async apiSysDatabaseCreateEntityPost(body?: CreateEntityInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
         return SysDatabaseApiFp(this.configuration).apiSysDatabaseCreateEntityPost(body, options).then((request) => request(this.axios, this.basePath));
     }
+    /**
+     * 
+     * @summary 创建 SeedData
+     * @param {CreateSeedDataInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysDatabaseApi
+     */
+    public async apiSysDatabaseCreateSeedDataPost(body?: CreateSeedDataInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysDatabaseApiFp(this.configuration).apiSysDatabaseCreateSeedDataPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
     /**
      * 
      * @summary 删除列

+ 44 - 0
Web/src/api-services/models/create-seed-data-input.ts

@@ -0,0 +1,44 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET
+ * 让 .NET 开发更简单、更通用、更流行。前后端分离架构(.NET6/Vue3),开箱即用紧随前沿技术。<br/><a href='https://gitee.com/zuohuaijun/Admin.NET/'>https://gitee.com/zuohuaijun/Admin.NET</a>
+ *
+ * OpenAPI spec version: 1.0.0
+ * Contact: 515096995@qq.com
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+/**
+ * 
+ * @export
+ * @interface CreateSeedDataInput
+ */
+export interface CreateSeedDataInput {
+    /**
+     * 表名
+     * @type {string}
+     * @memberof CreateEntityInput
+     */
+    tableName?: string | null;
+    /**
+     * 导出位置
+     * @type {string}
+     * @memberof CreateEntityInput
+     */
+    position?: string | null;
+    /**
+     * 库标识
+     * @type {string}
+     * @memberof CreateEntityInput
+     */
+    configId?: string | null;
+    /**
+     * 后缀
+     * @type {string}
+     * @memberof CreateEntityInput
+     */
+    suffix?: string | null;
+}

+ 1 - 0
Web/src/api-services/models/index.ts

@@ -90,6 +90,7 @@ export * from './code-gen-input';
 export * from './column-ouput';
 export * from './const-output';
 export * from './create-entity-input';
+export * from './create-seed-data-input';
 export * from './culture-level-enum';
 export * from './data-item';
 export * from './data-scope-enum';

+ 90 - 0
Web/src/views/system/database/component/genSeedData.vue

@@ -0,0 +1,90 @@
+<template>
+	<div class="sys-dbEntity-container">
+		<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="700px">
+			<template #header>
+				<div style="color: #fff">
+					<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Cpu /> </el-icon>
+					<span> 生成SeedData </span>
+				</div>
+			</template>
+			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
+				<el-row :gutter="35">
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="表名" prop="tableName" :rules="[{ required: true, message: '表名不能为空', trigger: 'blur' }]">
+							<el-input disabled v-model="state.ruleForm.tableName" placeholder="表名" clearable />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="后缀" prop="suffix">
+							<el-input v-model="state.ruleForm.suffix" placeholder="后缀" clearable />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="存放位置" prop="position">
+							<el-input v-model="state.ruleForm.position" placeholder="存放位置" clearable >Admin.NET.Core</el-input>
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button @click="cancel">取 消</el-button>
+					<el-button type="primary" @click="submit">确 定</el-button>
+				</span>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+
+<script lang="ts" setup name="sysGenEntity">
+import { onMounted, reactive, ref } from 'vue';
+
+import { getAPI } from '/@/utils/axios-utils';
+import { SysDatabaseApi, SysDictTypeApi } from '/@/api-services/api';
+
+const emits = defineEmits(['handleQueryColumn']);
+const ruleFormRef = ref();
+const state = reactive({
+	isShowDialog: false,
+	ruleForm: {} as any,
+	codeGenBaseClassName: [] as any,
+});
+
+onMounted(async () => {
+	let resDicData = await getAPI(SysDictTypeApi).apiSysDictTypeDataListGet('code_gen_base_class');
+	state.codeGenBaseClassName = resDicData.data.result;
+});
+
+// 打开弹窗
+const openDialog = (row: any) => {
+	state.ruleForm.configId = row.configId;
+	state.ruleForm.tableName = row.tableName;
+	//state.ruleForm.position = 'Admin.NET.Core';
+	if (state.ruleForm.position == undefined)
+		state.ruleForm.position = 'Admin.NET.Core';
+	state.isShowDialog = true;
+};
+
+// 关闭弹窗
+const closeDialog = () => {
+	emits('handleQueryColumn');
+	state.isShowDialog = false;
+};
+
+// 取消
+const cancel = () => {
+	state.isShowDialog = false;
+};
+
+// 提交
+const submit = () => {
+	ruleFormRef.value.validate(async (valid: boolean) => {
+		if (!valid) return;
+		await getAPI(SysDatabaseApi).apiSysDatabaseCreateSeedDataPost(state.ruleForm);
+		closeDialog();
+	});
+};
+
+// 导出对象
+defineExpose({ openDialog });
+</script>

+ 14 - 0
Web/src/views/system/database/index.vue

@@ -18,6 +18,7 @@
 					<el-button icon="ele-Plus" @click="openAddTable"> 增加表 </el-button>
 					<el-button icon="ele-Plus" @click="openAddColumn"> 增加列 </el-button>
 					<el-button icon="ele-Plus" @click="openGenDialog"> 生成实体 </el-button>
+					<el-button icon="ele-Plus" @click="openGenSeedDataDialog"> 生成SeedData </el-button>
 				</el-form-item>
 			</el-form>
 		</el-card>
@@ -63,6 +64,7 @@
 		<AddTable ref="addTableRef" @addTableSubmitted="addTableSubmitted" />
 		<AddColumn ref="addColumnRef" @handleQueryColumn="handleQueryColumn" />
 		<GenEntity ref="genEntityRef" @handleQueryColumn="handleQueryColumn" />
+		<GenSeedData ref="genSeedDataRef" />
 	</div>
 </template>
 
@@ -74,6 +76,7 @@ import EditColumn from '/@/views/system/database/component/editColumn.vue';
 import AddTable from '/@/views/system/database/component/addTable.vue';
 import AddColumn from '/@/views/system/database/component/addColumn.vue';
 import GenEntity from '/@/views/system/database/component/genEntity.vue';
+import GenSeedData from '/@/views/system/database/component/genSeedData.vue';
 
 import { getAPI } from '/@/utils/axios-utils';
 import { SysDatabaseApi } from '/@/api-services/api';
@@ -84,6 +87,7 @@ const editColumnRef = ref<InstanceType<typeof EditColumn>>();
 const addTableRef = ref<InstanceType<typeof AddTable>>();
 const addColumnRef = ref<InstanceType<typeof AddColumn>>();
 const genEntityRef = ref<InstanceType<typeof GenEntity>>();
+const genSeedDataRef = ref<InstanceType<typeof GenSeedData>>();
 const state = reactive({
 	loading: false,
 	loading1: false,
@@ -161,6 +165,16 @@ const openGenDialog = () => {
 	genEntityRef.value?.openDialog(table);
 };
 
+// 生成seedData页面
+const openGenSeedDataDialog = () => {
+	if (state.configId == '' || state.tableName == '') return;
+	var table: any = {
+		configId: state.configId,
+		tableName: state.tableName,
+	};
+	genSeedDataRef.value?.openDialog(table);
+};
+
 // 打开表增加页面
 const openAddTable = () => {
 	if (state.configId == '') {