增加:开发工具->数据重置(手动操作生成表和种子数据)

This commit is contained in:
coolcalf 2025-06-04 20:49:47 +08:00
parent d99c6f1f46
commit e2daef423e
9 changed files with 897 additions and 4 deletions

View File

@ -205,10 +205,11 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
new SysMenu{ Id=1310000000601, Pid=0, Title="开发工具", Path="/develop", Name="develop", Component="Layout", Icon="ele-Cpu", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=13000 },
new SysMenu{ Id=1310000000611, Pid=1310000000601, Title="库表管理", Path="/develop/database", Name="sysDatabase", Component="/system/database/index",Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
new SysMenu{ Id=1310000000621, Pid=1310000000601, Title="代码生成", Path="/develop/codeGen", Name="sysCodeGen", Component="/system/codeGen/index", Icon="ele-Crop", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
new SysMenu{ Id=1310000000631, Pid=1310000000601, Title="表单设计", Path="/develop/formDes", Name="sysFormDes", Component="/system/formDes/index", Icon="ele-Edit", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
new SysMenu{ Id=1310000000641, Pid=1310000000601, Title="系统接口", Path="/develop/api", Name="sysApi", Component="layout/routerView/iframe", IsIframe=true, OutLink="http://localhost:5005", Icon="ele-Help", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
new SysMenu{ Id=1310000000651, Pid=1310000000601, Title="接口压测", Path="/develop/stressTest", Name="sysStressTest", Component="/system/stressTest/index", Icon="ele-Compass", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2024-12-28 00:00:00"), OrderNo=140 },
new SysMenu{ Id=1310000000621, Pid=1310000000601, Title="数据重置", Path="/develop/dataInit", Name="sysDataInit", Component="/system/dataInit/index",Icon="ele-TakeawayBox", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
new SysMenu{ Id=1310000000631, Pid=1310000000601, Title="代码生成", Path="/develop/codeGen", Name="sysCodeGen", Component="/system/codeGen/index", Icon="ele-Crop", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
new SysMenu{ Id=1310000000641, Pid=1310000000601, Title="表单设计", Path="/develop/formDes", Name="sysFormDes", Component="/system/formDes/index", Icon="ele-Edit", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
new SysMenu{ Id=1310000000651, Pid=1310000000601, Title="系统接口", Path="/develop/api", Name="sysApi", Component="layout/routerView/iframe", IsIframe=true, OutLink="http://localhost:5005", Icon="ele-Help", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
new SysMenu{ Id=1310000000661, Pid=1310000000601, Title="接口压测", Path="/develop/stressTest", Name="sysStressTest", Component="/system/stressTest/index", Icon="ele-Compass", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2024-12-28 00:00:00"), OrderNo=140 },
new SysMenu{ Id=1310000000701, Pid=0, Title="帮助文档", Path="/doc", Name="doc", Component="Layout", Icon="ele-Notebook", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=14000 },
new SysMenu{ Id=1310000000711, Pid=1310000000701, Title="框架教程", Path="/doc/admin", Name="sysAdmin", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://adminnet.top/", Icon="ele-Sunny", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },

View File

@ -0,0 +1,14 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
public class DataInitInput
{
public string ConfigId { get; set; }
public List<string> EntityNames { get; set; }
}

View File

@ -0,0 +1,16 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
public class DataInitItemOutput
{
public string Name { get; set; }
public string AssemblyName { get; set; }
public string Description { get; set; }
}

View File

@ -0,0 +1,103 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
namespace Admin.NET.Core.Service;
/// <summary>
/// 系统表和种子数据初始化服务 🧩
/// </summary>
[ApiDescriptionSettings(Order = 250, Description = "系统表和种子数据初始化服务")]
public class SysDataInitService : IDynamicApiController, ITransient
{
private readonly UserManager userManager;
public SysDataInitService(UserManager userManager)
{
this.userManager = userManager;
}
/// <summary>
/// 获取实体类列表 🔖
/// </summary>
/// <returns></returns>
[DisplayName("获取实体类列表")]
public List<DataInitItemOutput> GetClassList(string configId)
{
var totalWatch = Stopwatch.StartNew(); // 开始总计时
Log.Information($"获取实体类列表");
var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false))
.Where(u => !u.GetCustomAttributes<IgnoreTableAttribute>().Any())
//.WhereIF(config.TableSettings.EnableIncreTable, u => u.IsDefined(typeof(IncreTableAttribute), false))
.ToList();
if (configId == SqlSugarConst.MainConfigId) // 默认库(有系统表特性、没有日志表和租户表特性)
entityTypes = entityTypes.Where(u => u.GetCustomAttributes<SysTableAttribute>().Any() || (!u.GetCustomAttributes<LogTableAttribute>().Any() && !u.GetCustomAttributes<TenantAttribute>().Any())).ToList();
else if (configId == SqlSugarConst.LogConfigId) // 日志库
entityTypes = entityTypes.Where(u => u.GetCustomAttributes<LogTableAttribute>().Any()).ToList();
else
entityTypes = entityTypes.Where(u => u.GetCustomAttribute<TenantAttribute>()?.configId.ToString() == configId).ToList(); // 自定义的库
List<DataInitItemOutput> outputList = new List<DataInitItemOutput>();
foreach (var entityType in entityTypes)
{
outputList.Add(new DataInitItemOutput() { Name = entityType.Name, AssemblyName = entityType.Assembly.ManifestModule.Name, Description = entityType.GetCustomAttribute<SugarTable>().TableDescription });
}
return outputList;
}
/// <summary>
/// 获取种子数据列表 🔖
/// </summary>
/// <returns></returns>
[DisplayName("获取种子数据列表")]
public List<DataInitItemOutput> GetSeedDataList(string configId)
{
bool enableIncreSeed = false; // 是否启用增量种子数据TODO
Log.Information($"初始化种子数据");
var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))))
.Where(u => !u.IsDefined(typeof(TenantSeedAttribute), false))
.WhereIF(enableIncreSeed, u => u.IsDefined(typeof(IncreSeedAttribute), false))
.OrderBy(u => u.GetCustomAttributes(typeof(SeedDataAttribute), false).Length > 0 ? ((SeedDataAttribute)u.GetCustomAttributes(typeof(SeedDataAttribute), false)[0]).Order : 0).ToList();
List<DataInitItemOutput> outputList = new List<DataInitItemOutput>();
foreach (var seedDataType in seedDataTypes)
{
var entityType = seedDataType.GetInterfaces().First().GetGenericArguments().First();
outputList.Add(new DataInitItemOutput() { Name = seedDataType.Name, AssemblyName = seedDataType.Assembly.ManifestModule.Name, Description = entityType.GetCustomAttribute<SugarTable>().TableDescription + "种子数据" });
}
return outputList;
}
/// <summary>
/// 初始化表结构 🔖
/// </summary>
/// <param name="input"></param>
[ApiDescriptionSettings(Name = "InitTable"), HttpPost]
[DisplayName("初始化表结构")]
public void InitializeTable(DataInitInput input)
{
if (!userManager.SuperAdmin)
throw Oops.Oh("无权限操作!");
SqlSugarSetup.InitTables(input.ConfigId, input.EntityNames);
}
/// <summary>
/// 初始化种子数据 🔖
/// </summary>
/// <param name="input"></param>
[ApiDescriptionSettings(Name = "InitSeedData"), HttpPost]
[DisplayName("初始化种子数据")]
public void InitializeSeedData(DataInitInput input)
{
if (!userManager.SuperAdmin)
throw Oops.Oh("无权限操作!");
SqlSugarSetup.InitSeedData(input.ConfigId, input.EntityNames);
}
}

View File

@ -703,4 +703,96 @@ public static class SqlSugarSetup
}
}
}
/// <summary>
/// 初始化表结构
/// </summary>
/// <param name="entityNames">实体名称列表</param>
public static void InitTables(string configId, List<string> entityNames)
{
var dbOptions = App.GetConfig<DbConnectionOptions>("DbConnection", true);
var config = dbOptions.ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == configId);
var dbProvider = ITenant.GetConnectionScope(config.ConfigId);
// 初始化表结构之前——系统版本号
var (startups, oldVerion, currentVersion) = BeforeInitTable(dbProvider);
// 初始化表结构
var totalWatch = Stopwatch.StartNew(); // 开始总计时
Log.Information($"初始化表结构 {config.DbType} - {config.ConfigId}");
var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false))
.Where(u => !u.GetCustomAttributes<IgnoreTableAttribute>().Any())
.WhereIF(config.TableSettings.EnableIncreTable, u => u.IsDefined(typeof(IncreTableAttribute), false)).ToList();
entityTypes = entityTypes.Where(u => entityNames.Contains(u.Name)).ToList();
// 删除视图再初始化表结构,防止因为视图导致无法同步表结构
var viewTypeList = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarView)))).ToList();
foreach (var viewType in viewTypeList)
{
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(viewType) ?? throw new Exception("获取视图实体配置有误");
if (dbProvider.DbMaintenance.GetViewInfoList(false).Any(it => it.Name.EqualIgnoreCase(entityInfo.DbTableName)))
dbProvider.DbMaintenance.DropView(entityInfo.DbTableName);
}
int taskIndex = 0, size = entityTypes.Count;
var taskList = entityTypes.Select(entityType => Task.Run(() =>
{
var stopWatch = Stopwatch.StartNew(); // 开始计时
dbProvider.InitTable(entityType); // 初始化表结构
stopWatch.Stop(); // 停止计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化表 {entityType,-64} ({config.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{size:D003}) 耗时:{stopWatch.ElapsedMilliseconds} ms");
}));
Task.WaitAll(taskList.ToArray());
totalWatch.Stop(); // 停止总计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化表结构 {config.DbType} - {config.ConfigId} 总耗时:{totalWatch.ElapsedMilliseconds} ms");
// 初始化种子数据之后——系统版本号
AfterInitSeed(dbProvider, startups, oldVerion, currentVersion);
}
/// <summary>
/// 初始化种子数据
/// </summary>
/// <param name="entityNames">实体名称列表</param>
public static void InitSeedData(string configId, List<string> entityNames)
{
var dbOptions = App.GetConfig<DbConnectionOptions>("DbConnection", true);
var config = dbOptions.ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == configId);
var dbProvider = ITenant.GetConnectionScope(config.ConfigId);
var totalWatch = Stopwatch.StartNew(); // 开始总计时
Log.Information($"初始化种子数据 {dbProvider.CurrentConnectionConfig.DbType} - {dbProvider.CurrentConnectionConfig.ConfigId}");
var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))))
.Where(u => !u.IsDefined(typeof(TenantSeedAttribute), false))
.OrderBy(u => u.GetCustomAttributes(typeof(SeedDataAttribute), false).Length > 0 ? ((SeedDataAttribute)u.GetCustomAttributes(typeof(SeedDataAttribute), false)[0]).Order : 0).ToList();
seedDataTypes = seedDataTypes.Where(u => entityNames.Contains(u.Name)).ToList();
int taskIndex = 0, size = seedDataTypes.Count;
foreach (var seedType in seedDataTypes)
{
var stopWatch = Stopwatch.StartNew(); // 开始计时
// 初始化种子数据
var tuple = dbProvider.InitTableSeedData(seedType);
if (tuple == null) continue;
stopWatch.Stop(); // 停止计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化种子数据 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId} - {Interlocked.Increment(ref taskIndex):D003}/{size:D003},数据量:{tuple.Value.Item1:D003},新增 {tuple.Value.Item2:D003} 条记录,更新 {tuple.Value.Item3:D003} 条记录,耗时:{stopWatch.ElapsedMilliseconds:N0} ms)");
}
totalWatch.Stop(); // 停止总计时
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"初始化种子数据 {dbProvider.CurrentConnectionConfig.DbType} - {dbProvider.CurrentConnectionConfig.ConfigId} 总耗时:{totalWatch.ElapsedMilliseconds:N0} ms");
}
}

View File

@ -0,0 +1,37 @@
import request from '/@/utils/request';
enum Api {
EntityClassList = '/api/sysDataInit/classList',
SeedDataList = '/api/sysDataInit/seedDataList',
InitTable = '/api/sysDataInit/initTable',
InitSeedData = '/api/sysDataInit/initSeedData',
}
// 获取所有实体类
export const getEntityClassList = (params?: any) =>
request({
url: `${Api.EntityClassList}/${params}`,
method: 'get',
});
// 获取所有种子数据
export const getSeedDataList = (params?: any) =>
request({
url: `${Api.SeedDataList}/${params}`,
method: 'get',
});
// 初始化表
export const initTable = (params?: any) =>
request({
url: `${Api.InitTable}`,
method: 'post',
data: params,
});
// 初始化种子数据
export const initSeedData = (params?: any) =>
request({
url: `${Api.InitSeedData}`,
method: 'post',
data: params,
});

View File

@ -0,0 +1,284 @@
<template>
<el-card shadow="hover" :body-style="{ padding: '20px 20px 16px 10px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%" @submit.prevent="handleQuery" >
<el-row :gutter="10">
<el-col class="mb5" :xs="24" :sm="10" :md="10" :lg="10" :xl="10">
<el-form-item label="库名" prop="configId">
<el-select v-model="state.configId" placeholder="库名" filterable @change="handleQueryTable">
<el-option v-for="item in state.dbData" :key="item.configId" :label="`${item.dbName}(${item.configId})`" :value="item.configId" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
<el-row>
<el-col>
<el-button-group>
<el-button type="primary" icon="ele-Search" @click="handleInitTable" :loading="options.loading">
生成表<span v-if="state.selectedRows.length > 0">({{ state.selectedRows.length }})</span>
</el-button>
</el-button-group>
</el-col>
</el-row>
</el-card>
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" v-on="gridEvents">
<template #row_record="{ row }">
<ModifyRecord :data="row" />
</template>
</vxe-grid>
<div style="text-align: right; margin: 7px 8px 7px 0px; color: #666; font-size: 12px;">
{{ xGrid?.getTableData ? xGrid.getTableData().fullData.length : 0 }} 条记录
</div>
</el-card>
</template>
<script lang="ts" setup name="entityList">
import { onMounted, reactive, ref } from 'vue';
import { ElMessageBox, ElMessage } from "element-plus";
import { useUserInfo } from '/@/stores/userInfo';
import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Local } from '/@/utils/storage';
import { formatDate } from '/@/utils/formatTime';
import { getAPI } from '/@/utils/axios-utils';
import { SysDatabaseApi } from '/@/api-services/api';
import { getEntityClassList, initTable } from '/@/api/system/dataInit';
//
const xGrid = ref<VxeGridInstance>();
const userStore = useUserInfo();
const dc = userStore.getDictItemByValue;
const dv = userStore.getDictItemByLabel;
const dl = userStore.getDictDataByCode;
//
const state = reactive({
loading: false,
dbData: [] as any,
configId: '',
showAdvanceQueryUI: false,
queryParams: {
searchKey: undefined,
GroupBy: [] as any,
projectName: undefined,
financingProjectName: undefined,
projectType: undefined,
constructionStatus: undefined,
approvalNumber: undefined,
approvalDate: undefined,
approvalDateRange: undefined,
constructionAddress: undefined,
},
localPageParam: {
pageSize: 50 as number,
defaultSort: { field: 'Id', order: 'asc', descStr: 'desc' },
},
totalSum:[] as any,
visible: false,
title: '',
selectedRows: [] as any[],
});
//
const localPageParamKey = 'localPageParam:entityList';
//
const changeAdvanceQueryUI = () => {
state.showAdvanceQueryUI = !state.showAdvanceQueryUI;
};
//
const checkTableColumnVisible = (tableColumnName: any) => {
return !userStore.userTableList.includes(tableColumnName);
};
//
const options = useVxeTable(
{
id: 'entityList',
name: '项目信息',
columns: [
{ type: 'checkbox', width: 40, fixed: 'left' },
{ type: 'seq', title: '序号', width: 50, fixed: 'left' },
{ field: 'assemblyName', title: '程序集', minWidth: 120, showOverflow: 'tooltip', sortable: false},
{ field: 'name', title: '名称', minWidth: 200, showOverflow: 'tooltip', sortable: false},
{ field: 'description', title: '描述', minWidth: 200, showOverflow: 'tooltip', sortable: false},
// { title: '', fixed: 'right', width: 120, showOverflow: true, slots: { default: 'row_buttons' } },
],
footerMethod: ({ columns, data }) => {
const totalSum=state.totalSum[0];
return [
// columns.map((column, colIndex) => {
// if (colIndex === 0) {
// return ``
// }
// if (column.field === 'estimatedTotalInvestment') {
// //
// return `${data.reduce((sum, row) => sum + (row.estimatedTotalInvestment || 0), 0)}/${totalSum?.estimatedTotalInvestment||0}`
// }
// })
]
},
},
// vxeGrid()vxe-table
{
// //
proxyConfig: { autoLoad: false, ajax: { query: ({ page, sort }) => handleQueryApi(page, sort) } },
//
sortConfig: { defaultSort: Local.get(localPageParamKey)?.defaultSort || state.localPageParam.defaultSort },
//
pagerConfig: { enabled: false },
//
toolbarConfig: { export: false },
//
// rowConfig: { height: 80 },
//
customConfig: {
visibleMethod({ column }) {
return checkTableColumnVisible(`entityList:${column.field}`);
},
},
showFooter: true, //
}
);
//
onMounted(async () => {
options.loading = true;
let res = await getAPI(SysDatabaseApi).apiSysDatabaseListGet();
state.dbData = res.data.result;
// let appNamesRes = await getAPI(SysCodeGenApi).apiSysCodeGenApplicationNamespacesGet();
// state.appNamespaces = appNamesRes.data.result as Array<string>;
options.loading = false;
});
// api
const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, sort: VxeGridPropTypes.ProxyAjaxQuerySortCheckedParams) => {
if (state.configId) {
return getEntityClassList(state.configId);
}
};
//
const handleQuery = async (reset = false) => {
options.loading = true;
reset ? await xGrid.value?.commitProxy('reload') : await xGrid.value?.commitProxy('query');
options.loading = false;
};
const listhandleQuery= async (qparams: any) => {
await handleQuery(true);
};
//
const resetQuery = async () => {
state.queryParams.searchKey = undefined;
state.queryParams.projectName = undefined;
state.queryParams.financingProjectName = undefined;
state.queryParams.projectType = undefined;
state.queryParams.constructionStatus = undefined;
state.queryParams.approvalNumber = undefined;
state.queryParams.approvalDate = undefined;
state.queryParams.constructionAddress = undefined;
await xGrid.value?.commitProxy('reload');
};
//
const gridEvents: VxeGridListeners = {
//
async cellClick({ row, column }) {
listClick(row,column);
},
//
checkboxChange({ records }) {
state.selectedRows = records;
},
// / selectedRows
checkboxAll({ records }) {
state.selectedRows = records;
},
// pager-config
async pageChange({ pageSize }) {
state.localPageParam.pageSize = pageSize;
Local.set(localPageParamKey, state.localPageParam);
},
//
async sortChange({ field, order }) {
state.localPageParam.defaultSort = { field: field, order: order!, descStr: 'desc' };
Local.set(localPageParamKey, state.localPageParam);
},
};
//
const handleQueryTable = async () => {
if (!state.configId) {
xGrid.value?.loadData([]);
return;
}
options.loading = true;
try {
const res = await getEntityClassList(state.configId);
const tableData = res?.data?.result ?? [];
xGrid.value?.loadData(tableData);
} catch (error) {
ElMessage.error('加载实体类列表失败');
xGrid.value?.loadData([]);
} finally {
options.loading = false;
}
};
//
const emits = defineEmits(['list-click']);
const listClick = (row: any,column:any) => {
emits('list-click', row,column);
};
//
const handleInitTable = async () => {
if (!state.configId) {
ElMessage.warning('请先选择库名');
return;
}
if (!state.selectedRows.length) {
ElMessage.warning('请至少选择一个实体');
return;
}
options.loading = true;
try {
const params = {
configId: state.configId,
entityNames: state.selectedRows.map(row => row.name)
};
await initTable(params);
ElMessage.success('生成表操作成功');
} catch (error) {
ElMessage.error('生成表操作失败');
} finally {
options.loading = false;
}
};
//
defineExpose({ listhandleQuery });
</script>
<style lang="scss" scoped>
:deep(.el-input),
:deep(.el-select),
:deep(.el-input-number) {
width: 100%;
}
:deep(.el-slider .el-input-number){
width: auto;
}
</style>

View File

@ -0,0 +1,284 @@
<template>
<el-card shadow="hover" :body-style="{ padding: '20px 20px 16px 10px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%" @submit.prevent="handleQuery" >
<el-row :gutter="10">
<el-col class="mb5" :xs="24" :sm="10" :md="10" :lg="10" :xl="10">
<el-form-item label="库名" prop="configId">
<el-select v-model="state.configId" placeholder="库名" filterable @change="handleQueryTable">
<el-option v-for="item in state.dbData" :key="item.configId" :label="`${item.dbName}(${item.configId})`" :value="item.configId" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
<el-row>
<el-col>
<el-button-group>
<el-button type="primary" icon="ele-Search" @click="handleinitSeedData" :loading="options.loading">
生成数据<span v-if="state.selectedRows.length > 0">({{ state.selectedRows.length }})</span>
</el-button>
</el-button-group>
</el-col>
</el-row>
</el-card>
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" v-on="gridEvents">
<template #row_record="{ row }">
<ModifyRecord :data="row" />
</template>
</vxe-grid>
<div style="text-align: right; margin: 7px 8px 7px 0px; color: #666; font-size: 12px;">
{{ xGrid?.getTableData ? xGrid.getTableData().fullData.length : 0 }} 条记录
</div>
</el-card>
</template>
<script lang="ts" setup name="entityList">
import { onMounted, reactive, ref } from 'vue';
import { ElMessageBox, ElMessage } from "element-plus";
import { useUserInfo } from '/@/stores/userInfo';
import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Local } from '/@/utils/storage';
import { formatDate } from '/@/utils/formatTime';
import { getAPI } from '/@/utils/axios-utils';
import { SysDatabaseApi } from '/@/api-services/api';
import { getSeedDataList, initSeedData } from '/@/api/system/dataInit';
//
const xGrid = ref<VxeGridInstance>();
const userStore = useUserInfo();
const dc = userStore.getDictItemByValue;
const dv = userStore.getDictItemByLabel;
const dl = userStore.getDictDataByCode;
//
const state = reactive({
loading: false,
dbData: [] as any,
configId: '',
showAdvanceQueryUI: false,
queryParams: {
searchKey: undefined,
GroupBy: [] as any,
projectName: undefined,
financingProjectName: undefined,
projectType: undefined,
constructionStatus: undefined,
approvalNumber: undefined,
approvalDate: undefined,
approvalDateRange: undefined,
constructionAddress: undefined,
},
localPageParam: {
pageSize: 50 as number,
defaultSort: { field: 'Id', order: 'asc', descStr: 'desc' },
},
totalSum:[] as any,
visible: false,
title: '',
selectedRows: [] as any[],
});
//
const localPageParamKey = 'localPageParam:entityList';
//
const changeAdvanceQueryUI = () => {
state.showAdvanceQueryUI = !state.showAdvanceQueryUI;
};
//
const checkTableColumnVisible = (tableColumnName: any) => {
return !userStore.userTableList.includes(tableColumnName);
};
//
const options = useVxeTable(
{
id: 'entityList',
name: '项目信息',
columns: [
{ type: 'checkbox', width: 40, fixed: 'left' },
{ type: 'seq', title: '序号', width: 50, fixed: 'left' },
{ field: 'assemblyName', title: '程序集', minWidth: 120, showOverflow: 'tooltip', sortable: false},
{ field: 'name', title: '名称', minWidth: 200, showOverflow: 'tooltip', sortable: false},
{ field: 'description', title: '描述', minWidth: 200, showOverflow: 'tooltip', sortable: false},
// { title: '', fixed: 'right', width: 120, showOverflow: true, slots: { default: 'row_buttons' } },
],
footerMethod: ({ columns, data }) => {
const totalSum=state.totalSum[0];
return [
// columns.map((column, colIndex) => {
// if (colIndex === 0) {
// return ``
// }
// if (column.field === 'estimatedTotalInvestment') {
// //
// return `${data.reduce((sum, row) => sum + (row.estimatedTotalInvestment || 0), 0)}/${totalSum?.estimatedTotalInvestment||0}`
// }
// })
]
},
},
// vxeGrid()vxe-table
{
// //
proxyConfig: { autoLoad: false, ajax: { query: ({ page, sort }) => handleQueryApi(page, sort) } },
//
sortConfig: { defaultSort: Local.get(localPageParamKey)?.defaultSort || state.localPageParam.defaultSort },
//
pagerConfig: { enabled: false },
//
toolbarConfig: { export: false },
//
// rowConfig: { height: 80 },
//
customConfig: {
visibleMethod({ column }) {
return checkTableColumnVisible(`entityList:${column.field}`);
},
},
showFooter: true, //
}
);
//
onMounted(async () => {
options.loading = true;
let res = await getAPI(SysDatabaseApi).apiSysDatabaseListGet();
state.dbData = res.data.result;
// let appNamesRes = await getAPI(SysCodeGenApi).apiSysCodeGenApplicationNamespacesGet();
// state.appNamespaces = appNamesRes.data.result as Array<string>;
options.loading = false;
});
// api
const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, sort: VxeGridPropTypes.ProxyAjaxQuerySortCheckedParams) => {
if (state.configId) {
return getSeedDataList(state.configId);
}
};
//
const handleQuery = async (reset = false) => {
options.loading = true;
reset ? await xGrid.value?.commitProxy('reload') : await xGrid.value?.commitProxy('query');
options.loading = false;
};
const listhandleQuery= async (qparams: any) => {
await handleQuery(true);
};
//
const resetQuery = async () => {
state.queryParams.searchKey = undefined;
state.queryParams.projectName = undefined;
state.queryParams.financingProjectName = undefined;
state.queryParams.projectType = undefined;
state.queryParams.constructionStatus = undefined;
state.queryParams.approvalNumber = undefined;
state.queryParams.approvalDate = undefined;
state.queryParams.constructionAddress = undefined;
await xGrid.value?.commitProxy('reload');
};
//
const gridEvents: VxeGridListeners = {
//
async cellClick({ row, column }) {
listClick(row,column);
},
//
checkboxChange({ records }) {
state.selectedRows = records;
},
// / selectedRows
checkboxAll({ records }) {
state.selectedRows = records;
},
// pager-config
async pageChange({ pageSize }) {
state.localPageParam.pageSize = pageSize;
Local.set(localPageParamKey, state.localPageParam);
},
//
async sortChange({ field, order }) {
state.localPageParam.defaultSort = { field: field, order: order!, descStr: 'desc' };
Local.set(localPageParamKey, state.localPageParam);
},
};
//
const handleQueryTable = async () => {
if (!state.configId) {
xGrid.value?.loadData([]);
return;
}
options.loading = true;
try {
const res = await getSeedDataList(state.configId);
const tableData = res?.data?.result ?? [];
xGrid.value?.loadData(tableData);
} catch (error) {
ElMessage.error('加载实体类列表失败');
xGrid.value?.loadData([]);
} finally {
options.loading = false;
}
};
//
const emits = defineEmits(['list-click']);
const listClick = (row: any,column:any) => {
emits('list-click', row,column);
};
//
const handleinitSeedData = async () => {
if (!state.configId) {
ElMessage.warning('请先选择库名');
return;
}
if (!state.selectedRows.length) {
ElMessage.warning('请至少选择一个实体');
return;
}
options.loading = true;
try {
const params = {
configId: state.configId,
entityNames: state.selectedRows.map(row => row.name)
};
await initSeedData(params);
ElMessage.success('生成种子数据操作成功');
} catch (error) {
ElMessage.error('生成种子数据操作失败');
} finally {
options.loading = false;
}
};
//
defineExpose({ listhandleQuery });
</script>
<style lang="scss" scoped>
:deep(.el-input),
:deep(.el-select),
:deep(.el-input-number) {
width: 100%;
}
:deep(.el-slider .el-input-number){
width: auto;
}
</style>

View File

@ -0,0 +1,62 @@
<template>
<div class="prj-entry-container full-height">
<el-row :gutter="8" style="width: 100%; height: 100%; flex: 1">
<el-col :span="12" :xs="24" class="full-height">
<EntityList ref="EntityListRef"/>
</el-col>
<el-col :span="12" :xs="24" class="full-height">
<SeedDataList ref="SeedDataListRef"/>
</el-col>
</el-row>
</div>
</template>
<script lang="ts" setup name="baseInfo">
import { onMounted, reactive, ref } from 'vue';
import { ElMessageBox, ElMessage } from "element-plus";
import EntityList from '/@/views/system/dataInit/component/entityList.vue';
import SeedDataList from '/@/views/system/dataInit/component/seedDataList.vue';
const EntityListRef = ref<InstanceType<typeof EntityList>>();
const SeedDataListRef = ref<InstanceType<typeof SeedDataList>>();
//
const state = reactive({
queryParams: {
searchKey: undefined,
projectName: undefined,
financingProjectName: undefined,
projectType: undefined,
constructionStatus: undefined,
approvalNumber: undefined,
approvalDate: undefined,
constructionAddress: undefined,
}
});
//
onMounted(() => {
EntityListRef.value?.listhandleQuery(state.queryParams);//
});
</script>
<style lang="scss" scoped>
.prj-entry-container {
height: 100%;
display: flex;
flex-direction: column;
}
.full-height {
display: flex;
flex-direction: column;
height: 100%;
}
:deep(.el-input),
:deep(.el-select),
:deep(.el-input-number) {
width: 100%;
}
:deep(.el-slider .el-input-number){
width: auto;
}
</style>