2·1
This commit is contained in:
parent
932eae46ad
commit
7cbea2a3ef
|
|
@ -6,6 +6,14 @@ import Http from "@/core/utils/Http";
|
||||||
export default class CodeGenerationService {
|
export default class CodeGenerationService {
|
||||||
static urlPrefix = "/api/v1/admin/CodeGeneration";
|
static urlPrefix = "/api/v1/admin/CodeGeneration";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据库列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
static getDatabases() {
|
||||||
|
return Http.get(`${this.urlPrefix}/GetDatabases`);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取数据列表
|
* 获取数据列表
|
||||||
* @param current
|
* @param current
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ const state = reactive({
|
||||||
tableName: undefined,
|
tableName: undefined,
|
||||||
entityName: undefined,
|
entityName: undefined,
|
||||||
displayName: undefined,
|
displayName: undefined,
|
||||||
|
dataBase: undefined,
|
||||||
},
|
},
|
||||||
sort: [] as any[],
|
sort: [] as any[],
|
||||||
},
|
},
|
||||||
|
|
@ -28,6 +29,7 @@ const state = reactive({
|
||||||
total: 100,
|
total: 100,
|
||||||
columns: [] as any,
|
columns: [] as any,
|
||||||
data: [] as any,
|
data: [] as any,
|
||||||
|
databaseList: [] as any,
|
||||||
});
|
});
|
||||||
|
|
||||||
//表格
|
//表格
|
||||||
|
|
@ -43,9 +45,47 @@ const refTableEditor = ref<InstanceType<typeof TableEditor>>();
|
||||||
* 初始化
|
* 初始化
|
||||||
*/
|
*/
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
loadDatabases();
|
||||||
findList();
|
findList();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载数据库列表
|
||||||
|
*/
|
||||||
|
async function loadDatabases() {
|
||||||
|
const result = await CodeGenerationService.getDatabases();
|
||||||
|
if (result.code != 200) return;
|
||||||
|
state.databaseList = result.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库切换事件
|
||||||
|
*/
|
||||||
|
function handleDatabaseChange() {
|
||||||
|
state.page = 1;
|
||||||
|
findList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据库颜色
|
||||||
|
*/
|
||||||
|
function getDatabaseColor(dataBaseKey: string): string {
|
||||||
|
const colorMap: Record<string, string> = {
|
||||||
|
'Admin': 'blue',
|
||||||
|
'MiaoYuChat': 'green',
|
||||||
|
'LiveForum': 'orange'
|
||||||
|
};
|
||||||
|
return colorMap[dataBaseKey] || 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据库显示名称
|
||||||
|
*/
|
||||||
|
function getDatabaseDisplayName(dataBaseKey: string): string {
|
||||||
|
const db = state.databaseList.find((d: any) => d.key === dataBaseKey);
|
||||||
|
return db?.displayName || dataBaseKey;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*获取数据
|
*获取数据
|
||||||
*/
|
*/
|
||||||
|
|
@ -139,6 +179,24 @@ function openTableEditor() {
|
||||||
<template #search>
|
<template #search>
|
||||||
<a-form ref="refSearchForm" :model="state.search.vm">
|
<a-form ref="refSearchForm" :model="state.search.vm">
|
||||||
<a-row :gutter="[16, 0]">
|
<a-row :gutter="[16, 0]">
|
||||||
|
<a-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||||
|
<a-form-item class="mb-0" name="dataBase" label="数据库">
|
||||||
|
<a-select
|
||||||
|
v-model:value="state.search.vm.dataBase"
|
||||||
|
placeholder="全部数据库"
|
||||||
|
@change="handleDatabaseChange"
|
||||||
|
>
|
||||||
|
<a-select-option value="">全部数据库</a-select-option>
|
||||||
|
<a-select-option
|
||||||
|
v-for="db in state.databaseList"
|
||||||
|
:key="db.key"
|
||||||
|
:value="db.key"
|
||||||
|
>
|
||||||
|
{{ db.displayName }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
<a-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||||
<a-form-item class="mb-0" name="tableName" label="表名称">
|
<a-form-item class="mb-0" name="tableName" label="表名称">
|
||||||
<a-input v-model:value="state.search.vm.tableName" placeholder="表名称" />
|
<a-input v-model:value="state.search.vm.tableName" placeholder="表名称" />
|
||||||
|
|
@ -228,6 +286,13 @@ function openTableEditor() {
|
||||||
<template #toolbar-right> </template>
|
<template #toolbar-right> </template>
|
||||||
<!-- table-col -->
|
<!-- table-col -->
|
||||||
<template #table-col>
|
<template #table-col>
|
||||||
|
<a-table-column title="数据库" data-index="dataBase" width="120px">
|
||||||
|
<template #default="{ record }">
|
||||||
|
<a-tag :color="getDatabaseColor(record.dataBase)">
|
||||||
|
{{ getDatabaseDisplayName(record.dataBase) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
<a-table-column title="表名称" data-index="tableName" />
|
<a-table-column title="表名称" data-index="tableName" />
|
||||||
<a-table-column title="显示名称" data-index="displayName">
|
<a-table-column title="显示名称" data-index="displayName">
|
||||||
<template #default="{ record }"> <a-input v-model:value="record.displayName" /></template>
|
<template #default="{ record }"> <a-input v-model:value="record.displayName" /></template>
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ async function getCode() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const result = await CodeGenerationService.getCode({
|
const result = await CodeGenerationService.getCode({
|
||||||
tableName: props.rowData.tableName,
|
tableName: props.rowData.tableName,
|
||||||
|
dataBase: props.rowData.dataBase,
|
||||||
type: codeType.value,
|
type: codeType.value,
|
||||||
codeText: "",
|
codeText: "",
|
||||||
});
|
});
|
||||||
|
|
@ -88,6 +89,7 @@ async function getCode() {
|
||||||
function download() {
|
function download() {
|
||||||
CodeGenerationService.download({
|
CodeGenerationService.download({
|
||||||
tableName: props.rowData.tableName,
|
tableName: props.rowData.tableName,
|
||||||
|
dataBase: props.rowData.dataBase,
|
||||||
type: codeType.value,
|
type: codeType.value,
|
||||||
codeText: "",
|
codeText: "",
|
||||||
});
|
});
|
||||||
|
|
@ -99,6 +101,7 @@ function download() {
|
||||||
function downloadAll() {
|
function downloadAll() {
|
||||||
CodeGenerationService.download({
|
CodeGenerationService.download({
|
||||||
tableName: props.rowData.tableName,
|
tableName: props.rowData.tableName,
|
||||||
|
dataBase: props.rowData.dataBase,
|
||||||
type: codeType.value,
|
type: codeType.value,
|
||||||
codeText: "",
|
codeText: "",
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,10 @@ function saveForm(successCallBack: Function | null = null) {
|
||||||
function autoImport() {
|
function autoImport() {
|
||||||
saveForm(async () => {
|
saveForm(async () => {
|
||||||
state.loading = true;
|
state.loading = true;
|
||||||
const result = await CodeGenerationService.autoImprotProject({ tableName: props.rowData.tableName });
|
const result = await CodeGenerationService.autoImprotProject({
|
||||||
|
tableName: props.rowData.tableName,
|
||||||
|
dataBase: props.rowData.dataBase
|
||||||
|
});
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
if (result.code !== 1) return;
|
if (result.code !== 1) return;
|
||||||
Tools.message.success("代码载入项目成功!");
|
Tools.message.success("代码载入项目成功!");
|
||||||
|
|
|
||||||
591
admin-client/前端接口对接文档.md
Normal file
591
admin-client/前端接口对接文档.md
Normal file
|
|
@ -0,0 +1,591 @@
|
||||||
|
# 低代码生成平台 - 前端接口对接文档
|
||||||
|
|
||||||
|
## 📋 更新概述
|
||||||
|
|
||||||
|
本次后端更新新增了数据库选择功能,支持按数据库筛选表列表。前端需要相应修改以支持以下功能:
|
||||||
|
|
||||||
|
1. **新增接口**:获取数据库列表
|
||||||
|
2. **增强接口**:表列表接口支持按数据库筛选
|
||||||
|
3. **返回数据变更**:表列表返回数据新增 `dataBase` 字段
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🆕 1. 新增接口:获取数据库列表
|
||||||
|
|
||||||
|
### 接口信息
|
||||||
|
|
||||||
|
- **请求路径**:`GET /api/CodeGeneration/databases`
|
||||||
|
- **请求方法**:`GET`
|
||||||
|
- **是否需要认证**:是
|
||||||
|
- **描述**:获取所有可用的数据库列表,用于前端下拉框选择
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
|
||||||
|
无
|
||||||
|
|
||||||
|
### 响应示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"key": "Admin",
|
||||||
|
"displayName": "主数据库"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MiaoYuChat",
|
||||||
|
"displayName": "喵语聊天"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "LiveForum",
|
||||||
|
"displayName": "论坛系统"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 响应字段说明
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| key | string | 数据库标识,用于后续接口传参 |
|
||||||
|
| displayName | string | 显示名称,用于前端展示 |
|
||||||
|
|
||||||
|
### 前端使用示例
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 1. 定义接口类型
|
||||||
|
interface DataSource {
|
||||||
|
key: string;
|
||||||
|
displayName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 调用接口
|
||||||
|
const getDatabases = async (): Promise<DataSource[]> => {
|
||||||
|
const response = await axios.get('/api/CodeGeneration/databases');
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 3. 使用示例(页面加载时)
|
||||||
|
onMounted(async () => {
|
||||||
|
const databases = await getDatabases();
|
||||||
|
// 填充到下拉框
|
||||||
|
databaseOptions.value = databases;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ 2. 修改接口:表列表查询
|
||||||
|
|
||||||
|
### 接口信息
|
||||||
|
|
||||||
|
- **请求路径**:`POST /api/CodeGeneration/{size}/{page}`
|
||||||
|
- **请求方法**:`POST`
|
||||||
|
- **是否需要认证**:是
|
||||||
|
- **描述**:获取表列表,支持按表名和数据库筛选
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
|
||||||
|
**路径参数:**
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 说明 |
|
||||||
|
|--------|------|------|------|
|
||||||
|
| size | number | 是 | 每页条数 |
|
||||||
|
| page | number | 是 | 页码 |
|
||||||
|
|
||||||
|
**Body 参数(JSON):**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tableName": "User", // 可选,表名模糊搜索
|
||||||
|
"dataBase": "Admin" // 🆕 新增,数据库标识筛选
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 请求字段说明
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 必填 | 说明 |
|
||||||
|
|--------|------|------|------|
|
||||||
|
| tableName | string | 否 | 表名,支持模糊搜索 |
|
||||||
|
| dataBase | string | 否 | 🆕 数据库标识,不传则返回所有数据库的表 |
|
||||||
|
|
||||||
|
### 响应示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"total": 25,
|
||||||
|
"page": 1,
|
||||||
|
"size": 10,
|
||||||
|
"pageCount": 3,
|
||||||
|
"dataSource": [
|
||||||
|
{
|
||||||
|
"tableName": "Users",
|
||||||
|
"remark": "用户表",
|
||||||
|
"dataBase": "Admin" // 🆕 新增字段
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "T_Image_Config",
|
||||||
|
"remark": "图片配置表",
|
||||||
|
"dataBase": "MiaoYuChat" // 🆕 新增字段
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 响应字段说明
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| tableName | string | 表名 |
|
||||||
|
| remark | string | 表备注/描述 |
|
||||||
|
| dataBase | string | 🆕 表所属的数据库标识 |
|
||||||
|
|
||||||
|
### 前端使用示例
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 1. 定义接口类型
|
||||||
|
interface TableListItem {
|
||||||
|
tableName: string;
|
||||||
|
remark: string;
|
||||||
|
dataBase: string; // 🆕 新增字段
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TableListRequest {
|
||||||
|
tableName?: string;
|
||||||
|
dataBase?: string; // 🆕 新增字段
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 调用接口
|
||||||
|
const getTableList = async (
|
||||||
|
page: number,
|
||||||
|
size: number,
|
||||||
|
search: TableListRequest
|
||||||
|
): Promise<PagingResult<TableListItem>> => {
|
||||||
|
const response = await axios.post(
|
||||||
|
`/api/CodeGeneration/${size}/${page}`,
|
||||||
|
search
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 3. 使用示例(带数据库筛选)
|
||||||
|
const loadTableList = async () => {
|
||||||
|
const result = await getTableList(1, 10, {
|
||||||
|
tableName: searchKeyword.value,
|
||||||
|
dataBase: selectedDatabase.value // 🆕 传递选中的数据库
|
||||||
|
});
|
||||||
|
tableList.value = result.dataSource;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 3. 代码生成接口参数调整
|
||||||
|
|
||||||
|
### 影响的接口
|
||||||
|
|
||||||
|
以下接口在调用时,需要确保 `dataBase` 参数正确传递:
|
||||||
|
|
||||||
|
1. **获取代码**:`POST /api/CodeGeneration/GetCodeAsync`
|
||||||
|
2. **下载代码**:`POST /api/CodeGeneration/DownloadAsync`
|
||||||
|
3. **下载所有代码**:`POST /api/CodeGeneration/DownloadAllAsync`
|
||||||
|
4. **自动导入项目**:`POST /api/CodeGeneration/AutoImprotProjectAsync`
|
||||||
|
|
||||||
|
### 请求 Body 示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tableName": "T_Image_Config",
|
||||||
|
"dataBase": "MiaoYuChat", // ⚠️ 必须传递,确保准确匹配表
|
||||||
|
"type": "MiaoYu.Models"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前端使用示例
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 生成代码时,从表列表中获取 dataBase 并传递
|
||||||
|
const generateCode = async (table: TableListItem, type: string) => {
|
||||||
|
const response = await axios.post('/api/CodeGeneration/GetCodeAsync', {
|
||||||
|
tableName: table.tableName,
|
||||||
|
dataBase: table.dataBase, // 🆕 必须传递
|
||||||
|
type: type
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 4. 前端需要修改的地方
|
||||||
|
|
||||||
|
### 4.1 页面布局调整
|
||||||
|
|
||||||
|
在表列表页面顶部新增数据库选择器:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div class="code-generation-page">
|
||||||
|
<!-- 🆕 新增:数据库选择器 -->
|
||||||
|
<div class="filter-section">
|
||||||
|
<a-select
|
||||||
|
v-model:value="selectedDatabase"
|
||||||
|
placeholder="选择数据库"
|
||||||
|
style="width: 200px"
|
||||||
|
@change="handleDatabaseChange"
|
||||||
|
>
|
||||||
|
<a-select-option value="">全部数据库</a-select-option>
|
||||||
|
<a-select-option
|
||||||
|
v-for="db in databaseList"
|
||||||
|
:key="db.key"
|
||||||
|
:value="db.key"
|
||||||
|
>
|
||||||
|
{{ db.displayName }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
|
||||||
|
<!-- 原有的搜索框 -->
|
||||||
|
<a-input
|
||||||
|
v-model:value="searchKeyword"
|
||||||
|
placeholder="搜索表名"
|
||||||
|
style="width: 300px; margin-left: 10px"
|
||||||
|
@change="handleSearch"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 表格列表 -->
|
||||||
|
<a-table :columns="columns" :data-source="tableList">
|
||||||
|
<!-- 🆕 新增:显示数据库标识列 -->
|
||||||
|
<a-table-column key="dataBase" title="数据库" data-index="dataBase" />
|
||||||
|
<a-table-column key="tableName" title="表名" data-index="tableName" />
|
||||||
|
<a-table-column key="remark" title="说明" data-index="remark" />
|
||||||
|
<!-- 其他列... -->
|
||||||
|
</a-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 状态管理
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
|
||||||
|
// 🆕 新增状态
|
||||||
|
const databaseList = ref<DataSource[]>([]);
|
||||||
|
const selectedDatabase = ref<string>(''); // 空字符串表示全部
|
||||||
|
|
||||||
|
// 原有状态
|
||||||
|
const tableList = ref<TableListItem[]>([]);
|
||||||
|
const searchKeyword = ref<string>('');
|
||||||
|
|
||||||
|
// 🆕 页面加载时获取数据库列表
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadDatabases();
|
||||||
|
await loadTableList();
|
||||||
|
});
|
||||||
|
|
||||||
|
const loadDatabases = async () => {
|
||||||
|
databaseList.value = await getDatabases();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 🆕 数据库切换事件
|
||||||
|
const handleDatabaseChange = () => {
|
||||||
|
loadTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 修改:加载表列表时传递数据库参数
|
||||||
|
const loadTableList = async () => {
|
||||||
|
const result = await getTableList(1, 10, {
|
||||||
|
tableName: searchKeyword.value,
|
||||||
|
dataBase: selectedDatabase.value // 🆕 传递数据库参数
|
||||||
|
});
|
||||||
|
tableList.value = result.dataSource;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 生成代码时传递数据库
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ⚠️ 重要:生成代码时必须传递 dataBase
|
||||||
|
const handleGenerateCode = async (record: TableListItem) => {
|
||||||
|
const code = await generateCode({
|
||||||
|
tableName: record.tableName,
|
||||||
|
dataBase: record.dataBase, // 🆕 从表列表记录中获取
|
||||||
|
type: selectedCodeType.value
|
||||||
|
});
|
||||||
|
// 展示生成的代码...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 5. 注意事项
|
||||||
|
|
||||||
|
### 5.1 兼容性说明
|
||||||
|
|
||||||
|
- **向后兼容**:`dataBase` 字段为可选,不传时返回所有数据库的表(保持原有行为)
|
||||||
|
- **推荐实践**:建议前端始终传递 `dataBase` 参数,避免同名表冲突
|
||||||
|
|
||||||
|
### 5.2 同名表处理
|
||||||
|
|
||||||
|
后端支持不同数据库中存在同名表,因此:
|
||||||
|
|
||||||
|
- 表列表中可能出现多个同名的表,通过 `dataBase` 字段区分
|
||||||
|
- 生成代码时**必须**传递 `dataBase` 参数,确保操作正确的表
|
||||||
|
|
||||||
|
### 5.3 UI/UX 建议
|
||||||
|
|
||||||
|
1. **数据库标识显示**:
|
||||||
|
- 在表名前添加数据库标签,如 `[Admin] Users`、`[MiaoYuChat] T_Image_Config`
|
||||||
|
- 使用不同颜色或图标区分不同数据库
|
||||||
|
|
||||||
|
2. **默认选择**:
|
||||||
|
- 建议默认选择第一个数据库,而不是"全部"
|
||||||
|
- 可根据用户最近使用的数据库进行智能默认
|
||||||
|
|
||||||
|
3. **表格列顺序**:
|
||||||
|
- 建议顺序:数据库 → 表名 → 说明 → 操作
|
||||||
|
- 数据库列可以考虑使用标签样式展示
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 6. 完整示例代码
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// types.ts
|
||||||
|
export interface DataSource {
|
||||||
|
key: string;
|
||||||
|
displayName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TableListItem {
|
||||||
|
tableName: string;
|
||||||
|
remark: string;
|
||||||
|
dataBase: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TableListRequest {
|
||||||
|
tableName?: string;
|
||||||
|
dataBase?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// api.ts
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export const codeGenerationApi = {
|
||||||
|
// 🆕 获取数据库列表
|
||||||
|
getDatabases: (): Promise<DataSource[]> => {
|
||||||
|
return axios.get('/api/CodeGeneration/databases').then(res => res.data);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取表列表(已修改)
|
||||||
|
getTableList: (page: number, size: number, search: TableListRequest) => {
|
||||||
|
return axios.post(`/api/CodeGeneration/${size}/${page}`, search)
|
||||||
|
.then(res => res.data);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 生成代码(已修改)
|
||||||
|
generateCode: (params: {
|
||||||
|
tableName: string;
|
||||||
|
dataBase: string;
|
||||||
|
type: string;
|
||||||
|
}) => {
|
||||||
|
return axios.post('/api/CodeGeneration/GetCodeAsync', params)
|
||||||
|
.then(res => res.data);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 其他接口...
|
||||||
|
};
|
||||||
|
|
||||||
|
// page.vue
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { codeGenerationApi } from '@/api/codeGeneration';
|
||||||
|
import type { DataSource, TableListItem } from '@/types/codeGeneration';
|
||||||
|
|
||||||
|
// 状态
|
||||||
|
const databaseList = ref<DataSource[]>([]);
|
||||||
|
const selectedDatabase = ref<string>('');
|
||||||
|
const tableList = ref<TableListItem[]>([]);
|
||||||
|
const searchKeyword = ref<string>('');
|
||||||
|
const pagination = ref({ page: 1, size: 10, total: 0 });
|
||||||
|
|
||||||
|
// 生命周期
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadDatabases();
|
||||||
|
await loadTableList();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载数据库列表
|
||||||
|
const loadDatabases = async () => {
|
||||||
|
try {
|
||||||
|
databaseList.value = await codeGenerationApi.getDatabases();
|
||||||
|
// 可选:默认选择第一个数据库
|
||||||
|
// if (databaseList.value.length > 0) {
|
||||||
|
// selectedDatabase.value = databaseList.value[0].key;
|
||||||
|
// }
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载数据库列表失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载表列表
|
||||||
|
const loadTableList = async () => {
|
||||||
|
try {
|
||||||
|
const result = await codeGenerationApi.getTableList(
|
||||||
|
pagination.value.page,
|
||||||
|
pagination.value.size,
|
||||||
|
{
|
||||||
|
tableName: searchKeyword.value,
|
||||||
|
dataBase: selectedDatabase.value
|
||||||
|
}
|
||||||
|
);
|
||||||
|
tableList.value = result.dataSource;
|
||||||
|
pagination.value.total = result.total;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载表列表失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 事件处理
|
||||||
|
const handleDatabaseChange = () => {
|
||||||
|
pagination.value.page = 1; // 重置页码
|
||||||
|
loadTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = () => {
|
||||||
|
pagination.value.page = 1; // 重置页码
|
||||||
|
loadTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGenerateCode = async (record: TableListItem) => {
|
||||||
|
try {
|
||||||
|
const code = await codeGenerationApi.generateCode({
|
||||||
|
tableName: record.tableName,
|
||||||
|
dataBase: record.dataBase,
|
||||||
|
type: 'MiaoYu.Models'
|
||||||
|
});
|
||||||
|
// 展示代码...
|
||||||
|
} catch (error) {
|
||||||
|
console.error('生成代码失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="code-generation-page">
|
||||||
|
<!-- 筛选区域 -->
|
||||||
|
<div class="filter-section">
|
||||||
|
<a-space>
|
||||||
|
<a-select
|
||||||
|
v-model:value="selectedDatabase"
|
||||||
|
placeholder="选择数据库"
|
||||||
|
style="width: 200px"
|
||||||
|
@change="handleDatabaseChange"
|
||||||
|
>
|
||||||
|
<a-select-option value="">全部数据库</a-select-option>
|
||||||
|
<a-select-option
|
||||||
|
v-for="db in databaseList"
|
||||||
|
:key="db.key"
|
||||||
|
:value="db.key"
|
||||||
|
>
|
||||||
|
{{ db.displayName }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
|
||||||
|
<a-input
|
||||||
|
v-model:value="searchKeyword"
|
||||||
|
placeholder="搜索表名"
|
||||||
|
style="width: 300px"
|
||||||
|
@change="handleSearch"
|
||||||
|
/>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<a-table
|
||||||
|
:data-source="tableList"
|
||||||
|
:pagination="{
|
||||||
|
current: pagination.page,
|
||||||
|
pageSize: pagination.size,
|
||||||
|
total: pagination.total,
|
||||||
|
onChange: (page) => {
|
||||||
|
pagination.page = page;
|
||||||
|
loadTableList();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<a-table-column key="dataBase" title="数据库" data-index="dataBase">
|
||||||
|
<template #default="{ record }">
|
||||||
|
<a-tag :color="getDatabaseColor(record.dataBase)">
|
||||||
|
{{ getDatabaseDisplayName(record.dataBase) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<a-table-column key="tableName" title="表名" data-index="tableName" />
|
||||||
|
<a-table-column key="remark" title="说明" data-index="remark" />
|
||||||
|
<a-table-column key="actions" title="操作">
|
||||||
|
<template #default="{ record }">
|
||||||
|
<a-button type="link" @click="handleGenerateCode(record)">
|
||||||
|
生成代码
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
</a-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.code-generation-page {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 7. 视觉效果建议
|
||||||
|
|
||||||
|
### 数据库标签颜色方案
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const getDatabaseColor = (databaseKey: string): string => {
|
||||||
|
const colorMap: Record<string, string> = {
|
||||||
|
'Admin': 'blue',
|
||||||
|
'MiaoYuChat': 'green',
|
||||||
|
'LiveForum': 'orange'
|
||||||
|
};
|
||||||
|
return colorMap[databaseKey] || 'default';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDatabaseDisplayName = (databaseKey: string): string => {
|
||||||
|
const database = databaseList.value.find(db => db.key === databaseKey);
|
||||||
|
return database?.displayName || databaseKey;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 表格展示效果
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────┬─────────────────┬──────────────┬────────┐
|
||||||
|
│ 数据库 │ 表名 │ 说明 │ 操作 │
|
||||||
|
├────────────┼─────────────────┼──────────────┼────────┤
|
||||||
|
│ [Admin] │ Users │ 用户表 │ 生成 │
|
||||||
|
│ [MiaoYuChat]│ T_Image_Config │ 图片配置表 │ 生成 │
|
||||||
|
│ [Admin] │ Roles │ 角色表 │ 生成 │
|
||||||
|
└────────────┴─────────────────┴──────────────┴────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 8. 技术支持
|
||||||
|
|
||||||
|
如有疑问,请联系后端开发团队。
|
||||||
|
|
||||||
|
**文档版本**:v1.0
|
||||||
|
**更新日期**:2024年
|
||||||
|
**后端版本**:v2.0(支持多数据源)
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 18
|
# Visual Studio Version 18
|
||||||
VisualStudioVersion = 18.0.11201.2 d18.0
|
VisualStudioVersion = 18.0.11201.2
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "00 Core", "00 Core", "{DB46F54A-9F53-44EC-80F8-9E53F0B871CF}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "00 Core", "00 Core", "{DB46F54A-9F53-44EC-80F8-9E53F0B871CF}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -56,6 +56,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiaoYu.Core.Cos", "MiaoYu.C
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiaoYu.Repository.LiveForum.Admin", "MiaoYu.Repository.LiveForum.Admin\MiaoYu.Repository.LiveForum.Admin.csproj", "{2AF20E5B-478F-46FE-8F8C-A385BB5D5EC7}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiaoYu.Repository.LiveForum.Admin", "MiaoYu.Repository.LiveForum.Admin\MiaoYu.Repository.LiveForum.Admin.csproj", "{2AF20E5B-478F-46FE-8F8C-A385BB5D5EC7}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiaoYu.Core.CodeGenerator", "MiaoYu.Core.CodeGenerator\MiaoYu.Core.CodeGenerator.csproj", "{428143F9-9D59-4DF6-A43A-41CA52C4E113}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -138,6 +140,10 @@ Global
|
||||||
{2AF20E5B-478F-46FE-8F8C-A385BB5D5EC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{2AF20E5B-478F-46FE-8F8C-A385BB5D5EC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{2AF20E5B-478F-46FE-8F8C-A385BB5D5EC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{2AF20E5B-478F-46FE-8F8C-A385BB5D5EC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{2AF20E5B-478F-46FE-8F8C-A385BB5D5EC7}.Release|Any CPU.Build.0 = Release|Any CPU
|
{2AF20E5B-478F-46FE-8F8C-A385BB5D5EC7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{428143F9-9D59-4DF6-A43A-41CA52C4E113}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{428143F9-9D59-4DF6-A43A-41CA52C4E113}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{428143F9-9D59-4DF6-A43A-41CA52C4E113}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{428143F9-9D59-4DF6-A43A-41CA52C4E113}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -162,6 +168,7 @@ Global
|
||||||
{39C765DB-41E7-4BC6-B75E-2A90CFF3A8EF} = {451BE0BB-26ED-47ED-ABC7-23001D21410C}
|
{39C765DB-41E7-4BC6-B75E-2A90CFF3A8EF} = {451BE0BB-26ED-47ED-ABC7-23001D21410C}
|
||||||
{3FBBDE5E-2D2C-428B-A2BF-298499ABA5A7} = {DB46F54A-9F53-44EC-80F8-9E53F0B871CF}
|
{3FBBDE5E-2D2C-428B-A2BF-298499ABA5A7} = {DB46F54A-9F53-44EC-80F8-9E53F0B871CF}
|
||||||
{2AF20E5B-478F-46FE-8F8C-A385BB5D5EC7} = {451BE0BB-26ED-47ED-ABC7-23001D21410C}
|
{2AF20E5B-478F-46FE-8F8C-A385BB5D5EC7} = {451BE0BB-26ED-47ED-ABC7-23001D21410C}
|
||||||
|
{428143F9-9D59-4DF6-A43A-41CA52C4E113} = {DB46F54A-9F53-44EC-80F8-9E53F0B871CF}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {E3C61955-46C1-4D06-994F-C86A72B2B0E2}
|
SolutionGuid = {E3C61955-46C1-4D06-994F-C86A72B2B0E2}
|
||||||
|
|
|
||||||
|
|
@ -64,5 +64,20 @@ public class DataSourceConfig
|
||||||
/// 排序权重(数字越小越靠前)
|
/// 排序权重(数字越小越靠前)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Order { get; set; }
|
public int Order { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否启用实体类名前缀(用于避免多数据源同名表冲突)
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableEntityPrefix { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体类名前缀(如:Chat、Forum)
|
||||||
|
/// </summary>
|
||||||
|
public string EntityPrefix { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否使用复数形式的路径(如 /Users/ vs /User/)
|
||||||
|
/// </summary>
|
||||||
|
public bool UsesPluralPath { get; set; } = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,28 +31,37 @@ public class PathResolver : IScopedDependency
|
||||||
var rootPath = _environment.ContentRootPath
|
var rootPath = _environment.ContentRootPath
|
||||||
.Replace("\\" + _environment.ApplicationName, "");
|
.Replace("\\" + _environment.ApplicationName, "");
|
||||||
|
|
||||||
var entityName = GetEntityName(tableName, config.NamingStrategy);
|
var entityName = GetEntityName(tableName, config);
|
||||||
|
var entityNamePlural = config.UsesPluralPath ? entityName + "s" : entityName;
|
||||||
|
|
||||||
return template
|
return template
|
||||||
.Replace("{RootPath}", rootPath)
|
.Replace("{RootPath}", rootPath)
|
||||||
.Replace("{AppPath}", _environment.ContentRootPath)
|
.Replace("{AppPath}", _environment.ContentRootPath)
|
||||||
.Replace("{Namespace}", config.EntityNamespace)
|
.Replace("{Namespace}", config.EntityNamespace)
|
||||||
.Replace("{EntityName}", entityName)
|
.Replace("{EntityName}", entityName)
|
||||||
.Replace("{EntityNamePlural}", entityName + "s")
|
.Replace("{EntityNamePlural}", entityNamePlural)
|
||||||
.Replace("{TableName}", tableName);
|
.Replace("{TableName}", tableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据命名策略获取实体名
|
/// 根据命名策略和配置获取实体名
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tableName">表名</param>
|
/// <param name="tableName">表名</param>
|
||||||
/// <param name="strategy">命名策略</param>
|
/// <param name="config">数据源配置</param>
|
||||||
/// <returns>实体名</returns>
|
/// <returns>实体名</returns>
|
||||||
private string GetEntityName(string tableName, EntityNamingStrategy strategy)
|
public string GetEntityName(string tableName, DataSourceConfig config)
|
||||||
{
|
{
|
||||||
return strategy == EntityNamingStrategy.ToPascalCase
|
var baseName = config.NamingStrategy == EntityNamingStrategy.ToPascalCase
|
||||||
? tableName.ToLineConvertHump()
|
? tableName.ToLineConvertHump()
|
||||||
: tableName;
|
: tableName;
|
||||||
|
|
||||||
|
// 应用前缀(如果启用)
|
||||||
|
if (config.EnableEntityPrefix && !string.IsNullOrWhiteSpace(config.EntityPrefix))
|
||||||
|
{
|
||||||
|
return config.EntityPrefix + baseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,9 @@ public interface ICodeGenerationService : IScopedDependency
|
||||||
/// 获取表字段集合
|
/// 获取表字段集合
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tableName"></param>
|
/// <param name="tableName"></param>
|
||||||
|
/// <param name="databaseKey">数据库标识(可选)</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
GenDbTableDto GetGenContextDtoByTableName(string tableName);
|
GenDbTableDto GetGenContextDtoByTableName(string tableName, string? databaseKey = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据 lowCodeTable 填充路径
|
/// 根据 lowCodeTable 填充路径
|
||||||
|
|
@ -114,4 +115,10 @@ public interface ICodeGenerationService : IScopedDependency
|
||||||
/// <param name="genFormDto"></param>
|
/// <param name="genFormDto"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task AutoImprotProjectAsync(GenFormDto genFormDto);
|
Task AutoImprotProjectAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有数据库列表
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<DataSourceDto> GetAllDataSources();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,8 @@ public class CodeGenerationService : ICodeGenerationService
|
||||||
var result = new List<Dictionary<string, object>>();
|
var result = new List<Dictionary<string, object>>();
|
||||||
|
|
||||||
var query = _databaseTableService.GetAllTablesByCache()
|
var query = _databaseTableService.GetAllTablesByCache()
|
||||||
.WhereIf(!string.IsNullOrWhiteSpace(search.TableName), w => w.TableName.Contains(search.TableName));
|
.WhereIf(!string.IsNullOrWhiteSpace(search.TableName), w => w.TableName.Contains(search.TableName))
|
||||||
|
.WhereIf(!string.IsNullOrWhiteSpace(search.DataBase), w => w.DataBase == search.DataBase);
|
||||||
|
|
||||||
var tables = query
|
var tables = query
|
||||||
.Skip((page - 1) * size)
|
.Skip((page - 1) * size)
|
||||||
|
|
@ -73,6 +74,7 @@ public class CodeGenerationService : ICodeGenerationService
|
||||||
var dic = new Dictionary<string, object>();
|
var dic = new Dictionary<string, object>();
|
||||||
dic.Add(nameof(item.TableName), item.TableName);
|
dic.Add(nameof(item.TableName), item.TableName);
|
||||||
dic.Add(nameof(item.Remark), item.Remark);
|
dic.Add(nameof(item.Remark), item.Remark);
|
||||||
|
dic.Add(nameof(item.DataBase), item.DataBase);
|
||||||
|
|
||||||
result.Add(dic);
|
result.Add(dic);
|
||||||
}
|
}
|
||||||
|
|
@ -88,12 +90,29 @@ public class CodeGenerationService : ICodeGenerationService
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取所有表集合信息
|
/// 获取所有表集合信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <param name="databaseKey">数据库标识(可选)</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public GenDbTableDto GetGenContextDtoByTableName(string tableName)
|
public GenDbTableDto GetGenContextDtoByTableName(string tableName, string? databaseKey = null)
|
||||||
{
|
{
|
||||||
var genDbTableDto = _databaseTableService.GetAllTables().FirstOrDefault(w => w.TableName == tableName);
|
var query = _databaseTableService.GetAllTables().AsEnumerable();
|
||||||
|
|
||||||
FillPathByLowCodeTable(genDbTableDto);
|
// 如果指定了数据库,则精确匹配
|
||||||
|
if (!string.IsNullOrWhiteSpace(databaseKey))
|
||||||
|
{
|
||||||
|
query = query.Where(w => w.TableName == tableName && w.DataBase == databaseKey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
query = query.Where(w => w.TableName == tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var genDbTableDto = query.FirstOrDefault();
|
||||||
|
|
||||||
|
if (genDbTableDto != null)
|
||||||
|
{
|
||||||
|
FillPathByLowCodeTable(genDbTableDto);
|
||||||
|
}
|
||||||
|
|
||||||
return genDbTableDto;
|
return genDbTableDto;
|
||||||
}
|
}
|
||||||
|
|
@ -161,8 +180,7 @@ public class CodeGenerationService : ICodeGenerationService
|
||||||
public GenDbTableDto GetGenContextDto(GenFormDto genFormDto)
|
public GenDbTableDto GetGenContextDto(GenFormDto genFormDto)
|
||||||
{
|
{
|
||||||
var tableName = genFormDto.TableName;
|
var tableName = genFormDto.TableName;
|
||||||
|
var tableInfo = GetGenContextDtoByTableName(tableName, genFormDto.DataBase);
|
||||||
var tableInfo = GetGenContextDtoByTableName(tableName);
|
|
||||||
|
|
||||||
if (tableInfo == null) return null;
|
if (tableInfo == null) return null;
|
||||||
tableInfo.Namespace = Tools.GetNamespacePrefix<CodeGenerationService>();
|
tableInfo.Namespace = Tools.GetNamespacePrefix<CodeGenerationService>();
|
||||||
|
|
@ -280,6 +298,7 @@ public class CodeGenerationService : ICodeGenerationService
|
||||||
foreach (var item in tables)
|
foreach (var item in tables)
|
||||||
{
|
{
|
||||||
genFormDto.TableName = item.TableName;
|
genFormDto.TableName = item.TableName;
|
||||||
|
genFormDto.DataBase = item.DataBase;
|
||||||
await CreateCodeFilesAsync(genFormDto);
|
await CreateCodeFilesAsync(genFormDto);
|
||||||
await Task.Delay(25);
|
await Task.Delay(25);
|
||||||
}
|
}
|
||||||
|
|
@ -445,21 +464,42 @@ public class CodeGenerationService : ICodeGenerationService
|
||||||
if (context == null)
|
if (context == null)
|
||||||
{
|
{
|
||||||
MessageBox.Show("找不到此数据表!");
|
MessageBox.Show("找不到此数据表!");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取表路径信息
|
//获取表路径信息
|
||||||
var tables = _databaseTableService.GetAllTablesByCache();
|
var tables = _databaseTableService.GetAllTablesByCache();
|
||||||
var tableInfo = tables.FirstOrDefault(w => w.TableName == genFormDto.TableName);
|
var tableInfo = tables.FirstOrDefault(w =>
|
||||||
|
w.TableName == genFormDto.TableName &&
|
||||||
|
w.DataBase == genFormDto.DataBase);
|
||||||
|
|
||||||
var fileTyps = Enum.GetValues<FileTypeEnum>();
|
var fileTyps = Enum.GetValues<FileTypeEnum>();
|
||||||
|
|
||||||
foreach (var fileType in fileTyps)
|
foreach (var fileType in fileTyps)
|
||||||
{
|
{
|
||||||
var (filePath, oldName, replaceName) = GetFileAbsolutelyPath(genFormDto.TableName, fileType);
|
var (filePath, oldName, replaceName) = GetFileAbsolutelyPath(
|
||||||
|
genFormDto.TableName, fileType, genFormDto.DataBase);
|
||||||
await SaveToFileAsync(genFormDto.TableName, fileType, filePath, oldName, replaceName);
|
await SaveToFileAsync(genFormDto.TableName, fileType, filePath, oldName, replaceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有数据库列表
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<DataSourceDto> GetAllDataSources()
|
||||||
|
{
|
||||||
|
var providers = _dataSourceManager.GetAllProviders()
|
||||||
|
.OrderBy(p => p.Config.Order)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return providers.Select(p => new DataSourceDto
|
||||||
|
{
|
||||||
|
Key = p.Config.DatabaseKey,
|
||||||
|
DisplayName = p.Config.DisplayName
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#region 私有方法
|
#region 私有方法
|
||||||
|
|
||||||
|
|
@ -518,20 +558,17 @@ public class CodeGenerationService : ICodeGenerationService
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private string FindCodeFileClassName(GenFormDto genFormDto)
|
private string FindCodeFileClassName(GenFormDto genFormDto)
|
||||||
{
|
{
|
||||||
var tableName = genFormDto.TableName.ToLineConvertHump();
|
var provider = _dataSourceManager.GetProvider(genFormDto.DataBase ?? DataSourceConstants.Admin);
|
||||||
if (genFormDto.TableName.Contains("T_")|| genFormDto.TableName.Contains("M_"))
|
var entityName = _pathResolver.GetEntityName(genFormDto.TableName, provider.Config);
|
||||||
{
|
|
||||||
tableName = genFormDto.TableName;
|
|
||||||
}
|
|
||||||
return genFormDto.Type switch
|
return genFormDto.Type switch
|
||||||
{
|
{
|
||||||
"MiaoYu.Models" => $"{tableName}.cs",
|
"MiaoYu.Models" => $"{entityName}.cs",
|
||||||
// "MiaoYu.Repository.DbSet" => ,
|
"MiaoYu.Services.Admin" => $"{entityName}Service.cs",
|
||||||
"MiaoYu.Services.Admin" => $"{tableName}Service.cs",
|
"MiaoYu.Controllers.Admin" => $"{entityName}Controller.cs",
|
||||||
"MiaoYu.Controllers.Admin" => $"{tableName}Controller.cs",
|
|
||||||
"Client.Index" => $"Index.vue",
|
"Client.Index" => $"Index.vue",
|
||||||
"Client.Info" => $"Info.vue",
|
"Client.Info" => $"Info.vue",
|
||||||
"Client.Service" => $"{tableName}Service.ts",
|
"Client.Service" => $"{entityName}Service.ts",
|
||||||
_ => string.Empty
|
_ => string.Empty
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -541,51 +578,39 @@ public class CodeGenerationService : ICodeGenerationService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tableName"></param>
|
/// <param name="tableName"></param>
|
||||||
/// <param name="type"></param>
|
/// <param name="type"></param>
|
||||||
|
/// <param name="databaseKey">数据库标识(可选)</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private (string, string, string) GetFileAbsolutelyPath(string tableName, FileTypeEnum type)
|
private (string, string, string) GetFileAbsolutelyPath(string tableName, FileTypeEnum type, string? databaseKey = null)
|
||||||
{
|
{
|
||||||
var replaceName = string.Empty;
|
var replaceName = string.Empty;
|
||||||
var oldFileName = string.Empty;
|
var oldFileName = string.Empty;
|
||||||
var dto = new GenFormDto() { TableName = tableName, Type = GetEnumDescription(type) };
|
var dto = new GenFormDto() { TableName = tableName, Type = GetEnumDescription(type), DataBase = databaseKey };
|
||||||
var humpTableName = tableName.ToLineConvertHump();
|
|
||||||
|
var provider = _dataSourceManager.GetProvider(databaseKey ?? DataSourceConstants.Admin);
|
||||||
|
var entityName = _pathResolver.GetEntityName(tableName, provider.Config);
|
||||||
|
var entityNameWithPath = provider.Config.UsesPluralPath ? entityName + "s" : entityName;
|
||||||
|
|
||||||
var fileName = FindCodeFileClassName(dto);
|
var fileName = FindCodeFileClassName(dto);
|
||||||
var path = string.Empty;
|
var path = string.Empty;
|
||||||
//获取表路径信息
|
//获取表路径信息
|
||||||
var tableInfo = GetGenContextDtoByTableName(tableName);
|
var tableInfo = GetGenContextDtoByTableName(tableName, databaseKey);
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case FileTypeEnum.Model:
|
case FileTypeEnum.Model:
|
||||||
if (tableInfo.DataBase == "MiaoYuChat")
|
path = provider.Config.UsesPluralPath
|
||||||
{
|
? $"{tableInfo.ModelPath}/{entityNameWithPath}"
|
||||||
path = tableInfo.ModelPath + $"/";
|
: tableInfo.ModelPath;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = tableInfo.ModelPath + $"/{humpTableName}s";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FileTypeEnum.Service:
|
case FileTypeEnum.Service:
|
||||||
if (tableInfo.DataBase == "MiaoYuChat")
|
path = provider.Config.UsesPluralPath
|
||||||
{
|
? $"{tableInfo.ServicePath}/{entityNameWithPath}"
|
||||||
path = tableInfo.ServicePath + $"/MiaoYuChat";
|
: tableInfo.ServicePath;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = tableInfo.ServicePath + $"/{humpTableName}s";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FileTypeEnum.Controller:
|
case FileTypeEnum.Controller:
|
||||||
if (tableInfo.DataBase == "MiaoYuChat")
|
path = provider.Config.UsesPluralPath
|
||||||
{
|
? $"{tableInfo.ControllerPath}/{entityNameWithPath}"
|
||||||
path = tableInfo.ControllerPath + $"/MiaoYuChat";
|
: tableInfo.ControllerPath;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = tableInfo.ControllerPath + $"/{humpTableName}s";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FileTypeEnum.ClientIndex:
|
case FileTypeEnum.ClientIndex:
|
||||||
path = tableInfo.ClientIndexPath + $"/{tableName}s";
|
path = tableInfo.ClientIndexPath + $"/{tableName}s";
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
using MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Core;
|
||||||
|
|
||||||
namespace MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl;
|
namespace MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -84,7 +86,13 @@ public class LowCodeTableInfoService : ApplicationService<IRepository<LowCodeTab
|
||||||
{
|
{
|
||||||
var allTables = _databaseTableService.GetAllTableInfos();
|
var allTables = _databaseTableService.GetAllTableInfos();
|
||||||
var table = await _lowCodeTableRepository.FindAsync(w => w.Id == tableId);
|
var table = await _lowCodeTableRepository.FindAsync(w => w.Id == tableId);
|
||||||
var tableInfo = allTables.Find(w => w.Name == table.TableName);
|
|
||||||
|
// 修复:同时匹配表名和数据库标识
|
||||||
|
var tableInfo = allTables.Find(w =>
|
||||||
|
{
|
||||||
|
var dbKey = w.Schema.ExtractDatabaseKey();
|
||||||
|
return w.Name == table.TableName && dbKey == table.DataBase;
|
||||||
|
});
|
||||||
|
|
||||||
//查询出当前表所有的字段
|
//查询出当前表所有的字段
|
||||||
var tableColumns = await _defaultRepository.ToListAsync(w => w.Low_Code_TableId == table.Id);
|
var tableColumns = await _defaultRepository.ToListAsync(w => w.Low_Code_TableId == table.Id);
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,10 @@ public class AdminDataSourceProvider : IDataSourceProvider, IScopedDependency
|
||||||
ClientServicePathTemplate = "{RootPath}\\admin-client\\src\\services\\apps\\{TableName}s",
|
ClientServicePathTemplate = "{RootPath}\\admin-client\\src\\services\\apps\\{TableName}s",
|
||||||
TemplatePath = "/wwwroot/code_generation/template/",
|
TemplatePath = "/wwwroot/code_generation/template/",
|
||||||
NamingStrategy = EntityNamingStrategy.ToPascalCase,
|
NamingStrategy = EntityNamingStrategy.ToPascalCase,
|
||||||
Order = 1
|
Order = 1,
|
||||||
|
EnableEntityPrefix = false,
|
||||||
|
EntityPrefix = "",
|
||||||
|
UsesPluralPath = true
|
||||||
};
|
};
|
||||||
|
|
||||||
public List<DbTableInfo> GetTables()
|
public List<DbTableInfo> GetTables()
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,10 @@ public class MiaoYuChatDataSourceProvider : IDataSourceProvider, IScopedDependen
|
||||||
ClientServicePathTemplate = "{RootPath}\\admin-client\\src\\services\\apps\\{TableName}s",
|
ClientServicePathTemplate = "{RootPath}\\admin-client\\src\\services\\apps\\{TableName}s",
|
||||||
TemplatePath = "/wwwroot/code_generation/templatev4/",
|
TemplatePath = "/wwwroot/code_generation/templatev4/",
|
||||||
NamingStrategy = EntityNamingStrategy.KeepOriginal,
|
NamingStrategy = EntityNamingStrategy.KeepOriginal,
|
||||||
Order = 2
|
Order = 2,
|
||||||
|
EnableEntityPrefix = false,
|
||||||
|
EntityPrefix = "Chat",
|
||||||
|
UsesPluralPath = false
|
||||||
};
|
};
|
||||||
|
|
||||||
public List<DbTableInfo> GetTables()
|
public List<DbTableInfo> GetTables()
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,17 @@ public class CodeGenerationController : AdminControllerBase<ICodeGenerationServi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有数据库列表
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[ActionDescriptor(DisplayName = "获取数据库列表")]
|
||||||
|
[HttpGet]
|
||||||
|
public List<DataSourceDto> GetDatabasesAsync()
|
||||||
|
{
|
||||||
|
return _defaultService.GetAllDataSources();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取列表
|
/// 获取列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -41,7 +52,9 @@ public class CodeGenerationController : AdminControllerBase<ICodeGenerationServi
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(genFormDto.TableName))
|
if (!string.IsNullOrWhiteSpace(genFormDto.TableName))
|
||||||
{
|
{
|
||||||
var table = _defaultService.GetGenContextDtoByTableName(genFormDto.TableName);
|
var table = _defaultService.GetGenContextDtoByTableName(
|
||||||
|
genFormDto.TableName,
|
||||||
|
genFormDto.DataBase);
|
||||||
|
|
||||||
//lowCodeTableInfos = table.TableInfos;
|
//lowCodeTableInfos = table.TableInfos;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1449,6 +1449,21 @@
|
||||||
排序权重(数字越小越靠前)
|
排序权重(数字越小越靠前)
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="P:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Abstractions.DataSourceConfig.EnableEntityPrefix">
|
||||||
|
<summary>
|
||||||
|
是否启用实体类名前缀(用于避免多数据源同名表冲突)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Abstractions.DataSourceConfig.EntityPrefix">
|
||||||
|
<summary>
|
||||||
|
实体类名前缀(如:Chat、Forum)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Abstractions.DataSourceConfig.UsesPluralPath">
|
||||||
|
<summary>
|
||||||
|
是否使用复数形式的路径(如 /Users/ vs /User/)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Abstractions.DataSourceConstants">
|
<member name="T:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Abstractions.DataSourceConstants">
|
||||||
<summary>
|
<summary>
|
||||||
数据源常量
|
数据源常量
|
||||||
|
|
@ -1569,12 +1584,12 @@
|
||||||
<param name="tableName">表名</param>
|
<param name="tableName">表名</param>
|
||||||
<returns>解析后的完整路径</returns>
|
<returns>解析后的完整路径</returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Core.PathResolver.GetEntityName(System.String,MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Abstractions.EntityNamingStrategy)">
|
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Core.PathResolver.GetEntityName(System.String,MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Abstractions.DataSourceConfig)">
|
||||||
<summary>
|
<summary>
|
||||||
根据命名策略获取实体名
|
根据命名策略和配置获取实体名
|
||||||
</summary>
|
</summary>
|
||||||
<param name="tableName">表名</param>
|
<param name="tableName">表名</param>
|
||||||
<param name="strategy">命名策略</param>
|
<param name="config">数据源配置</param>
|
||||||
<returns>实体名</returns>
|
<returns>实体名</returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="T:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.ICodeGenerationService">
|
<member name="T:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.ICodeGenerationService">
|
||||||
|
|
@ -1588,11 +1603,12 @@
|
||||||
</summary>
|
</summary>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.ICodeGenerationService.GetGenContextDtoByTableName(System.String)">
|
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.ICodeGenerationService.GetGenContextDtoByTableName(System.String,System.String)">
|
||||||
<summary>
|
<summary>
|
||||||
获取表字段集合
|
获取表字段集合
|
||||||
</summary>
|
</summary>
|
||||||
<param name="tableName"></param>
|
<param name="tableName"></param>
|
||||||
|
<param name="databaseKey">数据库标识(可选)</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.ICodeGenerationService.FillPathByLowCodeTable(MiaoYu.Repository.Admin.Entities.LowCode.LowCodeTable)">
|
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.ICodeGenerationService.FillPathByLowCodeTable(MiaoYu.Repository.Admin.Entities.LowCode.LowCodeTable)">
|
||||||
|
|
@ -1692,6 +1708,12 @@
|
||||||
<param name="genFormDto"></param>
|
<param name="genFormDto"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.ICodeGenerationService.GetAllDataSources">
|
||||||
|
<summary>
|
||||||
|
获取所有数据库列表
|
||||||
|
</summary>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="T:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService">
|
<member name="T:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService">
|
||||||
<summary>
|
<summary>
|
||||||
代码生成服务
|
代码生成服务
|
||||||
|
|
@ -1713,10 +1735,12 @@
|
||||||
</summary>
|
</summary>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService.GetGenContextDtoByTableName(System.String)">
|
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService.GetGenContextDtoByTableName(System.String,System.String)">
|
||||||
<summary>
|
<summary>
|
||||||
获取所有表集合信息
|
获取所有表集合信息
|
||||||
</summary>
|
</summary>
|
||||||
|
<param name="tableName">表名</param>
|
||||||
|
<param name="databaseKey">数据库标识(可选)</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService.FillPathByLowCodeTable(MiaoYu.Repository.Admin.Entities.LowCode.LowCodeTable)">
|
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService.FillPathByLowCodeTable(MiaoYu.Repository.Admin.Entities.LowCode.LowCodeTable)">
|
||||||
|
|
@ -1816,6 +1840,12 @@
|
||||||
<param name="genFormDto"></param>
|
<param name="genFormDto"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService.GetAllDataSources">
|
||||||
|
<summary>
|
||||||
|
获取所有数据库列表
|
||||||
|
</summary>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService.ClearSymbol(System.Text.StringBuilder)">
|
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService.ClearSymbol(System.Text.StringBuilder)">
|
||||||
<summary>
|
<summary>
|
||||||
清除多余符号
|
清除多余符号
|
||||||
|
|
@ -1837,12 +1867,13 @@
|
||||||
<param name="genFormDto"></param>
|
<param name="genFormDto"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService.GetFileAbsolutelyPath(System.String,MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.FileTypeEnum)">
|
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService.GetFileAbsolutelyPath(System.String,MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.FileTypeEnum,System.String)">
|
||||||
<summary>
|
<summary>
|
||||||
获取要生成文件的绝对路径
|
获取要生成文件的绝对路径
|
||||||
</summary>
|
</summary>
|
||||||
<param name="tableName"></param>
|
<param name="tableName"></param>
|
||||||
<param name="type"></param>
|
<param name="type"></param>
|
||||||
|
<param name="databaseKey">数据库标识(可选)</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService.SaveToFileAsync(System.String,MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.FileTypeEnum,System.String,System.String,System.String)">
|
<member name="M:MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.CodeGenerationService.SaveToFileAsync(System.String,MiaoYu.Api.Admin.ApplicationServices.DevelopmentTools.LowCode.Impl.FileTypeEnum,System.String,System.String,System.String)">
|
||||||
|
|
@ -3822,6 +3853,12 @@
|
||||||
代码生成器控制器
|
代码生成器控制器
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:MiaoYu.Api.Admin.Controllers.DevelopmentTools.CodeGenerationController.GetDatabasesAsync">
|
||||||
|
<summary>
|
||||||
|
获取所有数据库列表
|
||||||
|
</summary>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="M:MiaoYu.Api.Admin.Controllers.DevelopmentTools.CodeGenerationController.FindListAsync(System.Int32,System.Int32,MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool.GenFormDto)">
|
<member name="M:MiaoYu.Api.Admin.Controllers.DevelopmentTools.CodeGenerationController.FindListAsync(System.Int32,System.Int32,MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool.GenFormDto)">
|
||||||
<summary>
|
<summary>
|
||||||
获取列表
|
获取列表
|
||||||
|
|
@ -4724,6 +4761,21 @@
|
||||||
域名
|
域名
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="T:MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool.DataSourceDto">
|
||||||
|
<summary>
|
||||||
|
数据源信息 DTO
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool.DataSourceDto.Key">
|
||||||
|
<summary>
|
||||||
|
数据库标识(Admin, MiaoYuChat, LiveForum)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool.DataSourceDto.DisplayName">
|
||||||
|
<summary>
|
||||||
|
显示名称
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool.GenContextDto">
|
<member name="T:MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool.GenContextDto">
|
||||||
<summary>
|
<summary>
|
||||||
生成代码上下文
|
生成代码上下文
|
||||||
|
|
@ -4744,6 +4796,11 @@
|
||||||
表名称
|
表名称
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="P:MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool.GenFormDto.DataBase">
|
||||||
|
<summary>
|
||||||
|
数据库标识(Admin, MiaoYuChat, LiveForum)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="P:MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool.GenFormDto.Type">
|
<member name="P:MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool.GenFormDto.Type">
|
||||||
<summary>
|
<summary>
|
||||||
类型代码
|
类型代码
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据源信息 DTO
|
||||||
|
/// </summary>
|
||||||
|
public class DataSourceDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库标识(Admin, MiaoYuChat, LiveForum)
|
||||||
|
/// </summary>
|
||||||
|
public string Key { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示名称
|
||||||
|
/// </summary>
|
||||||
|
public string DisplayName { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -10,6 +10,11 @@ public class GenFormDto
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? TableName { get; set; }
|
public string? TableName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库标识(Admin, MiaoYuChat, LiveForum)
|
||||||
|
/// </summary>
|
||||||
|
public string? DataBase { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 类型代码
|
/// 类型代码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Abstractions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据源配置
|
||||||
|
/// </summary>
|
||||||
|
public class DataSourceConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库标识(如:Admin, MiaoYuChat, LiveForum)
|
||||||
|
/// </summary>
|
||||||
|
public string DatabaseKey { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示名称
|
||||||
|
/// </summary>
|
||||||
|
public string DisplayName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体项目命名空间
|
||||||
|
/// </summary>
|
||||||
|
public string EntityNamespace { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体类路径模板(支持占位符:{RootPath}, {Namespace}, {EntityName}, {EntityNamePlural}, {TableName})
|
||||||
|
/// </summary>
|
||||||
|
public string ModelPathTemplate { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 服务层路径模板
|
||||||
|
/// </summary>
|
||||||
|
public string ServicePathTemplate { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 控制器路径模板
|
||||||
|
/// </summary>
|
||||||
|
public string ControllerPathTemplate { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前端Index页面路径模板
|
||||||
|
/// </summary>
|
||||||
|
public string ClientIndexPathTemplate { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前端Info页面路径模板
|
||||||
|
/// </summary>
|
||||||
|
public string ClientInfoPathTemplate { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前端Service路径模板
|
||||||
|
/// </summary>
|
||||||
|
public string ClientServicePathTemplate { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 代码生成模板目录
|
||||||
|
/// </summary>
|
||||||
|
public string TemplatePath { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体类命名规则(保持原名 or 驼峰转换)
|
||||||
|
/// </summary>
|
||||||
|
public EntityNamingStrategy NamingStrategy { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 排序权重(数字越小越靠前)
|
||||||
|
/// </summary>
|
||||||
|
public int Order { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否启用实体类名前缀(用于避免多数据源同名表冲突)
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableEntityPrefix { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体类名前缀(如:Chat、Forum)
|
||||||
|
/// </summary>
|
||||||
|
public string EntityPrefix { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否使用复数形式的路径(如 /Users/ vs /User/)
|
||||||
|
/// </summary>
|
||||||
|
public bool UsesPluralPath { get; set; } = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Abstractions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据源常量
|
||||||
|
/// </summary>
|
||||||
|
public static class DataSourceConstants
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 后台管理系统数据库
|
||||||
|
/// </summary>
|
||||||
|
public const string Admin = "Admin";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 喵语AI聊天数据库
|
||||||
|
/// </summary>
|
||||||
|
public const string MiaoYuChat = "MiaoYuChat";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 直播论坛数据库(预留)
|
||||||
|
/// </summary>
|
||||||
|
public const string LiveForum = "LiveForum";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Abstractions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体命名策略
|
||||||
|
/// </summary>
|
||||||
|
public enum EntityNamingStrategy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 保持数据库表名原样
|
||||||
|
/// </summary>
|
||||||
|
KeepOriginal = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 转换为驼峰命名(去除前缀下划线)
|
||||||
|
/// </summary>
|
||||||
|
ToPascalCase = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Abstractions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据源提供者接口
|
||||||
|
/// </summary>
|
||||||
|
public interface IDataSourceProvider
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 数据源配置
|
||||||
|
/// </summary>
|
||||||
|
DataSourceConfig Config { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取该数据源的所有表信息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>表信息列表</returns>
|
||||||
|
List<DbTableInfo> GetTables();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取DbContext(用于获取FreeSql实例)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>数据库上下文</returns>
|
||||||
|
object GetDbContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
using MiaoYu.Core.CodeGenerator.Abstractions;
|
||||||
|
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据源扩展方法
|
||||||
|
/// </summary>
|
||||||
|
public static class DataSourceExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 从 Schema 中提取数据库标识
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="schema">Schema字符串</param>
|
||||||
|
/// <returns>数据库标识</returns>
|
||||||
|
public static string ExtractDatabaseKey(this string schema)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(schema))
|
||||||
|
return DataSourceConstants.Admin;
|
||||||
|
|
||||||
|
if (schema.Contains("."))
|
||||||
|
{
|
||||||
|
var parts = schema.Split('.');
|
||||||
|
return parts.Length > 1 ? parts[1] : DataSourceConstants.Admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DataSourceConstants.Admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清理 Schema(移除数据库标识)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="schema">Schema字符串</param>
|
||||||
|
/// <returns>清理后的Schema</returns>
|
||||||
|
public static string CleanSchema(this string schema)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(schema))
|
||||||
|
return schema;
|
||||||
|
|
||||||
|
return schema.Contains(".")
|
||||||
|
? schema.Split('.')[0]
|
||||||
|
: schema;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
using MiaoYu.Core.CodeGenerator.Abstractions;
|
||||||
|
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据源管理器
|
||||||
|
/// </summary>
|
||||||
|
[Component]
|
||||||
|
public class DataSourceManager : IScopedDependency
|
||||||
|
{
|
||||||
|
private readonly IEnumerable<IDataSourceProvider> _providers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数(通过依赖注入自动收集所有IDataSourceProvider实现)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="providers">所有数据源提供者</param>
|
||||||
|
public DataSourceManager(IEnumerable<IDataSourceProvider> providers)
|
||||||
|
{
|
||||||
|
_providers = providers.OrderBy(p => p.Config.Order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有数据源提供者
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>数据源提供者集合</returns>
|
||||||
|
public IEnumerable<IDataSourceProvider> GetAllProviders() => _providers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据数据库标识获取数据源提供者
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="databaseKey">数据库标识(如:Admin, MiaoYuChat)</param>
|
||||||
|
/// <returns>数据源提供者,如果未找到返回null</returns>
|
||||||
|
public IDataSourceProvider? GetProvider(string databaseKey)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(databaseKey))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return _providers.FirstOrDefault(p =>
|
||||||
|
p.Config.DatabaseKey.Equals(databaseKey, StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有数据源的表信息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>所有表信息列表</returns>
|
||||||
|
public List<DbTableInfo> GetAllTables()
|
||||||
|
{
|
||||||
|
var allTables = new List<DbTableInfo>();
|
||||||
|
|
||||||
|
foreach (var provider in _providers)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tables = provider.GetTables();
|
||||||
|
if (tables != null && tables.Count > 0)
|
||||||
|
{
|
||||||
|
allTables.AddRange(tables);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogUtil.Log.Warning($"获取数据源 {provider.Config.DatabaseKey} 的表信息失败: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allTables;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
93
admin-server/MiaoYu.Core.CodeGenerator/Core/PathResolver.cs
Normal file
93
admin-server/MiaoYu.Core.CodeGenerator/Core/PathResolver.cs
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using MiaoYu.Core.CodeGenerator.Abstractions;
|
||||||
|
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 路径解析器
|
||||||
|
/// </summary>
|
||||||
|
[Component]
|
||||||
|
public class PathResolver : IScopedDependency
|
||||||
|
{
|
||||||
|
private readonly IWebHostEnvironment _environment;
|
||||||
|
|
||||||
|
public PathResolver(IWebHostEnvironment environment)
|
||||||
|
{
|
||||||
|
_environment = environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 解析路径模板
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="template">路径模板(支持占位符)</param>
|
||||||
|
/// <param name="config">数据源配置</param>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <returns>解析后的完整路径</returns>
|
||||||
|
public string ResolvePath(string template, DataSourceConfig config, string tableName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(template))
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var rootPath = _environment.ContentRootPath
|
||||||
|
.Replace("\\" + _environment.ApplicationName, "");
|
||||||
|
|
||||||
|
var entityName = GetEntityName(tableName, config);
|
||||||
|
var entityNamePlural = config.UsesPluralPath ? entityName + "s" : entityName;
|
||||||
|
|
||||||
|
return template
|
||||||
|
.Replace("{RootPath}", rootPath)
|
||||||
|
.Replace("{AppPath}", _environment.ContentRootPath)
|
||||||
|
.Replace("{Namespace}", config.EntityNamespace)
|
||||||
|
.Replace("{EntityName}", entityName)
|
||||||
|
.Replace("{EntityNamePlural}", entityNamePlural)
|
||||||
|
.Replace("{TableName}", tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据命名策略和配置获取实体名
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <param name="config">数据源配置</param>
|
||||||
|
/// <returns>实体名</returns>
|
||||||
|
public string GetEntityName(string tableName, DataSourceConfig config)
|
||||||
|
{
|
||||||
|
var baseName = config.NamingStrategy == EntityNamingStrategy.ToPascalCase
|
||||||
|
? ConvertToPascalCase(tableName)
|
||||||
|
: tableName;
|
||||||
|
|
||||||
|
// 应用前缀(如果启用)
|
||||||
|
if (config.EnableEntityPrefix && !string.IsNullOrWhiteSpace(config.EntityPrefix))
|
||||||
|
{
|
||||||
|
return config.EntityPrefix + baseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将下划线命名转换为 PascalCase
|
||||||
|
/// </summary>
|
||||||
|
private static string ConvertToPascalCase(string input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(input))
|
||||||
|
return input;
|
||||||
|
|
||||||
|
var words = input.Split(new[] { '_', '-' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
var result = new System.Text.StringBuilder();
|
||||||
|
|
||||||
|
foreach (var word in words)
|
||||||
|
{
|
||||||
|
if (word.Length > 0)
|
||||||
|
{
|
||||||
|
result.Append(char.ToUpper(word[0]));
|
||||||
|
if (word.Length > 1)
|
||||||
|
{
|
||||||
|
result.Append(word.Substring(1).ToLower());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Import Project="..\projects\project.targets" />
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- 基础框架 -->
|
||||||
|
<ProjectReference Include="..\MiaoYu.Core\MiaoYu.Core.csproj" />
|
||||||
|
<ProjectReference Include="..\MiaoYu.Core.Razor\MiaoYu.Core.Razor.csproj" />
|
||||||
|
<ProjectReference Include="..\MiaoYu.Core.FreeSql\MiaoYu.Core.FreeSql.csproj" />
|
||||||
|
<ProjectReference Include="..\MiaoYu.Core.Logs\MiaoYu.Core.Logs.csproj" />
|
||||||
|
<ProjectReference Include="..\MiaoYu.Shared\MiaoYu.Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- 数据访问和工具包 -->
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.2" />
|
||||||
|
<PackageReference Include="FreeSql" Version="3.2.806" />
|
||||||
|
<PackageReference Include="NPOI" Version="2.6.2" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
1182
admin-server/MiaoYu.Core.CodeGenerator/MiaoYu.Core.CodeGenerator.xml
Normal file
1182
admin-server/MiaoYu.Core.CodeGenerator/MiaoYu.Core.CodeGenerator.xml
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,43 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列元信息配置
|
||||||
|
/// </summary>
|
||||||
|
public class ColumnMetaConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 显示名称
|
||||||
|
/// </summary>
|
||||||
|
public string? DisplayName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列描述
|
||||||
|
/// </summary>
|
||||||
|
public string? Describe { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// C# 字段名
|
||||||
|
/// </summary>
|
||||||
|
public string? CsField { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否查询
|
||||||
|
/// </summary>
|
||||||
|
public bool? IsTableSelect { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否是图片Id
|
||||||
|
/// </summary>
|
||||||
|
public bool? IsImageId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否显示在Column上
|
||||||
|
/// </summary>
|
||||||
|
public bool? IsTableColumnShow { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 宽度
|
||||||
|
/// </summary>
|
||||||
|
public int? Width { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据源信息 DTO
|
||||||
|
/// </summary>
|
||||||
|
public class DataSourceDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库标识(如:Admin, MiaoYuChat)
|
||||||
|
/// </summary>
|
||||||
|
public string Key { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示名称
|
||||||
|
/// </summary>
|
||||||
|
public string DisplayName { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库列信息(从数据库元数据查询)
|
||||||
|
/// </summary>
|
||||||
|
public class DbColumnInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 列名
|
||||||
|
/// </summary>
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库类型
|
||||||
|
/// </summary>
|
||||||
|
public string? DbType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// C# 类型
|
||||||
|
/// </summary>
|
||||||
|
public string? CsType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否主键
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPrimary { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否自增
|
||||||
|
/// </summary>
|
||||||
|
public bool IsIdentity { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否可为空
|
||||||
|
/// </summary>
|
||||||
|
public bool IsNullable { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大长度
|
||||||
|
/// </summary>
|
||||||
|
public int? MaxLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列位置
|
||||||
|
/// </summary>
|
||||||
|
public int Position { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列注释
|
||||||
|
/// </summary>
|
||||||
|
public string? Comment { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
38
admin-server/MiaoYu.Core.CodeGenerator/Models/DbTableInfo.cs
Normal file
38
admin-server/MiaoYu.Core.CodeGenerator/Models/DbTableInfo.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库表信息(从数据库元数据查询)
|
||||||
|
/// </summary>
|
||||||
|
public class DbTableInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表名
|
||||||
|
/// </summary>
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表架构
|
||||||
|
/// </summary>
|
||||||
|
public string? Schema { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所属数据库标识
|
||||||
|
/// </summary>
|
||||||
|
public string? DataBase { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表类型
|
||||||
|
/// </summary>
|
||||||
|
public string? Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表注释
|
||||||
|
/// </summary>
|
||||||
|
public string? Comment { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列信息
|
||||||
|
/// </summary>
|
||||||
|
public List<DbColumnInfo>? Columns { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 代码生成表 DTO
|
||||||
|
/// </summary>
|
||||||
|
public class GenDbTableDto : LowCodeTable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表字段信息
|
||||||
|
/// </summary>
|
||||||
|
public List<LowCodeTableInfo>? TableInfos { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 命名空间
|
||||||
|
/// </summary>
|
||||||
|
public string? Namespace { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
28
admin-server/MiaoYu.Core.CodeGenerator/Models/GenFormDto.cs
Normal file
28
admin-server/MiaoYu.Core.CodeGenerator/Models/GenFormDto.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 代码生成表单模型
|
||||||
|
/// </summary>
|
||||||
|
public class GenFormDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表名称
|
||||||
|
/// </summary>
|
||||||
|
public string? TableName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库标识(Admin, MiaoYuChat, LiveForum)
|
||||||
|
/// </summary>
|
||||||
|
public string? DataBase { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 类型代码
|
||||||
|
/// </summary>
|
||||||
|
public string? Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 代码文本
|
||||||
|
/// </summary>
|
||||||
|
public string? CodeText { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 低代码表(不依赖数据库实体)
|
||||||
|
/// </summary>
|
||||||
|
public class LowCodeTable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表架构
|
||||||
|
/// </summary>
|
||||||
|
public string? Schema { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所属数据库
|
||||||
|
/// </summary>
|
||||||
|
public string? DataBase { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 类型
|
||||||
|
/// </summary>
|
||||||
|
public string? Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表名称
|
||||||
|
/// </summary>
|
||||||
|
public string? TableName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示名称 描述
|
||||||
|
/// </summary>
|
||||||
|
public string? DisplayName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体名称
|
||||||
|
/// </summary>
|
||||||
|
public string? EntityName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 备注
|
||||||
|
/// </summary>
|
||||||
|
public string? Remark { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体保存路径
|
||||||
|
/// </summary>
|
||||||
|
public string? ModelPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 服务保存路径
|
||||||
|
/// </summary>
|
||||||
|
public string? ServicePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 控制器保存路径
|
||||||
|
/// </summary>
|
||||||
|
public string? ControllerPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前端视图保存路径
|
||||||
|
/// </summary>
|
||||||
|
public string? ClientIndexPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前端信息弹窗保存位置
|
||||||
|
/// </summary>
|
||||||
|
public string? ClientInfoPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前端服务保存位置
|
||||||
|
/// </summary>
|
||||||
|
public string? ClientServicePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否覆盖生成
|
||||||
|
/// </summary>
|
||||||
|
public bool? IsCover { get; set; } = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 低代码表列信息(不依赖数据库实体)
|
||||||
|
/// </summary>
|
||||||
|
public class LowCodeTableInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 主键
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPrimary { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自增标识
|
||||||
|
/// </summary>
|
||||||
|
public bool IsIdentity { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否可DBNull
|
||||||
|
/// </summary>
|
||||||
|
public bool IsNullable { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 字段位置
|
||||||
|
/// </summary>
|
||||||
|
public int Position { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列名
|
||||||
|
/// </summary>
|
||||||
|
public string? ColumnName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列描述
|
||||||
|
/// </summary>
|
||||||
|
public string? Describe { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库列类型
|
||||||
|
/// </summary>
|
||||||
|
public string? DatabaseColumnType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// c# 数据类型
|
||||||
|
/// </summary>
|
||||||
|
public string? CsType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// c# 字段
|
||||||
|
/// </summary>
|
||||||
|
public string? CsField { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大长度
|
||||||
|
/// </summary>
|
||||||
|
public int? MaxLength { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示名称
|
||||||
|
/// </summary>
|
||||||
|
public string? DisplayName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否查询
|
||||||
|
/// </summary>
|
||||||
|
public bool? IsTableSelect { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否是图片Id
|
||||||
|
/// </summary>
|
||||||
|
public bool? IsImageId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否显示在Column上
|
||||||
|
/// </summary>
|
||||||
|
public bool? IsTableColumnShow { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 宽度
|
||||||
|
/// </summary>
|
||||||
|
public string? Width { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 排序
|
||||||
|
/// </summary>
|
||||||
|
public int? OrderById { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
44
admin-server/MiaoYu.Core.CodeGenerator/Models/PagingView.cs
Normal file
44
admin-server/MiaoYu.Core.CodeGenerator/Models/PagingView.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 简化的分页视图模型
|
||||||
|
/// </summary>
|
||||||
|
public class PagingView
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 数据源
|
||||||
|
/// </summary>
|
||||||
|
public object? DataSource { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 总数
|
||||||
|
/// </summary>
|
||||||
|
public long Total { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 总页数
|
||||||
|
/// </summary>
|
||||||
|
public long PageCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 一页显示多少条
|
||||||
|
/// </summary>
|
||||||
|
public int Size { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页码
|
||||||
|
/// </summary>
|
||||||
|
public int Page { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="page"></param>
|
||||||
|
/// <param name="size"></param>
|
||||||
|
public PagingView(int page, int size)
|
||||||
|
{
|
||||||
|
Page = page;
|
||||||
|
Size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表元信息配置
|
||||||
|
/// </summary>
|
||||||
|
public class TableMetaConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 显示名称
|
||||||
|
/// </summary>
|
||||||
|
public string? DisplayName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体名称
|
||||||
|
/// </summary>
|
||||||
|
public string? EntityName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 备注
|
||||||
|
/// </summary>
|
||||||
|
public string? Remark { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体保存路径
|
||||||
|
/// </summary>
|
||||||
|
public string? ModelPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 服务保存路径
|
||||||
|
/// </summary>
|
||||||
|
public string? ServicePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 控制器保存路径
|
||||||
|
/// </summary>
|
||||||
|
public string? ControllerPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前端视图保存路径
|
||||||
|
/// </summary>
|
||||||
|
public string? ClientIndexPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前端信息弹窗保存位置
|
||||||
|
/// </summary>
|
||||||
|
public string? ClientInfoPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前端服务保存位置
|
||||||
|
/// </summary>
|
||||||
|
public string? ClientServicePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否覆盖生成
|
||||||
|
/// </summary>
|
||||||
|
public bool IsCover { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列配置(Key: ColumnName)
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, ColumnMetaConfig>? Columns { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,765 @@
|
||||||
|
using MiaoYu.Core.CodeGenerator.Abstractions;
|
||||||
|
using MiaoYu.Core.CodeGenerator.Core;
|
||||||
|
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 代码生成服务
|
||||||
|
/// </summary>
|
||||||
|
public class CodeGenerationService : ICodeGenerationService
|
||||||
|
{
|
||||||
|
private readonly string _webRootPath;
|
||||||
|
private readonly string templateRootPath = "/wwwroot/code_generation/template/";
|
||||||
|
private readonly string templateRootPath_v4 = "/wwwroot/code_generation/templatev4/";
|
||||||
|
private readonly string codesRootPath = "/code_generation/codes";
|
||||||
|
private readonly string zipRootPath = "/code_generation/zip";
|
||||||
|
|
||||||
|
//domain 模板文件
|
||||||
|
private readonly string templateModel = "tempModel.cshtml";
|
||||||
|
private readonly string templateService = "tempService.cshtml";
|
||||||
|
private readonly string templateController = "tempController.cshtml";
|
||||||
|
private readonly string templateServiceJs = "tempClientService.cshtml";
|
||||||
|
private readonly string templateIndex = "tempClientIndex.cshtml";
|
||||||
|
private readonly string templateInfo = "tempClientInfo.cshtml";
|
||||||
|
|
||||||
|
// 客户端名称
|
||||||
|
private readonly string projectClientName = "admin-client";
|
||||||
|
|
||||||
|
private readonly IDatabaseTableService _databaseTableService;
|
||||||
|
private readonly IRazorViewRender _razorViewRender;
|
||||||
|
private readonly DataSourceManager _dataSourceManager;
|
||||||
|
private readonly PathResolver _pathResolver;
|
||||||
|
private readonly ITableMetaConfigService _tableMetaConfigService;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="databaseTableService">数据库表服务</param>
|
||||||
|
/// <param name="razorViewRender">Razor视图渲染器</param>
|
||||||
|
/// <param name="webHostEnvironment">Web宿主环境</param>
|
||||||
|
/// <param name="dataSourceManager">数据源管理器</param>
|
||||||
|
/// <param name="pathResolver">路径解析器</param>
|
||||||
|
/// <param name="tableMetaConfigService">表元信息配置服务</param>
|
||||||
|
public CodeGenerationService(IDatabaseTableService databaseTableService,
|
||||||
|
IRazorViewRender razorViewRender,
|
||||||
|
IWebHostEnvironment webHostEnvironment,
|
||||||
|
DataSourceManager dataSourceManager,
|
||||||
|
PathResolver pathResolver,
|
||||||
|
ITableMetaConfigService tableMetaConfigService)
|
||||||
|
{
|
||||||
|
_databaseTableService = databaseTableService;
|
||||||
|
_razorViewRender = razorViewRender;
|
||||||
|
_webRootPath = webHostEnvironment.WebRootPath;
|
||||||
|
_dataSourceManager = dataSourceManager;
|
||||||
|
_pathResolver = pathResolver;
|
||||||
|
_tableMetaConfigService = tableMetaConfigService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成上下文集合
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public PagingView GetGenContextDtos(int page, int size, GenFormDto search)
|
||||||
|
{
|
||||||
|
var PagingView = new PagingView(page, size);
|
||||||
|
var result = new List<Dictionary<string, object>>();
|
||||||
|
|
||||||
|
var query = _databaseTableService.GetAllTablesByCache().AsEnumerable();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(search.TableName))
|
||||||
|
{
|
||||||
|
query = query.Where(w => w.TableName != null && w.TableName.Contains(search.TableName));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(search.DataBase))
|
||||||
|
{
|
||||||
|
query = query.Where(w => w.DataBase == search.DataBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tables = query
|
||||||
|
.Skip((page - 1) * size)
|
||||||
|
.Take(size)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var item in tables)
|
||||||
|
{
|
||||||
|
var dic = new Dictionary<string, object>();
|
||||||
|
dic.Add(nameof(item.TableName), item.TableName);
|
||||||
|
dic.Add(nameof(item.Remark), item.Remark);
|
||||||
|
dic.Add(nameof(item.DataBase), item.DataBase);
|
||||||
|
|
||||||
|
result.Add(dic);
|
||||||
|
}
|
||||||
|
|
||||||
|
PagingView.Total = query.LongCount();
|
||||||
|
PagingView.Page = page;
|
||||||
|
PagingView.Size = size;
|
||||||
|
PagingView.DataSource = result;
|
||||||
|
PagingView.PageCount = PagingView.Total / size;
|
||||||
|
return PagingView;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有表集合信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <param name="databaseKey">数据库标识(可选)</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public GenDbTableDto GetGenContextDtoByTableName(string tableName, string? databaseKey = null)
|
||||||
|
{
|
||||||
|
var query = _databaseTableService.GetAllTables().AsEnumerable();
|
||||||
|
|
||||||
|
// 如果指定了数据库,则精确匹配
|
||||||
|
if (!string.IsNullOrWhiteSpace(databaseKey))
|
||||||
|
{
|
||||||
|
query = query.Where(w => w.TableName == tableName && w.DataBase == databaseKey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
query = query.Where(w => w.TableName == tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var genDbTableDto = query.FirstOrDefault();
|
||||||
|
|
||||||
|
if (genDbTableDto != null)
|
||||||
|
{
|
||||||
|
FillPathByLowCodeTable(genDbTableDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
return genDbTableDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据 lowCodeTable 填充路径(支持多数据源)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lowCodeTable">低代码表配置</param>
|
||||||
|
/// <returns>填充路径后的低代码表配置</returns>
|
||||||
|
public LowCodeTable FillPathByLowCodeTable(LowCodeTable lowCodeTable)
|
||||||
|
{
|
||||||
|
var provider = _dataSourceManager.GetProvider(lowCodeTable.DataBase ?? DataSourceConstants.Admin);
|
||||||
|
if (provider == null)
|
||||||
|
{
|
||||||
|
LogUtil.Log.Warning($"未找到数据源 {lowCodeTable.DataBase},使用默认Admin配置");
|
||||||
|
provider = _dataSourceManager.GetProvider(DataSourceConstants.Admin);
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = provider!.Config;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(lowCodeTable.ModelPath))
|
||||||
|
{
|
||||||
|
lowCodeTable.ModelPath = _pathResolver.ResolvePath(
|
||||||
|
config.ModelPathTemplate, config, lowCodeTable.TableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(lowCodeTable.ServicePath))
|
||||||
|
{
|
||||||
|
lowCodeTable.ServicePath = _pathResolver.ResolvePath(
|
||||||
|
config.ServicePathTemplate, config, lowCodeTable.TableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(lowCodeTable.ControllerPath))
|
||||||
|
{
|
||||||
|
lowCodeTable.ControllerPath = _pathResolver.ResolvePath(
|
||||||
|
config.ControllerPathTemplate, config, lowCodeTable.TableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(lowCodeTable.ClientIndexPath))
|
||||||
|
{
|
||||||
|
lowCodeTable.ClientIndexPath = _pathResolver.ResolvePath(
|
||||||
|
config.ClientIndexPathTemplate, config, lowCodeTable.TableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(lowCodeTable.ClientInfoPath))
|
||||||
|
{
|
||||||
|
lowCodeTable.ClientInfoPath = _pathResolver.ResolvePath(
|
||||||
|
config.ClientInfoPathTemplate, config, lowCodeTable.TableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(lowCodeTable.ClientServicePath))
|
||||||
|
{
|
||||||
|
lowCodeTable.ClientServicePath = _pathResolver.ResolvePath(
|
||||||
|
config.ClientServicePathTemplate, config, lowCodeTable.TableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lowCodeTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取代码生成上下文
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public GenDbTableDto GetGenContextDto(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var tableName = genFormDto.TableName;
|
||||||
|
var tableInfo = GetGenContextDtoByTableName(tableName, genFormDto.DataBase);
|
||||||
|
|
||||||
|
if (tableInfo == null) return null;
|
||||||
|
tableInfo.Namespace = Tools.GetNamespacePrefix<CodeGenerationService>();
|
||||||
|
return tableInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成model(支持多数据源)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<string> GenModelAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var context = GetGenContextDto(genFormDto);
|
||||||
|
var provider = _dataSourceManager.GetProvider(context.DataBase ?? DataSourceConstants.Admin);
|
||||||
|
var templatePath = provider?.Config.TemplatePath ?? templateRootPath;
|
||||||
|
return ClearSymbol(await _razorViewRender.RenderAsync(templatePath + templateModel, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成service(支持多数据源)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<string> GenServiceAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var context = GetGenContextDto(genFormDto);
|
||||||
|
var provider = _dataSourceManager.GetProvider(context.DataBase ?? DataSourceConstants.Admin);
|
||||||
|
var templatePath = provider?.Config.TemplatePath ?? templateRootPath;
|
||||||
|
return ClearSymbol(await _razorViewRender.RenderAsync(templatePath + templateService, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成controller(支持多数据源)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<string> GenControllerAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var context = GetGenContextDto(genFormDto);
|
||||||
|
var provider = _dataSourceManager.GetProvider(context.DataBase ?? DataSourceConstants.Admin);
|
||||||
|
var templatePath = provider?.Config.TemplatePath ?? templateRootPath;
|
||||||
|
return ClearSymbol(await _razorViewRender.RenderAsync(templatePath + templateController, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成service js(支持多数据源)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<string> GenServiceJsAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var context = GetGenContextDto(genFormDto);
|
||||||
|
var provider = _dataSourceManager.GetProvider(context.DataBase ?? DataSourceConstants.Admin);
|
||||||
|
var templatePath = provider?.Config.TemplatePath ?? templateRootPath;
|
||||||
|
return ClearSymbol(await _razorViewRender.RenderAsync(templatePath + templateServiceJs, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成 index vue(支持多数据源)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<string> GenIndexAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var context = GetGenContextDto(genFormDto);
|
||||||
|
var provider = _dataSourceManager.GetProvider(context.DataBase ?? DataSourceConstants.Admin);
|
||||||
|
var templatePath = provider?.Config.TemplatePath ?? templateRootPath;
|
||||||
|
return ClearSymbol(await _razorViewRender.RenderAsync(templatePath + templateIndex, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成 info vue(支持多数据源)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<string> GenInfoAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var context = GetGenContextDto(genFormDto);
|
||||||
|
var provider = _dataSourceManager.GetProvider(context.DataBase ?? DataSourceConstants.Admin);
|
||||||
|
var templatePath = provider?.Config.TemplatePath ?? templateRootPath;
|
||||||
|
return ClearSymbol(await _razorViewRender.RenderAsync(templatePath + templateInfo, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取代码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<string> GetCodeByTypeAndTableNameAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
return genFormDto.Type switch
|
||||||
|
{
|
||||||
|
"MiaoYu.Models" => await GenModelAsync(genFormDto),
|
||||||
|
//"MiaoYu.Repository.DbSet" => await this.CreateRepositoryDbSetAsync(),
|
||||||
|
"MiaoYu.Services.Admin" => await GenServiceAsync(genFormDto),
|
||||||
|
"MiaoYu.Controllers.Admin" => await GenControllerAsync(genFormDto),
|
||||||
|
"Client.Index" => await GenIndexAsync(genFormDto),
|
||||||
|
"Client.Info" => await GenInfoAsync(genFormDto),
|
||||||
|
"Client.Service" => await GenServiceJsAsync(genFormDto),
|
||||||
|
_ => string.Empty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建所有代码文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<bool> CreateAllCodeFilesAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var tables = _databaseTableService.GetAllTablesByCache();
|
||||||
|
|
||||||
|
foreach (var item in tables)
|
||||||
|
{
|
||||||
|
genFormDto.TableName = item.TableName;
|
||||||
|
genFormDto.DataBase = item.DataBase;
|
||||||
|
await CreateCodeFilesAsync(genFormDto);
|
||||||
|
|
||||||
|
// 保存元信息到配置文件
|
||||||
|
await SaveTableMetaConfigAsync(item);
|
||||||
|
|
||||||
|
await Task.Delay(25);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取下载代码信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<(byte[] codeBytes, string contentType, string fileName)> DownloadAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var fileName = FindCodeFileClassName(genFormDto);
|
||||||
|
|
||||||
|
var contentType = Tools.GetFileContentType[".cs"];
|
||||||
|
if (fileName == "Index.vue" || fileName == "Info.vue")
|
||||||
|
{
|
||||||
|
contentType = Tools.GetFileContentType[".txt"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Encoding.UTF8.GetBytes(await GetCodeByTypeAndTableNameAsync(genFormDto)), contentType, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据类型下载所有代码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<(byte[] codeBytes, string contentType, string fileName)> DownloadAllAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var isViews = genFormDto.Type == "Client.Index" || genFormDto.Type == "Client.Info";
|
||||||
|
var success = await CreateAllCodeFilesAsync(genFormDto);
|
||||||
|
|
||||||
|
if (!success) LogUtil.Log.Warning("无法下载,代码创建失败!");
|
||||||
|
|
||||||
|
string path;
|
||||||
|
string zipPath;
|
||||||
|
|
||||||
|
if (isViews)
|
||||||
|
{
|
||||||
|
path = $"{_webRootPath}{codesRootPath}/pages";
|
||||||
|
zipPath = $"{_webRootPath}{zipRootPath}";
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(zipPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(zipPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
zipPath += "/pages.zip";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
path = $"{_webRootPath}{codesRootPath}/{genFormDto.Type}";
|
||||||
|
zipPath = $"{_webRootPath}{zipRootPath}";
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(zipPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(zipPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
zipPath += $"/{genFormDto.Type}.zip";
|
||||||
|
}
|
||||||
|
|
||||||
|
//开始压缩
|
||||||
|
var zip = new MiaoYu.Core.Zips.Zip(path, zipPath);
|
||||||
|
var bytes = await File.ReadAllBytesAsync(zipPath);
|
||||||
|
|
||||||
|
//删除文件
|
||||||
|
if (File.Exists(zipPath)) File.Delete(zipPath);
|
||||||
|
if (Directory.Exists(path)) Directory.Delete(path, true);
|
||||||
|
|
||||||
|
return (bytes, Tools.GetFileContentType[".zip"], $"{(isViews ? "pages" : genFormDto.Type)}.zip");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建数据库字典文件
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public (byte[] excel, string dataBase) CreateDataDictionary()
|
||||||
|
{
|
||||||
|
var tables = _databaseTableService.GetAllTablesByCache();
|
||||||
|
var workbook = new XSSFWorkbook();
|
||||||
|
var dataBaseName = _databaseTableService.GetDatabaseName();
|
||||||
|
|
||||||
|
foreach (var item in tables)
|
||||||
|
{
|
||||||
|
var sheet = workbook.CreateSheet(item.TableName + (string.IsNullOrWhiteSpace(item.Remark) ? "" : "_" + item.Remark));
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
#region 配置表头
|
||||||
|
|
||||||
|
var rowTitle = sheet.CreateRow(i);
|
||||||
|
rowTitle.CreateCell(0).SetCellValue("表空间");
|
||||||
|
sheet.SetColumnWidth(0, 20 * 256);
|
||||||
|
rowTitle.CreateCell(1).SetCellValue("表名");
|
||||||
|
sheet.SetColumnWidth(1, 20 * 256);
|
||||||
|
rowTitle.CreateCell(2).SetCellValue("表描述");
|
||||||
|
sheet.SetColumnWidth(2, 20 * 256);
|
||||||
|
rowTitle.CreateCell(3).SetCellValue("字段");
|
||||||
|
sheet.SetColumnWidth(3, 20 * 256);
|
||||||
|
rowTitle.CreateCell(4).SetCellValue("字段描述");
|
||||||
|
sheet.SetColumnWidth(4, 20 * 256);
|
||||||
|
rowTitle.CreateCell(5).SetCellValue("是否主键");
|
||||||
|
sheet.SetColumnWidth(5, 20 * 256);
|
||||||
|
rowTitle.CreateCell(6).SetCellValue("是否自增");
|
||||||
|
sheet.SetColumnWidth(6, 20 * 256);
|
||||||
|
rowTitle.CreateCell(7).SetCellValue("可否为 Null");
|
||||||
|
sheet.SetColumnWidth(7, 20 * 256);
|
||||||
|
rowTitle.CreateCell(8).SetCellValue("数据库类型");
|
||||||
|
sheet.SetColumnWidth(8, 20 * 256);
|
||||||
|
rowTitle.CreateCell(9).SetCellValue("C#类型");
|
||||||
|
sheet.SetColumnWidth(9, 20 * 256);
|
||||||
|
rowTitle.CreateCell(10).SetCellValue("数据长度");
|
||||||
|
sheet.SetColumnWidth(10, 20 * 256);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
//组装数据
|
||||||
|
foreach (var tableInfo in item.TableInfos)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
var index = item.TableInfos.IndexOf(tableInfo);
|
||||||
|
var row = sheet.CreateRow(i);
|
||||||
|
//row.CreateCell(0).SetCellValue(item.Schema);
|
||||||
|
row.CreateCell(1).SetCellValue(item.TableName);
|
||||||
|
row.CreateCell(2).SetCellValue(item.Remark);
|
||||||
|
row.CreateCell(3).SetCellValue(tableInfo.ColumnName);
|
||||||
|
row.CreateCell(4).SetCellValue(tableInfo.Describe);
|
||||||
|
row.CreateCell(5).SetCellValue(tableInfo.IsPrimary ? "是" : "否");
|
||||||
|
row.CreateCell(6).SetCellValue(tableInfo.IsIdentity ? "是" : "否");
|
||||||
|
row.CreateCell(7).SetCellValue(tableInfo.IsNullable ? "是" : "否");
|
||||||
|
row.CreateCell(8).SetCellValue(tableInfo.DatabaseColumnType);
|
||||||
|
row.CreateCell(9).SetCellValue(tableInfo.CsType);
|
||||||
|
row.CreateCell(10).SetCellValue(tableInfo.MaxLength ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//填充byte
|
||||||
|
using var ms = new MemoryStream();
|
||||||
|
workbook.Write(ms);
|
||||||
|
return (ms.ToArray(), dataBaseName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自动导入文件到项目
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task AutoImprotProjectAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var context = GetGenContextDto(genFormDto);
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
LogUtil.Log.Warning($"找不到数据表: {genFormDto.TableName} (数据库: {genFormDto.DataBase})");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取表路径信息
|
||||||
|
var tables = _databaseTableService.GetAllTablesByCache();
|
||||||
|
var tableInfo = tables.FirstOrDefault(w =>
|
||||||
|
w.TableName == genFormDto.TableName &&
|
||||||
|
w.DataBase == genFormDto.DataBase);
|
||||||
|
|
||||||
|
var fileTyps = Enum.GetValues<FileTypeEnum>();
|
||||||
|
|
||||||
|
foreach (var fileType in fileTyps)
|
||||||
|
{
|
||||||
|
var (filePath, oldName, replaceName) = GetFileAbsolutelyPath(
|
||||||
|
genFormDto.TableName, fileType, genFormDto.DataBase);
|
||||||
|
await SaveToFileAsync(genFormDto.TableName, fileType, filePath, oldName, replaceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有数据库列表
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<DataSourceDto> GetAllDataSources()
|
||||||
|
{
|
||||||
|
var providers = _dataSourceManager.GetAllProviders()
|
||||||
|
.OrderBy(p => p.Config.Order)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return providers.Select(p => new DataSourceDto
|
||||||
|
{
|
||||||
|
Key = p.Config.DatabaseKey,
|
||||||
|
DisplayName = p.Config.DisplayName
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region 私有方法
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清除多余符号
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string ClearSymbol(StringBuilder code)
|
||||||
|
{
|
||||||
|
return code
|
||||||
|
.ToString()
|
||||||
|
.Replace("<pre>", "")
|
||||||
|
.Replace("</pre>", "")
|
||||||
|
.Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建代码文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task<string> CreateCodeFilesAsync(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var path = $"{_webRootPath}{codesRootPath}";
|
||||||
|
|
||||||
|
if (genFormDto.Type == "Client.Index" || genFormDto.Type == "Client.Info")
|
||||||
|
{
|
||||||
|
path += $"/pages"; //
|
||||||
|
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
|
||||||
|
path += $"/{genFormDto.TableName}";
|
||||||
|
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
|
||||||
|
//Index
|
||||||
|
var codeString = await GenIndexAsync(genFormDto);
|
||||||
|
await File.WriteAllTextAsync($"{path}/Index.vue", codeString, Encoding.UTF8);
|
||||||
|
//Info
|
||||||
|
codeString = await GenInfoAsync(genFormDto);
|
||||||
|
await File.WriteAllTextAsync($"{path}/Info.vue", codeString, Encoding.UTF8);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
path = $"{_webRootPath}{codesRootPath}/{genFormDto.Type}";
|
||||||
|
var className = FindCodeFileClassName(genFormDto);
|
||||||
|
var code = await GetCodeByTypeAndTableNameAsync(genFormDto);
|
||||||
|
//
|
||||||
|
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
|
||||||
|
await File.WriteAllTextAsync($"{path}/{className}", code, Encoding.UTF8);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取代码文件名称
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string FindCodeFileClassName(GenFormDto genFormDto)
|
||||||
|
{
|
||||||
|
var provider = _dataSourceManager.GetProvider(genFormDto.DataBase ?? DataSourceConstants.Admin);
|
||||||
|
var entityName = _pathResolver.GetEntityName(genFormDto.TableName, provider.Config);
|
||||||
|
|
||||||
|
return genFormDto.Type switch
|
||||||
|
{
|
||||||
|
"MiaoYu.Models" => $"{entityName}.cs",
|
||||||
|
"MiaoYu.Services.Admin" => $"{entityName}Service.cs",
|
||||||
|
"MiaoYu.Controllers.Admin" => $"{entityName}Controller.cs",
|
||||||
|
"Client.Index" => $"Index.vue",
|
||||||
|
"Client.Info" => $"Info.vue",
|
||||||
|
"Client.Service" => $"{entityName}Service.ts",
|
||||||
|
_ => string.Empty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取要生成文件的绝对路径
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName"></param>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="databaseKey">数据库标识(可选)</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private (string, string, string) GetFileAbsolutelyPath(string tableName, FileTypeEnum type, string? databaseKey = null)
|
||||||
|
{
|
||||||
|
var replaceName = string.Empty;
|
||||||
|
var oldFileName = string.Empty;
|
||||||
|
var dto = new GenFormDto() { TableName = tableName, Type = GetEnumDescription(type), DataBase = databaseKey };
|
||||||
|
|
||||||
|
var provider = _dataSourceManager.GetProvider(databaseKey ?? DataSourceConstants.Admin);
|
||||||
|
var entityName = _pathResolver.GetEntityName(tableName, provider.Config);
|
||||||
|
var entityNameWithPath = provider.Config.UsesPluralPath ? entityName + "s" : entityName;
|
||||||
|
|
||||||
|
var fileName = FindCodeFileClassName(dto);
|
||||||
|
var path = string.Empty;
|
||||||
|
//获取表路径信息
|
||||||
|
var tableInfo = GetGenContextDtoByTableName(tableName, databaseKey);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case FileTypeEnum.Model:
|
||||||
|
path = provider.Config.UsesPluralPath
|
||||||
|
? $"{tableInfo.ModelPath}/{entityNameWithPath}"
|
||||||
|
: tableInfo.ModelPath;
|
||||||
|
break;
|
||||||
|
case FileTypeEnum.Service:
|
||||||
|
path = provider.Config.UsesPluralPath
|
||||||
|
? $"{tableInfo.ServicePath}/{entityNameWithPath}"
|
||||||
|
: tableInfo.ServicePath;
|
||||||
|
break;
|
||||||
|
case FileTypeEnum.Controller:
|
||||||
|
path = provider.Config.UsesPluralPath
|
||||||
|
? $"{tableInfo.ControllerPath}/{entityNameWithPath}"
|
||||||
|
: tableInfo.ControllerPath;
|
||||||
|
break;
|
||||||
|
case FileTypeEnum.ClientIndex:
|
||||||
|
path = tableInfo.ClientIndexPath + $"/{tableName}s";
|
||||||
|
break;
|
||||||
|
case FileTypeEnum.ClientInfo:
|
||||||
|
path = tableInfo.ClientInfoPath + $"/{tableName}s";
|
||||||
|
break;
|
||||||
|
case FileTypeEnum.ClientService:
|
||||||
|
path = tableInfo.ClientServicePath + $"/{tableName}s";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileDirPath = Path.Combine(path);
|
||||||
|
if (!Directory.Exists(fileDirPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(fileDirPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组合成完整路劲
|
||||||
|
var filePath = $"{fileDirPath}/{fileName}";
|
||||||
|
// 判断是否覆盖文件
|
||||||
|
if (!(tableInfo.IsCover ?? false))
|
||||||
|
{
|
||||||
|
// 如果文件已存在 加尾缀 重新创建文件夹
|
||||||
|
if (File.Exists(filePath))
|
||||||
|
{
|
||||||
|
oldFileName = FindCodeFileClassName(dto);
|
||||||
|
replaceName = $"{oldFileName}{DateTime.Now.ToString("yyyyMMddHHmmss")}";
|
||||||
|
filePath = $"{fileDirPath}/{replaceName}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (filePath, oldFileName, replaceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存到文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName"></param>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="filePath"></param>
|
||||||
|
/// <param name="oldName"></param>
|
||||||
|
/// <param name="replaceName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task SaveToFileAsync(string tableName, FileTypeEnum type, string filePath, string oldName, string replaceName)
|
||||||
|
{
|
||||||
|
var dto = new GenFormDto() { TableName = tableName, Type = GetEnumDescription(type) };
|
||||||
|
var codeString = await GetCodeByTypeAndTableNameAsync(dto);
|
||||||
|
if (!string.IsNullOrWhiteSpace(replaceName) && !string.IsNullOrWhiteSpace(oldName))
|
||||||
|
{
|
||||||
|
if (type == FileTypeEnum.Model || type == FileTypeEnum.Service || type == FileTypeEnum.Controller)
|
||||||
|
{
|
||||||
|
codeString = codeString.Replace(oldName, replaceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await Task.Delay(500);
|
||||||
|
await File.WriteAllTextAsync(filePath, codeString, Encoding.UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取枚举上的描述特性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string GetEnumDescription(FileTypeEnum type)
|
||||||
|
{
|
||||||
|
return type.GetType().GetField(Enum.GetName(type)).GetCustomAttribute<DescriptionAttribute>().Description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存表元信息到配置文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableDto">表信息</param>
|
||||||
|
private async Task SaveTableMetaConfigAsync(GenDbTableDto tableDto)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(tableDto.DataBase) || string.IsNullOrEmpty(tableDto.TableName))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = new TableMetaConfig
|
||||||
|
{
|
||||||
|
DisplayName = tableDto.DisplayName,
|
||||||
|
EntityName = tableDto.EntityName,
|
||||||
|
Remark = tableDto.Remark,
|
||||||
|
ModelPath = tableDto.ModelPath,
|
||||||
|
ServicePath = tableDto.ServicePath,
|
||||||
|
ControllerPath = tableDto.ControllerPath,
|
||||||
|
ClientIndexPath = tableDto.ClientIndexPath,
|
||||||
|
ClientInfoPath = tableDto.ClientInfoPath,
|
||||||
|
ClientServicePath = tableDto.ClientServicePath,
|
||||||
|
IsCover = tableDto.IsCover ?? false,
|
||||||
|
Columns = new Dictionary<string, ColumnMetaConfig>()
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存列配置
|
||||||
|
if (tableDto.TableInfos != null)
|
||||||
|
{
|
||||||
|
foreach (var column in tableDto.TableInfos)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(column.ColumnName))
|
||||||
|
{
|
||||||
|
config.Columns[column.ColumnName] = new ColumnMetaConfig
|
||||||
|
{
|
||||||
|
DisplayName = column.DisplayName,
|
||||||
|
Describe = column.Describe,
|
||||||
|
CsField = column.CsField,
|
||||||
|
IsTableSelect = column.IsTableSelect,
|
||||||
|
IsImageId = column.IsImageId,
|
||||||
|
IsTableColumnShow = column.IsTableColumnShow
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await _tableMetaConfigService.SaveConfigAsync(tableDto.DataBase, tableDto.TableName, config);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum FileTypeEnum
|
||||||
|
{
|
||||||
|
[Description("MiaoYu.Models")]
|
||||||
|
Model,
|
||||||
|
[Description("MiaoYu.Services.Admin")]
|
||||||
|
Service,
|
||||||
|
[Description("MiaoYu.Controllers.Admin")]
|
||||||
|
Controller,
|
||||||
|
[Description("Client.Index")]
|
||||||
|
ClientIndex,
|
||||||
|
[Description("Client.Info")]
|
||||||
|
ClientInfo,
|
||||||
|
[Description("Client.Service")]
|
||||||
|
ClientService
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库表服务
|
||||||
|
/// </summary>
|
||||||
|
public class DatabaseTableService : IDatabaseTableService
|
||||||
|
{
|
||||||
|
private readonly ITableSchemaCache _tableSchemaCache;
|
||||||
|
private readonly ITableMetaConfigService _tableMetaConfigService;
|
||||||
|
private readonly ILogger<DatabaseTableService> _logger;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableSchemaCache">表结构缓存</param>
|
||||||
|
/// <param name="tableMetaConfigService">表元信息配置服务</param>
|
||||||
|
/// <param name="logger">日志</param>
|
||||||
|
public DatabaseTableService(
|
||||||
|
ITableSchemaCache tableSchemaCache,
|
||||||
|
ITableMetaConfigService tableMetaConfigService,
|
||||||
|
ILogger<DatabaseTableService> logger)
|
||||||
|
{
|
||||||
|
_tableSchemaCache = tableSchemaCache;
|
||||||
|
_tableMetaConfigService = tableMetaConfigService;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有的表 包含表下面的列(支持多数据源)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>所有表信息列表</returns>
|
||||||
|
public virtual List<DbTableInfo> GetAllTableInfos()
|
||||||
|
{
|
||||||
|
return _tableSchemaCache.GetAllTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有的表(合并缓存和配置文件)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual List<GenDbTableDto> GetAllTables()
|
||||||
|
{
|
||||||
|
var schemaTables = _tableSchemaCache.GetAllTables();
|
||||||
|
var result = new List<GenDbTableDto>();
|
||||||
|
|
||||||
|
foreach (var schemaTable in schemaTables)
|
||||||
|
{
|
||||||
|
var genTable = MergeTableWithConfig(schemaTable);
|
||||||
|
result.Add(genTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取表信息根据缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<GenDbTableDto> GetAllTablesByCache() => GetAllTables();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清空所有表缓存信息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool ClearAllTablesByCache()
|
||||||
|
{
|
||||||
|
_tableSchemaCache.ClearCache();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 刷新缓存
|
||||||
|
/// </summary>
|
||||||
|
public void RefreshCache()
|
||||||
|
{
|
||||||
|
_tableSchemaCache.RefreshCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取数据库名称
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string? GetDatabaseName()
|
||||||
|
{
|
||||||
|
var tables = _tableSchemaCache.GetAllTables();
|
||||||
|
return tables.FirstOrDefault()?.DataBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 合并表结构和配置文件信息
|
||||||
|
/// </summary>
|
||||||
|
private GenDbTableDto MergeTableWithConfig(DbTableInfo schemaTable)
|
||||||
|
{
|
||||||
|
var genTable = new GenDbTableDto
|
||||||
|
{
|
||||||
|
TableName = schemaTable.Name,
|
||||||
|
DataBase = schemaTable.DataBase,
|
||||||
|
Schema = schemaTable.Schema,
|
||||||
|
Type = schemaTable.Type,
|
||||||
|
Remark = schemaTable.Comment,
|
||||||
|
TableInfos = schemaTable.Columns?.Select(c => new LowCodeTableInfo
|
||||||
|
{
|
||||||
|
ColumnName = c.Name,
|
||||||
|
IsPrimary = c.IsPrimary,
|
||||||
|
IsIdentity = c.IsIdentity,
|
||||||
|
IsNullable = c.IsNullable,
|
||||||
|
Position = c.Position,
|
||||||
|
DatabaseColumnType = c.DbType,
|
||||||
|
CsType = c.CsType,
|
||||||
|
MaxLength = c.MaxLength,
|
||||||
|
Describe = c.Comment
|
||||||
|
}).ToList() ?? new List<LowCodeTableInfo>()
|
||||||
|
};
|
||||||
|
|
||||||
|
// 尝试从配置文件加载元信息
|
||||||
|
if (!string.IsNullOrEmpty(schemaTable.DataBase) && !string.IsNullOrEmpty(schemaTable.Name))
|
||||||
|
{
|
||||||
|
var config = _tableMetaConfigService.LoadConfig(schemaTable.DataBase, schemaTable.Name);
|
||||||
|
if (config != null)
|
||||||
|
{
|
||||||
|
// 使用配置文件中的元信息覆盖
|
||||||
|
genTable.DisplayName = config.DisplayName;
|
||||||
|
genTable.EntityName = config.EntityName;
|
||||||
|
genTable.Remark = config.Remark ?? genTable.Remark;
|
||||||
|
genTable.ModelPath = config.ModelPath;
|
||||||
|
genTable.ServicePath = config.ServicePath;
|
||||||
|
genTable.ControllerPath = config.ControllerPath;
|
||||||
|
genTable.ClientIndexPath = config.ClientIndexPath;
|
||||||
|
genTable.ClientInfoPath = config.ClientInfoPath;
|
||||||
|
genTable.ClientServicePath = config.ClientServicePath;
|
||||||
|
genTable.IsCover = config.IsCover;
|
||||||
|
|
||||||
|
// 合并列配置
|
||||||
|
if (config.Columns != null && genTable.TableInfos != null)
|
||||||
|
{
|
||||||
|
foreach (var columnInfo in genTable.TableInfos)
|
||||||
|
{
|
||||||
|
if (config.Columns.TryGetValue(columnInfo.ColumnName ?? "", out var columnConfig))
|
||||||
|
{
|
||||||
|
columnInfo.DisplayName = columnConfig.DisplayName;
|
||||||
|
columnInfo.Describe = columnConfig.Describe ?? columnInfo.Describe;
|
||||||
|
columnInfo.CsField = columnConfig.CsField;
|
||||||
|
columnInfo.IsTableSelect = columnConfig.IsTableSelect;
|
||||||
|
columnInfo.IsImageId = columnConfig.IsImageId;
|
||||||
|
columnInfo.IsTableColumnShow = columnConfig.IsTableColumnShow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return genTable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 代码生成服务
|
||||||
|
/// </summary>
|
||||||
|
public interface ICodeGenerationService : IScopedDependency
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 生成上下文集合
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
PagingView GetGenContextDtos(int page, int size, GenFormDto search);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取表字段集合
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName"></param>
|
||||||
|
/// <param name="databaseKey">数据库标识(可选)</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
GenDbTableDto GetGenContextDtoByTableName(string tableName, string? databaseKey = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据 lowCodeTable 填充路径
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lowCodeTable"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
LowCodeTable FillPathByLowCodeTable(LowCodeTable lowCodeTable);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取代码生成上下文
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
GenDbTableDto GetGenContextDto(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成 model
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<string> GenModelAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成 service
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<string> GenServiceAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成 controller
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<string> GenControllerAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成 serviceJs
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<string> GenServiceJsAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成 Index
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<string> GenIndexAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成 Info
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<string> GenInfoAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取代码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<string> GetCodeByTypeAndTableNameAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下载
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<(byte[] codeBytes, string contentType, string fileName)> DownloadAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据类型下载类型下所有的代码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<(byte[] codeBytes, string contentType, string fileName)> DownloadAllAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建所有代码文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<bool> CreateAllCodeFilesAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建数据字典文件 excel
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
(byte[] excel, string dataBase) CreateDataDictionary();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 代码生成自动导入项目
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="genFormDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task AutoImprotProjectAsync(GenFormDto genFormDto);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有数据库列表
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<DataSourceDto> GetAllDataSources();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库表服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface IDatabaseTableService : IScopedDependency
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有的表 包含表下面的列(支持多数据源)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>所有表信息列表</returns>
|
||||||
|
List<DbTableInfo> GetAllTableInfos();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有的表 包含表下面的列
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<GenDbTableDto> GetAllTables();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取表信息根据缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<GenDbTableDto> GetAllTablesByCache();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清空所有表缓存信息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool ClearAllTablesByCache();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 刷新缓存
|
||||||
|
/// </summary>
|
||||||
|
void RefreshCache();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取数据库名称
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
string? GetDatabaseName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表元信息配置服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface ITableMetaConfigService : IScopedDependency
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 加载表元信息配置
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="databaseKey">数据库标识</param>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <returns>配置对象,不存在则返回 null</returns>
|
||||||
|
TableMetaConfig? LoadConfig(string databaseKey, string tableName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存表元信息配置
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="databaseKey">数据库标识</param>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <param name="config">配置对象</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task SaveConfigAsync(string databaseKey, string tableName, TableMetaConfig config);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查配置文件是否存在
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="databaseKey">数据库标识</param>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool ExistsConfig(string databaseKey, string tableName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除配置文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="databaseKey">数据库标识</param>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task DeleteConfigAsync(string databaseKey, string tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表结构缓存接口
|
||||||
|
/// </summary>
|
||||||
|
public interface ITableSchemaCache : IScopedDependency
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有表信息(从缓存或数据库)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<DbTableInfo> GetAllTables();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 刷新缓存
|
||||||
|
/// </summary>
|
||||||
|
void RefreshCache();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清除缓存
|
||||||
|
/// </summary>
|
||||||
|
void ClearCache();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据数据库和表名获取表信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="databaseKey">数据库标识</param>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
DbTableInfo? GetTable(string databaseKey, string tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表元信息配置服务实现
|
||||||
|
/// </summary>
|
||||||
|
[Component]
|
||||||
|
public class TableMetaConfigService : ITableMetaConfigService
|
||||||
|
{
|
||||||
|
private readonly IWebHostEnvironment _environment;
|
||||||
|
private readonly ILogger<TableMetaConfigService> _logger;
|
||||||
|
|
||||||
|
// JSON 序列化选项
|
||||||
|
private static readonly JsonSerializerOptions _jsonOptions = new()
|
||||||
|
{
|
||||||
|
WriteIndented = true,
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||||
|
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull,
|
||||||
|
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||||
|
};
|
||||||
|
|
||||||
|
public TableMetaConfigService(IWebHostEnvironment environment, ILogger<TableMetaConfigService> logger)
|
||||||
|
{
|
||||||
|
_environment = environment;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取配置文件路径
|
||||||
|
/// </summary>
|
||||||
|
private string GetConfigFilePath(string databaseKey, string tableName)
|
||||||
|
{
|
||||||
|
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
var configDir = Path.Combine(baseDir, "CodeGenConfig", databaseKey);
|
||||||
|
|
||||||
|
// 确保目录存在
|
||||||
|
if (!Directory.Exists(configDir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(configDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Path.Combine(configDir, $"{tableName}.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载表元信息配置
|
||||||
|
/// </summary>
|
||||||
|
public TableMetaConfig? LoadConfig(string databaseKey, string tableName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filePath = GetConfigFilePath(databaseKey, tableName);
|
||||||
|
|
||||||
|
if (!File.Exists(filePath))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var json = File.ReadAllText(filePath);
|
||||||
|
var config = JsonSerializer.Deserialize<TableMetaConfig>(json, _jsonOptions);
|
||||||
|
|
||||||
|
_logger.LogDebug("成功加载配置: {DatabaseKey}/{TableName}", databaseKey, tableName);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "加载配置文件失败: {DatabaseKey}/{TableName}", databaseKey, tableName);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存表元信息配置
|
||||||
|
/// </summary>
|
||||||
|
public async Task SaveConfigAsync(string databaseKey, string tableName, TableMetaConfig config)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filePath = GetConfigFilePath(databaseKey, tableName);
|
||||||
|
var json = JsonSerializer.Serialize(config, _jsonOptions);
|
||||||
|
|
||||||
|
await File.WriteAllTextAsync(filePath, json);
|
||||||
|
|
||||||
|
_logger.LogInformation("成功保存配置: {DatabaseKey}/{TableName}", databaseKey, tableName);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "保存配置文件失败: {DatabaseKey}/{TableName}", databaseKey, tableName);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查配置文件是否存在
|
||||||
|
/// </summary>
|
||||||
|
public bool ExistsConfig(string databaseKey, string tableName)
|
||||||
|
{
|
||||||
|
var filePath = GetConfigFilePath(databaseKey, tableName);
|
||||||
|
return File.Exists(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除配置文件
|
||||||
|
/// </summary>
|
||||||
|
public async Task DeleteConfigAsync(string databaseKey, string tableName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filePath = GetConfigFilePath(databaseKey, tableName);
|
||||||
|
|
||||||
|
if (File.Exists(filePath))
|
||||||
|
{
|
||||||
|
await Task.Run(() => File.Delete(filePath));
|
||||||
|
_logger.LogInformation("成功删除配置: {DatabaseKey}/{TableName}", databaseKey, tableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "删除配置文件失败: {DatabaseKey}/{TableName}", databaseKey, tableName);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
namespace MiaoYu.Core.CodeGenerator.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表结构缓存服务实现
|
||||||
|
/// </summary>
|
||||||
|
[Component]
|
||||||
|
public class TableSchemaCache : ITableSchemaCache
|
||||||
|
{
|
||||||
|
private readonly IMemoryCache _memoryCache;
|
||||||
|
private readonly DataSourceManager _dataSourceManager;
|
||||||
|
private readonly ILogger<TableSchemaCache> _logger;
|
||||||
|
|
||||||
|
private const string CACHE_KEY = "CodeGenerator:AllTables";
|
||||||
|
private static readonly TimeSpan CACHE_DURATION = TimeSpan.FromMinutes(20);
|
||||||
|
|
||||||
|
public TableSchemaCache(
|
||||||
|
IMemoryCache memoryCache,
|
||||||
|
DataSourceManager dataSourceManager,
|
||||||
|
ILogger<TableSchemaCache> logger)
|
||||||
|
{
|
||||||
|
_memoryCache = memoryCache;
|
||||||
|
_dataSourceManager = dataSourceManager;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有表信息(从缓存或数据库)
|
||||||
|
/// </summary>
|
||||||
|
public List<DbTableInfo> GetAllTables()
|
||||||
|
{
|
||||||
|
return _memoryCache.GetOrCreate(CACHE_KEY, entry =>
|
||||||
|
{
|
||||||
|
entry.SlidingExpiration = CACHE_DURATION;
|
||||||
|
|
||||||
|
_logger.LogInformation("缓存未命中,从数据库查询表结构信息");
|
||||||
|
|
||||||
|
var tables = _dataSourceManager.GetAllTables();
|
||||||
|
|
||||||
|
_logger.LogInformation("成功加载 {Count} 个表到缓存", tables.Count);
|
||||||
|
|
||||||
|
return tables;
|
||||||
|
}) ?? new List<DbTableInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 刷新缓存
|
||||||
|
/// </summary>
|
||||||
|
public void RefreshCache()
|
||||||
|
{
|
||||||
|
_logger.LogInformation("手动刷新表结构缓存");
|
||||||
|
|
||||||
|
_memoryCache.Remove(CACHE_KEY);
|
||||||
|
|
||||||
|
// 重新加载
|
||||||
|
GetAllTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清除缓存
|
||||||
|
/// </summary>
|
||||||
|
public void ClearCache()
|
||||||
|
{
|
||||||
|
_logger.LogInformation("清除表结构缓存");
|
||||||
|
_memoryCache.Remove(CACHE_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据数据库和表名获取表信息
|
||||||
|
/// </summary>
|
||||||
|
public DbTableInfo? GetTable(string databaseKey, string tableName)
|
||||||
|
{
|
||||||
|
var allTables = GetAllTables();
|
||||||
|
|
||||||
|
return allTables.FirstOrDefault(t =>
|
||||||
|
t.DataBase?.Equals(databaseKey, StringComparison.OrdinalIgnoreCase) == true &&
|
||||||
|
t.Name?.Equals(tableName, StringComparison.OrdinalIgnoreCase) == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
22
admin-server/MiaoYu.Core.CodeGenerator/Usings.cs
Normal file
22
admin-server/MiaoYu.Core.CodeGenerator/Usings.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
global using System;
|
||||||
|
global using System.Collections.Generic;
|
||||||
|
global using System.Linq;
|
||||||
|
global using System.Text;
|
||||||
|
global using System.Threading.Tasks;
|
||||||
|
global using System.IO;
|
||||||
|
global using System.Reflection;
|
||||||
|
global using System.ComponentModel;
|
||||||
|
global using Microsoft.Extensions.DependencyInjection;
|
||||||
|
global using Microsoft.Extensions.Caching.Memory;
|
||||||
|
global using Microsoft.Extensions.Logging;
|
||||||
|
global using Microsoft.AspNetCore.Hosting;
|
||||||
|
global using NPOI.XSSF.UserModel;
|
||||||
|
global using HZY.Framework.DependencyInjection;
|
||||||
|
global using HZY.Framework.DependencyInjection.Attributes;
|
||||||
|
global using MiaoYu.Core.Logs;
|
||||||
|
global using MiaoYu.Core.Razor.Services;
|
||||||
|
global using MiaoYu.Core.CodeGenerator.Abstractions;
|
||||||
|
global using MiaoYu.Core.CodeGenerator.Core;
|
||||||
|
global using MiaoYu.Core.CodeGenerator.Models;
|
||||||
|
global using MiaoYu.Core.CodeGenerator.Services;
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<doc>
|
<doc>
|
||||||
<assembly>
|
<assembly>
|
||||||
<name>MiaoYu.Core.FreeSql</name>
|
<name>MiaoYu.Core.FreeSql</name>
|
||||||
|
|
|
||||||
591
admin-server/前端接口对接文档.md
Normal file
591
admin-server/前端接口对接文档.md
Normal file
|
|
@ -0,0 +1,591 @@
|
||||||
|
# 低代码生成平台 - 前端接口对接文档
|
||||||
|
|
||||||
|
## 📋 更新概述
|
||||||
|
|
||||||
|
本次后端更新新增了数据库选择功能,支持按数据库筛选表列表。前端需要相应修改以支持以下功能:
|
||||||
|
|
||||||
|
1. **新增接口**:获取数据库列表
|
||||||
|
2. **增强接口**:表列表接口支持按数据库筛选
|
||||||
|
3. **返回数据变更**:表列表返回数据新增 `dataBase` 字段
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🆕 1. 新增接口:获取数据库列表
|
||||||
|
|
||||||
|
### 接口信息
|
||||||
|
|
||||||
|
- **请求路径**:`GET /api/CodeGeneration/databases`
|
||||||
|
- **请求方法**:`GET`
|
||||||
|
- **是否需要认证**:是
|
||||||
|
- **描述**:获取所有可用的数据库列表,用于前端下拉框选择
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
|
||||||
|
无
|
||||||
|
|
||||||
|
### 响应示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"key": "Admin",
|
||||||
|
"displayName": "主数据库"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "MiaoYuChat",
|
||||||
|
"displayName": "喵语聊天"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "LiveForum",
|
||||||
|
"displayName": "论坛系统"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 响应字段说明
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| key | string | 数据库标识,用于后续接口传参 |
|
||||||
|
| displayName | string | 显示名称,用于前端展示 |
|
||||||
|
|
||||||
|
### 前端使用示例
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 1. 定义接口类型
|
||||||
|
interface DataSource {
|
||||||
|
key: string;
|
||||||
|
displayName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 调用接口
|
||||||
|
const getDatabases = async (): Promise<DataSource[]> => {
|
||||||
|
const response = await axios.get('/api/CodeGeneration/databases');
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 3. 使用示例(页面加载时)
|
||||||
|
onMounted(async () => {
|
||||||
|
const databases = await getDatabases();
|
||||||
|
// 填充到下拉框
|
||||||
|
databaseOptions.value = databases;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ 2. 修改接口:表列表查询
|
||||||
|
|
||||||
|
### 接口信息
|
||||||
|
|
||||||
|
- **请求路径**:`POST /api/CodeGeneration/{size}/{page}`
|
||||||
|
- **请求方法**:`POST`
|
||||||
|
- **是否需要认证**:是
|
||||||
|
- **描述**:获取表列表,支持按表名和数据库筛选
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
|
||||||
|
**路径参数:**
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 说明 |
|
||||||
|
|--------|------|------|------|
|
||||||
|
| size | number | 是 | 每页条数 |
|
||||||
|
| page | number | 是 | 页码 |
|
||||||
|
|
||||||
|
**Body 参数(JSON):**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tableName": "User", // 可选,表名模糊搜索
|
||||||
|
"dataBase": "Admin" // 🆕 新增,数据库标识筛选
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 请求字段说明
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 必填 | 说明 |
|
||||||
|
|--------|------|------|------|
|
||||||
|
| tableName | string | 否 | 表名,支持模糊搜索 |
|
||||||
|
| dataBase | string | 否 | 🆕 数据库标识,不传则返回所有数据库的表 |
|
||||||
|
|
||||||
|
### 响应示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"total": 25,
|
||||||
|
"page": 1,
|
||||||
|
"size": 10,
|
||||||
|
"pageCount": 3,
|
||||||
|
"dataSource": [
|
||||||
|
{
|
||||||
|
"tableName": "Users",
|
||||||
|
"remark": "用户表",
|
||||||
|
"dataBase": "Admin" // 🆕 新增字段
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "T_Image_Config",
|
||||||
|
"remark": "图片配置表",
|
||||||
|
"dataBase": "MiaoYuChat" // 🆕 新增字段
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 响应字段说明
|
||||||
|
|
||||||
|
| 字段名 | 类型 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| tableName | string | 表名 |
|
||||||
|
| remark | string | 表备注/描述 |
|
||||||
|
| dataBase | string | 🆕 表所属的数据库标识 |
|
||||||
|
|
||||||
|
### 前端使用示例
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 1. 定义接口类型
|
||||||
|
interface TableListItem {
|
||||||
|
tableName: string;
|
||||||
|
remark: string;
|
||||||
|
dataBase: string; // 🆕 新增字段
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TableListRequest {
|
||||||
|
tableName?: string;
|
||||||
|
dataBase?: string; // 🆕 新增字段
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 调用接口
|
||||||
|
const getTableList = async (
|
||||||
|
page: number,
|
||||||
|
size: number,
|
||||||
|
search: TableListRequest
|
||||||
|
): Promise<PagingResult<TableListItem>> => {
|
||||||
|
const response = await axios.post(
|
||||||
|
`/api/CodeGeneration/${size}/${page}`,
|
||||||
|
search
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 3. 使用示例(带数据库筛选)
|
||||||
|
const loadTableList = async () => {
|
||||||
|
const result = await getTableList(1, 10, {
|
||||||
|
tableName: searchKeyword.value,
|
||||||
|
dataBase: selectedDatabase.value // 🆕 传递选中的数据库
|
||||||
|
});
|
||||||
|
tableList.value = result.dataSource;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 3. 代码生成接口参数调整
|
||||||
|
|
||||||
|
### 影响的接口
|
||||||
|
|
||||||
|
以下接口在调用时,需要确保 `dataBase` 参数正确传递:
|
||||||
|
|
||||||
|
1. **获取代码**:`POST /api/CodeGeneration/GetCodeAsync`
|
||||||
|
2. **下载代码**:`POST /api/CodeGeneration/DownloadAsync`
|
||||||
|
3. **下载所有代码**:`POST /api/CodeGeneration/DownloadAllAsync`
|
||||||
|
4. **自动导入项目**:`POST /api/CodeGeneration/AutoImprotProjectAsync`
|
||||||
|
|
||||||
|
### 请求 Body 示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tableName": "T_Image_Config",
|
||||||
|
"dataBase": "MiaoYuChat", // ⚠️ 必须传递,确保准确匹配表
|
||||||
|
"type": "MiaoYu.Models"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前端使用示例
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 生成代码时,从表列表中获取 dataBase 并传递
|
||||||
|
const generateCode = async (table: TableListItem, type: string) => {
|
||||||
|
const response = await axios.post('/api/CodeGeneration/GetCodeAsync', {
|
||||||
|
tableName: table.tableName,
|
||||||
|
dataBase: table.dataBase, // 🆕 必须传递
|
||||||
|
type: type
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 4. 前端需要修改的地方
|
||||||
|
|
||||||
|
### 4.1 页面布局调整
|
||||||
|
|
||||||
|
在表列表页面顶部新增数据库选择器:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div class="code-generation-page">
|
||||||
|
<!-- 🆕 新增:数据库选择器 -->
|
||||||
|
<div class="filter-section">
|
||||||
|
<a-select
|
||||||
|
v-model:value="selectedDatabase"
|
||||||
|
placeholder="选择数据库"
|
||||||
|
style="width: 200px"
|
||||||
|
@change="handleDatabaseChange"
|
||||||
|
>
|
||||||
|
<a-select-option value="">全部数据库</a-select-option>
|
||||||
|
<a-select-option
|
||||||
|
v-for="db in databaseList"
|
||||||
|
:key="db.key"
|
||||||
|
:value="db.key"
|
||||||
|
>
|
||||||
|
{{ db.displayName }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
|
||||||
|
<!-- 原有的搜索框 -->
|
||||||
|
<a-input
|
||||||
|
v-model:value="searchKeyword"
|
||||||
|
placeholder="搜索表名"
|
||||||
|
style="width: 300px; margin-left: 10px"
|
||||||
|
@change="handleSearch"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 表格列表 -->
|
||||||
|
<a-table :columns="columns" :data-source="tableList">
|
||||||
|
<!-- 🆕 新增:显示数据库标识列 -->
|
||||||
|
<a-table-column key="dataBase" title="数据库" data-index="dataBase" />
|
||||||
|
<a-table-column key="tableName" title="表名" data-index="tableName" />
|
||||||
|
<a-table-column key="remark" title="说明" data-index="remark" />
|
||||||
|
<!-- 其他列... -->
|
||||||
|
</a-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 状态管理
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
|
||||||
|
// 🆕 新增状态
|
||||||
|
const databaseList = ref<DataSource[]>([]);
|
||||||
|
const selectedDatabase = ref<string>(''); // 空字符串表示全部
|
||||||
|
|
||||||
|
// 原有状态
|
||||||
|
const tableList = ref<TableListItem[]>([]);
|
||||||
|
const searchKeyword = ref<string>('');
|
||||||
|
|
||||||
|
// 🆕 页面加载时获取数据库列表
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadDatabases();
|
||||||
|
await loadTableList();
|
||||||
|
});
|
||||||
|
|
||||||
|
const loadDatabases = async () => {
|
||||||
|
databaseList.value = await getDatabases();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 🆕 数据库切换事件
|
||||||
|
const handleDatabaseChange = () => {
|
||||||
|
loadTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 修改:加载表列表时传递数据库参数
|
||||||
|
const loadTableList = async () => {
|
||||||
|
const result = await getTableList(1, 10, {
|
||||||
|
tableName: searchKeyword.value,
|
||||||
|
dataBase: selectedDatabase.value // 🆕 传递数据库参数
|
||||||
|
});
|
||||||
|
tableList.value = result.dataSource;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 生成代码时传递数据库
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ⚠️ 重要:生成代码时必须传递 dataBase
|
||||||
|
const handleGenerateCode = async (record: TableListItem) => {
|
||||||
|
const code = await generateCode({
|
||||||
|
tableName: record.tableName,
|
||||||
|
dataBase: record.dataBase, // 🆕 从表列表记录中获取
|
||||||
|
type: selectedCodeType.value
|
||||||
|
});
|
||||||
|
// 展示生成的代码...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 5. 注意事项
|
||||||
|
|
||||||
|
### 5.1 兼容性说明
|
||||||
|
|
||||||
|
- **向后兼容**:`dataBase` 字段为可选,不传时返回所有数据库的表(保持原有行为)
|
||||||
|
- **推荐实践**:建议前端始终传递 `dataBase` 参数,避免同名表冲突
|
||||||
|
|
||||||
|
### 5.2 同名表处理
|
||||||
|
|
||||||
|
后端支持不同数据库中存在同名表,因此:
|
||||||
|
|
||||||
|
- 表列表中可能出现多个同名的表,通过 `dataBase` 字段区分
|
||||||
|
- 生成代码时**必须**传递 `dataBase` 参数,确保操作正确的表
|
||||||
|
|
||||||
|
### 5.3 UI/UX 建议
|
||||||
|
|
||||||
|
1. **数据库标识显示**:
|
||||||
|
- 在表名前添加数据库标签,如 `[Admin] Users`、`[MiaoYuChat] T_Image_Config`
|
||||||
|
- 使用不同颜色或图标区分不同数据库
|
||||||
|
|
||||||
|
2. **默认选择**:
|
||||||
|
- 建议默认选择第一个数据库,而不是"全部"
|
||||||
|
- 可根据用户最近使用的数据库进行智能默认
|
||||||
|
|
||||||
|
3. **表格列顺序**:
|
||||||
|
- 建议顺序:数据库 → 表名 → 说明 → 操作
|
||||||
|
- 数据库列可以考虑使用标签样式展示
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 6. 完整示例代码
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// types.ts
|
||||||
|
export interface DataSource {
|
||||||
|
key: string;
|
||||||
|
displayName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TableListItem {
|
||||||
|
tableName: string;
|
||||||
|
remark: string;
|
||||||
|
dataBase: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TableListRequest {
|
||||||
|
tableName?: string;
|
||||||
|
dataBase?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// api.ts
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export const codeGenerationApi = {
|
||||||
|
// 🆕 获取数据库列表
|
||||||
|
getDatabases: (): Promise<DataSource[]> => {
|
||||||
|
return axios.get('/api/CodeGeneration/databases').then(res => res.data);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取表列表(已修改)
|
||||||
|
getTableList: (page: number, size: number, search: TableListRequest) => {
|
||||||
|
return axios.post(`/api/CodeGeneration/${size}/${page}`, search)
|
||||||
|
.then(res => res.data);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 生成代码(已修改)
|
||||||
|
generateCode: (params: {
|
||||||
|
tableName: string;
|
||||||
|
dataBase: string;
|
||||||
|
type: string;
|
||||||
|
}) => {
|
||||||
|
return axios.post('/api/CodeGeneration/GetCodeAsync', params)
|
||||||
|
.then(res => res.data);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 其他接口...
|
||||||
|
};
|
||||||
|
|
||||||
|
// page.vue
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { codeGenerationApi } from '@/api/codeGeneration';
|
||||||
|
import type { DataSource, TableListItem } from '@/types/codeGeneration';
|
||||||
|
|
||||||
|
// 状态
|
||||||
|
const databaseList = ref<DataSource[]>([]);
|
||||||
|
const selectedDatabase = ref<string>('');
|
||||||
|
const tableList = ref<TableListItem[]>([]);
|
||||||
|
const searchKeyword = ref<string>('');
|
||||||
|
const pagination = ref({ page: 1, size: 10, total: 0 });
|
||||||
|
|
||||||
|
// 生命周期
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadDatabases();
|
||||||
|
await loadTableList();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载数据库列表
|
||||||
|
const loadDatabases = async () => {
|
||||||
|
try {
|
||||||
|
databaseList.value = await codeGenerationApi.getDatabases();
|
||||||
|
// 可选:默认选择第一个数据库
|
||||||
|
// if (databaseList.value.length > 0) {
|
||||||
|
// selectedDatabase.value = databaseList.value[0].key;
|
||||||
|
// }
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载数据库列表失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载表列表
|
||||||
|
const loadTableList = async () => {
|
||||||
|
try {
|
||||||
|
const result = await codeGenerationApi.getTableList(
|
||||||
|
pagination.value.page,
|
||||||
|
pagination.value.size,
|
||||||
|
{
|
||||||
|
tableName: searchKeyword.value,
|
||||||
|
dataBase: selectedDatabase.value
|
||||||
|
}
|
||||||
|
);
|
||||||
|
tableList.value = result.dataSource;
|
||||||
|
pagination.value.total = result.total;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载表列表失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 事件处理
|
||||||
|
const handleDatabaseChange = () => {
|
||||||
|
pagination.value.page = 1; // 重置页码
|
||||||
|
loadTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = () => {
|
||||||
|
pagination.value.page = 1; // 重置页码
|
||||||
|
loadTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGenerateCode = async (record: TableListItem) => {
|
||||||
|
try {
|
||||||
|
const code = await codeGenerationApi.generateCode({
|
||||||
|
tableName: record.tableName,
|
||||||
|
dataBase: record.dataBase,
|
||||||
|
type: 'MiaoYu.Models'
|
||||||
|
});
|
||||||
|
// 展示代码...
|
||||||
|
} catch (error) {
|
||||||
|
console.error('生成代码失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="code-generation-page">
|
||||||
|
<!-- 筛选区域 -->
|
||||||
|
<div class="filter-section">
|
||||||
|
<a-space>
|
||||||
|
<a-select
|
||||||
|
v-model:value="selectedDatabase"
|
||||||
|
placeholder="选择数据库"
|
||||||
|
style="width: 200px"
|
||||||
|
@change="handleDatabaseChange"
|
||||||
|
>
|
||||||
|
<a-select-option value="">全部数据库</a-select-option>
|
||||||
|
<a-select-option
|
||||||
|
v-for="db in databaseList"
|
||||||
|
:key="db.key"
|
||||||
|
:value="db.key"
|
||||||
|
>
|
||||||
|
{{ db.displayName }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
|
||||||
|
<a-input
|
||||||
|
v-model:value="searchKeyword"
|
||||||
|
placeholder="搜索表名"
|
||||||
|
style="width: 300px"
|
||||||
|
@change="handleSearch"
|
||||||
|
/>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<a-table
|
||||||
|
:data-source="tableList"
|
||||||
|
:pagination="{
|
||||||
|
current: pagination.page,
|
||||||
|
pageSize: pagination.size,
|
||||||
|
total: pagination.total,
|
||||||
|
onChange: (page) => {
|
||||||
|
pagination.page = page;
|
||||||
|
loadTableList();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<a-table-column key="dataBase" title="数据库" data-index="dataBase">
|
||||||
|
<template #default="{ record }">
|
||||||
|
<a-tag :color="getDatabaseColor(record.dataBase)">
|
||||||
|
{{ getDatabaseDisplayName(record.dataBase) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<a-table-column key="tableName" title="表名" data-index="tableName" />
|
||||||
|
<a-table-column key="remark" title="说明" data-index="remark" />
|
||||||
|
<a-table-column key="actions" title="操作">
|
||||||
|
<template #default="{ record }">
|
||||||
|
<a-button type="link" @click="handleGenerateCode(record)">
|
||||||
|
生成代码
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
</a-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.code-generation-page {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 7. 视觉效果建议
|
||||||
|
|
||||||
|
### 数据库标签颜色方案
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const getDatabaseColor = (databaseKey: string): string => {
|
||||||
|
const colorMap: Record<string, string> = {
|
||||||
|
'Admin': 'blue',
|
||||||
|
'MiaoYuChat': 'green',
|
||||||
|
'LiveForum': 'orange'
|
||||||
|
};
|
||||||
|
return colorMap[databaseKey] || 'default';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDatabaseDisplayName = (databaseKey: string): string => {
|
||||||
|
const database = databaseList.value.find(db => db.key === databaseKey);
|
||||||
|
return database?.displayName || databaseKey;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 表格展示效果
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────┬─────────────────┬──────────────┬────────┐
|
||||||
|
│ 数据库 │ 表名 │ 说明 │ 操作 │
|
||||||
|
├────────────┼─────────────────┼──────────────┼────────┤
|
||||||
|
│ [Admin] │ Users │ 用户表 │ 生成 │
|
||||||
|
│ [MiaoYuChat]│ T_Image_Config │ 图片配置表 │ 生成 │
|
||||||
|
│ [Admin] │ Roles │ 角色表 │ 生成 │
|
||||||
|
└────────────┴─────────────────┴──────────────┴────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 8. 技术支持
|
||||||
|
|
||||||
|
如有疑问,请联系后端开发团队。
|
||||||
|
|
||||||
|
**文档版本**:v1.0
|
||||||
|
**更新日期**:2024年
|
||||||
|
**后端版本**:v2.0(支持多数据源)
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user