Merge branch 'master' into LiveForum

This commit is contained in:
zpc 2025-11-12 00:22:52 +08:00
commit 2c9540aeaf
56 changed files with 3909 additions and 76 deletions

View File

@ -7,7 +7,7 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>寰梦后台管理</title>
<script type="module" crossorigin src="/static/js/index-D6L9FI9G.js"></script>
<script type="module" crossorigin src="/static/js/index-B89JIRFb.js"></script>
<link rel="stylesheet" crossorigin href="/static/css/index-CzwB8sLn.css">
</head>

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
body[data-v-b95e5a42]{margin:0;padding:0;overflow:hidden}.login[data-v-b95e5a42]{display:flex;justify-content:center;align-items:center;height:100vh;background:url(/static/jpg/login-1-DvL7JDPn.jpg) no-repeat;background-size:cover}.login .login-card[data-v-b95e5a42]{height:600px;width:1000px;box-shadow:0 16px 48px 16px #000000b8,0 12px 32px #000,0 8px 16px -8px #000;display:flex;border-radius:5px}.login .login-card .flex-left[data-v-b95e5a42]{flex:1;width:450px}.login .login-card .flex-left img[data-v-b95e5a42]{height:100%}.login .login-card .flex-right[data-v-b95e5a42]{flex:1;background-color:#fff;display:flex;justify-content:center;flex-direction:column;border-top-right-radius:5px;border-bottom-right-radius:5px}.login .login-card .title[data-v-b95e5a42]{text-align:center;font-size:30px;padding:20px;font-weight:700}.login .login-card .el-input-group__append[data-v-b95e5a42]{padding:0!important}.login .login-card .el-input-group__append .login-code[data-v-b95e5a42]{height:38px}@media (max-width: 1024px){.flex-left[data-v-b95e5a42]{display:none;flex:0!important}.flex-left img[data-v-b95e5a42]{height:auto!important;width:80%!important}.flex-right[data-v-b95e5a42]{border-radius:5px}}@media (min-width: 600px) and (max-width: 1024px){.login-card[data-v-b95e5a42]{width:70%!important}}@media (max-width: 600px){.login-card[data-v-b95e5a42]{width:100%!important}}.lang-content[data-v-b95e5a42]{position:absolute;right:24px;top:20px}

View File

@ -40,7 +40,6 @@ declare module 'vue' {
AInputSearch: typeof import('ant-design-vue/es')['InputSearch']
ALayout: typeof import('ant-design-vue/es')['Layout']
ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
ALayoutFooter: typeof import('ant-design-vue/es')['LayoutFooter']
ALayoutHeader: typeof import('ant-design-vue/es')['LayoutHeader']
ALayoutSider: typeof import('ant-design-vue/es')['LayoutSider']
AMenu: typeof import('ant-design-vue/es')['Menu']
@ -82,7 +81,6 @@ declare module 'vue' {
AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger']
BarChartTransverse: typeof import('./core/components/charts/BarChartTransverse.vue')['default']
ColumnSetting: typeof import('./core/components/curd/components/ColumnSetting.vue')['default']
copy: typeof import('./core/components/layouts/LayoutMode1 copy.vue')['default']
ExternalJump: typeof import('./core/components/ExternalJump.vue')['default']
FindBack: typeof import('./core/components/FindBack.vue')['default']
GenerateCron: typeof import('./core/components/GenerateCron.vue')['default']

View File

@ -8,6 +8,7 @@ import NProgress from "nprogress";
import Cookies from "universal-cookie";
import AppConsts from "../../utils/AppConsts";
import TImageConfigService from "@/services/apps/T_Image_Configs/TImageConfigService";
import CosService from "@/services/system/CosService";
import COS from "cos-js-sdk-v5";
import { log } from "@antv/g2plot/lib/utils";
/**
@ -390,7 +391,7 @@ class Tools {
* @returns
*/
static async cosUploadFile(file: File, modelName?: string) {
var request = await TImageConfigService.getGenerateTemporaryKey(
const request = await CosService.getGenerateTemporaryKey(
file.name,
modelName
);

View File

@ -0,0 +1,39 @@
import Http from "@/core/utils/Http";
import type ApiResult from "@/core/typings/ApiResult";
import type { GenerateTemporaryModel } from "./types/cos";
/**
* COS
*/
export default class CosService {
static urlPrefix = "/api/v1/admin/Cos";
/**
* COS URL
*/
static getCosSign(): Promise<ApiResult<string>> {
return Http.get(`${this.urlPrefix}/GetCosSign`);
}
/**
*
* @param fileName
* @param modelName
*/
static getGenerateTemporaryKey(
fileName?: string,
modelName?: string
): Promise<ApiResult<GenerateTemporaryModel>> {
const params: Record<string, string> = {};
if (fileName != null) {
params.fileName = escape(fileName);
}
if (modelName != null) {
params.modelName = escape(modelName);
}
return Http.get(`${this.urlPrefix}/GetGenerateTemporaryKey`, params) as Promise<
ApiResult<GenerateTemporaryModel>
>;
}
}

View File

@ -0,0 +1,17 @@
export interface GenerateTemporaryModel {
credentials: {
token: string;
tmpSecretId: string;
tmpSecretKey: string;
};
expiration: string;
expiredTime: number;
startTime: number;
requestId: string;
bucket: string;
region: string;
prefixes: string;
filePath: string;
domainName: string;
}

View File

@ -0,0 +1,264 @@
# 腾讯云COS服务接口迁移文档
## 📋 更新概述
本次更新将腾讯云COS相关接口从 `TImageConfigController` 迁移到独立的 `CosController`实现服务分离COS服务不再与业务数据库关联。
---
## 🆕 一、新增接口
### 1.1 获取COS签名
**接口信息:**
- **请求路径**`GET /api/v1/admin/Cos/GetCosSign`
- **请求方法**`GET`
- **是否需要认证**:是
- **描述**获取腾讯云COS预签名URL
**请求参数:**
**响应示例:**
```json
"https://cos.ap-shanghai.myqcloud.com/miaoyu-1308826010/exampleobject?sign=..."
```
**响应字段说明:**
- 返回类型:`string`
- 说明预签名的COS上传URL
---
### 1.2 获取临时密钥
**接口信息:**
- **请求路径**`GET /api/v1/admin/Cos/GetGenerateTemporaryKey`
- **请求方法**`GET`
- **是否需要认证**:是
- **描述**获取腾讯云COS临时访问密钥STS
**请求参数:**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| fileName | string | 否 | 文件名,不传则生成时间戳文件名 |
| modelName | string | 否 | 模型名称,默认值为 "images" |
**请求示例:**
```http
GET /api/v1/admin/Cos/GetGenerateTemporaryKey?fileName=test.jpg&modelName=images
```
**响应示例:**
```json
{
"credentials": {
"token": "xxx",
"tmpSecretId": "xxx",
"tmpSecretKey": "xxx"
},
"expiration": "2024-12-07T10:00:00Z",
"expiredTime": 1701936000,
"startTime": 1701935400,
"requestId": "xxx",
"bucket": "miaoyu-1308826010",
"region": "ap-shanghai",
"prefixes": "miaoyu",
"filePath": "miaoyu/images/20241207/1701936000.jpg",
"domainName": "https://cos.shhuanmeng.com/"
}
```
**响应字段说明:**
| 字段名 | 类型 | 说明 |
|--------|------|------|
| credentials | object | 临时访问凭证 |
| credentials.token | string | 临时Token |
| credentials.tmpSecretId | string | 临时SecretId |
| credentials.tmpSecretKey | string | 临时SecretKey |
| expiration | string | 过期时间ISO8601格式 |
| expiredTime | number | 过期时间Unix时间戳 |
| startTime | number | 开始时间Unix时间戳 |
| requestId | string | 请求ID |
| bucket | string | 存储桶名称 |
| region | string | 地域 |
| prefixes | string | 路径前缀 |
| filePath | string | 文件路径 |
| domainName | string | 访问域名 |
---
## ⚠️ 二、废弃接口
以下接口已废弃,请使用新的接口替代:
### 2.1 废弃获取COS签名
- **旧接口路径**`GET /api/v1/admin/TImageConfig/GetCosSign`
- **新接口路径**`GET /api/v1/admin/Cos/GetCosSign`
- **状态**:❌ 已废弃,请使用新接口
### 2.2 废弃:获取临时密钥
- **旧接口路径**`GET /api/v1/admin/TImageConfig/GetGenerateTemporaryKey`
- **新接口路径**`GET /api/v1/admin/Cos/GetGenerateTemporaryKey`
- **状态**:❌ 已废弃,请使用新接口
---
## 🔄 三、接口迁移对照表
| 功能 | 旧接口 | 新接口 | 状态 |
|------|--------|--------|------|
| 获取COS签名 | `GET /api/v1/admin/TImageConfig/GetCosSign` | `GET /api/v1/admin/Cos/GetCosSign` | ✅ 已迁移 |
| 获取临时密钥 | `GET /api/v1/admin/TImageConfig/GetGenerateTemporaryKey` | `GET /api/v1/admin/Cos/GetGenerateTemporaryKey` | ✅ 已迁移 |
---
## 📝 四、前端修改说明
### 4.1 接口地址变更
**修改前:**
```typescript
// 获取COS签名
const getCosSign = async () => {
return axios.get('/api/v1/admin/TImageConfig/GetCosSign');
};
// 获取临时密钥
const getTemporaryKey = async (fileName?: string, modelName?: string) => {
return axios.get('/api/v1/admin/TImageConfig/GetGenerateTemporaryKey', {
params: { fileName, modelName }
});
};
```
**修改后:**
```typescript
// 获取COS签名
const getCosSign = async () => {
return axios.get('/api/v1/admin/Cos/GetCosSign');
};
// 获取临时密钥
const getTemporaryKey = async (fileName?: string, modelName?: string) => {
return axios.get('/api/v1/admin/Cos/GetGenerateTemporaryKey', {
params: { fileName, modelName }
});
};
```
### 4.2 API服务更新
**建议更新 API 服务文件:**
```typescript
// api/cos.ts
export const cosApi = {
// 获取COS签名
getCosSign: (): Promise<string> => {
return axios.get('/api/v1/admin/Cos/GetCosSign').then(res => res.data);
},
// 获取临时密钥
getTemporaryKey: (params?: {
fileName?: string;
modelName?: string;
}): Promise<GenerateTemporaryModel> => {
return axios.get('/api/v1/admin/Cos/GetGenerateTemporaryKey', {
params
}).then(res => res.data);
}
};
```
### 4.3 类型定义(如需要)
```typescript
// types/cos.ts
export interface GenerateTemporaryModel {
credentials: {
token: string;
tmpSecretId: string;
tmpSecretKey: string;
};
expiration: string;
expiredTime: number;
startTime: number;
requestId: string;
bucket: string;
region: string;
prefixes: string;
filePath: string;
domainName: string;
}
```
---
## ✨ 五、注意事项
### 5.1 接口兼容性
- **旧接口已完全废弃**,不再可用
- **新接口的参数和返回值与旧接口完全一致**,仅路径变更
- **无需修改业务逻辑**,只需更新接口地址
### 5.2 权限控制
- 新接口需要认证(`[Authorize]`
- 权限控制规则与旧接口一致
- 如果旧接口有特殊权限配置,新接口保持相同配置
### 5.3 错误处理
- 错误响应格式保持不变
- 错误码和错误信息保持一致
- 前端错误处理逻辑无需修改
---
## 🔍 六、验证清单
请确认以下内容已完成:
- [ ] 更新所有调用 `TImageConfig/GetCosSign` 的代码
- [ ] 更新所有调用 `TImageConfig/GetGenerateTemporaryKey` 的代码
- [ ] 更新 API 服务文件中的接口地址
- [ ] 测试新接口是否正常工作
- [ ] 移除对旧接口的引用
- [ ] 更新相关文档和注释
---
## 📞 七、技术支持
如有疑问,请联系后端开发团队。
**文档版本**v1.0
**更新日期**2024年12月
**后端版本**COS服务分离重构版本
---
## 📚 附录:完整接口列表
### 新接口列表
1. **获取COS签名**
- `GET /api/v1/admin/Cos/GetCosSign`
2. **获取临时密钥**
- `GET /api/v1/admin/Cos/GetGenerateTemporaryKey?fileName={fileName}&modelName={modelName}`
### 已废弃接口列表
1. ~~`GET /api/v1/admin/TImageConfig/GetCosSign`~~
2. ~~`GET /api/v1/admin/TImageConfig/GetGenerateTemporaryKey`~~
---
**文档结束**

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35913.81
# Visual Studio Version 18
VisualStudioVersion = 18.0.11201.2
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "00 Core", "00 Core", "{DB46F54A-9F53-44EC-80F8-9E53F0B871CF}"
EndProject

View File

@ -15,6 +15,7 @@ namespace MiaoYu.Api.Admin;
CoreRedisStartup,
CoreIdentityStartup,
AdminRepositoryStartup,
//ChatAdminRepositoryStartup,
LiveForumAdminRepositoryStartup,
CoreSwaggerJwtStartup,
SharedAdminStartup,

View File

@ -0,0 +1,83 @@
using MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.Dtos;
using MiaoYu.Core.ApplicationServices;
using MiaoYu.Core.Cos.Configs;
using MiaoYu.Core.Cos.Models;
using MiaoYu.Core.Cos.Services;
namespace MiaoYu.Api.Admin.ApplicationServices.Systems.Cos;
/// <summary>
/// 腾讯云COS服务
/// </summary>
public class CosService : ApplicationService
{
private readonly ICodeCosService _codeCosService;
private readonly TencentConfig _tencentConfig;
public CosService(ICodeCosService codeCosService, TencentConfig tencentConfig)
{
_codeCosService = codeCosService;
_tencentConfig = tencentConfig;
}
/// <summary>
/// 获取签名
/// </summary>
/// <returns></returns>
public string GetCosSign()
{
var (sign, ex) = _codeCosService.GenerateSignURL(new CosGenerateSign());
return sign;
}
/// <summary>
/// 获取临时签名
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="modelName">模型名称</param>
/// <returns></returns>
public GenerateTemporaryModel GetGenerateTemporaryKey(string fileName = "", string modelName = "")
{
var cosConfig = _tencentConfig.CosConfig;
var t = new CosGenerateSign()
{
Prefixes = "miaoyu",
Bucket = cosConfig?.Bucket,
Region = cosConfig?.Region,
AppId = cosConfig?.AppId,
SecretId = cosConfig?.SecretId,
SecretKey = cosConfig?.SecretKey,
DurationSecond = cosConfig?.DurationSecond ?? 300
};
if (string.IsNullOrEmpty(modelName))
{
modelName = "images";
}
var tempFile = fileName;
if (!string.IsNullOrEmpty(tempFile))
{
var ext = Path.GetExtension(tempFile);
if (!string.IsNullOrEmpty(ext))
{
// 使用 UTC 时间生成时间戳文件名
tempFile = $"{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}{ext}";
}
}
var model = _codeCosService.GenerateTemporaryKey(t);
// 复制对象属性
var generateTemporaryModel = model.CopyObject<CodeCosGenerateTemporaryKeyEntity, GenerateTemporaryModel>() ?? new GenerateTemporaryModel();
generateTemporaryModel.Bucket = t.Bucket + "-" + t.AppId;
generateTemporaryModel.Region = t.Region;
generateTemporaryModel.Prefixes = t.Prefixes;
// 修复日期格式yyyMMdd -> yyyyMMdd
generateTemporaryModel.FilePath = $"{t.Prefixes}/{modelName}/{DateTime.Now.ToString("yyyyMMdd")}/{tempFile}";
generateTemporaryModel.DomainName = "https://cos.shhuanmeng.com/";
return generateTemporaryModel;
}
}

View File

@ -0,0 +1,36 @@
using MiaoYu.Core.Cos.Models;
namespace MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.Dtos;
/// <summary>
/// cos临时密钥
/// </summary>
public class GenerateTemporaryModel : CodeCosGenerateTemporaryKeyEntity
{
/// <summary>
/// 存储桶名称
/// </summary>
public string Bucket { get; set; }
/// <summary>
/// 关于地域的详情见
/// </summary>
public string Region { get; set; }
/// <summary>
/// 前缀
/// </summary>
public string Prefixes { get; set; }
/// <summary>
/// 文件路径
/// </summary>
public string FilePath { get; set; }
/// <summary>
/// 域名
/// </summary>
public string DomainName { get; set; }
}

View File

@ -1,4 +1,5 @@
using MiaoYu.Api.Admin.ApplicationServices.Apps.LiveForum;
using MiaoYu.Api.Admin.ApplicationServices.Apps.LiveForum;
using MiaoYu.Repository.LiveForum.Admin.Entities.Apps;
namespace MiaoYu.Api.Admin.Controllers.Apps.LiveForum;

View File

@ -0,0 +1,41 @@
using MiaoYu.Api.Admin.ApplicationServices.Systems.Cos;
using MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.Dtos;
namespace MiaoYu.Api.Admin.Controllers.Systems;
/// <summary>
/// 腾讯云COS控制器
/// </summary>
[ControllerDescriptor(DisplayName = "腾讯云COS")]
public class CosController : AdminControllerBase<CosService>
{
public CosController(CosService defaultService)
: base(defaultService)
{
}
/// <summary>
/// 获取COS签名
/// </summary>
/// <returns></returns>
[HttpGet]
[ActionDescriptor(DisplayName = "获取COS签名")]
public string GetCosSign()
{
return this._defaultService.GetCosSign();
}
/// <summary>
/// 获取临时密钥
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="modelName">模型名称</param>
/// <returns></returns>
[HttpGet]
[ActionDescriptor(DisplayName = "获取COS临时密钥")]
public GenerateTemporaryModel GetGenerateTemporaryKey(string fileName = "", string modelName = "")
{
return this._defaultService.GetGenerateTemporaryKey(fileName, modelName);
}
}

View File

@ -0,0 +1,38 @@
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["MiaoYu.Api.Admin/MiaoYu.Api.Admin.csproj", "MiaoYu.Api.Admin/"]
COPY ["MiaoYu.Core.Cos/MiaoYu.Core.Cos.csproj", "MiaoYu.Core.Cos/"]
COPY ["MiaoYu.Core.EntityFramework/MiaoYu.Core.EntityFramework.csproj", "MiaoYu.Core.EntityFramework/"]
COPY ["MiaoYu.Core.Identity/MiaoYu.Core.Identity.csproj", "MiaoYu.Core.Identity/"]
COPY ["MiaoYu.Core/MiaoYu.Core.csproj", "MiaoYu.Core/"]
COPY ["MiaoYu.Core.Quartz/MiaoYu.Core.Quartz.csproj", "MiaoYu.Core.Quartz/"]
COPY ["MiaoYu.Core.Razor/MiaoYu.Core.Razor.csproj", "MiaoYu.Core.Razor/"]
COPY ["MiaoYu.Core.Redis/MiaoYu.Core.Redis.csproj", "MiaoYu.Core.Redis/"]
COPY ["MiaoYu.Core.Swagger/MiaoYu.Core.Swagger.csproj", "MiaoYu.Core.Swagger/"]
COPY ["MiaoYu.Repository.Admin/MiaoYu.Repository.Admin.csproj", "MiaoYu.Repository.Admin/"]
COPY ["MiaoYu.Core.Logs/MiaoYu.Core.Logs.csproj", "MiaoYu.Core.Logs/"]
COPY ["MiaoYu.Repository.ChatAI.Admin/MiaoYu.Repository.ChatAI.Admin.csproj", "MiaoYu.Repository.ChatAI.Admin/"]
COPY ["MiaoYu.Shared.Admin/MiaoYu.Shared.Admin.csproj", "MiaoYu.Shared.Admin/"]
COPY ["MiaoYu.Shared/MiaoYu.Shared.csproj", "MiaoYu.Shared/"]
RUN ls
RUN dotnet restore "./MiaoYu.Api.Admin/MiaoYu.Api.Admin.csproj"
COPY . .
WORKDIR "/src/MiaoYu.Api.Admin"
RUN dotnet build "./MiaoYu.Api.Admin.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./MiaoYu.Api.Admin.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MiaoYu.Api.Admin.dll"]

View File

@ -52,6 +52,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="ApplicationServices\Apps\" />
<Folder Include="Controllers\Apps\LiveForum\" />
<Folder Include="wwwroot\docs\" />
</ItemGroup>

View File

@ -589,6 +589,55 @@
</summary>
<returns></returns>
</member>
<member name="T:MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.CosService">
<summary>
腾讯云COS服务
</summary>
</member>
<member name="M:MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.CosService.GetCosSign">
<summary>
获取签名
</summary>
<returns></returns>
</member>
<member name="M:MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.CosService.GetGenerateTemporaryKey(System.String,System.String)">
<summary>
获取临时签名
</summary>
<param name="fileName">文件名</param>
<param name="modelName">模型名称</param>
<returns></returns>
</member>
<member name="T:MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.Dtos.GenerateTemporaryModel">
<summary>
cos临时密钥
</summary>
</member>
<member name="P:MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.Dtos.GenerateTemporaryModel.Bucket">
<summary>
存储桶名称
</summary>
</member>
<member name="P:MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.Dtos.GenerateTemporaryModel.Region">
<summary>
关于地域的详情见
</summary>
</member>
<member name="P:MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.Dtos.GenerateTemporaryModel.Prefixes">
<summary>
前缀
</summary>
</member>
<member name="P:MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.Dtos.GenerateTemporaryModel.FilePath">
<summary>
文件路径
</summary>
</member>
<member name="P:MiaoYu.Api.Admin.ApplicationServices.Systems.Cos.Dtos.GenerateTemporaryModel.DomainName">
<summary>
域名
</summary>
</member>
<member name="T:MiaoYu.Api.Admin.ApplicationServices.Systems.PermissionService">
<summary>
系统权限服务
@ -1502,6 +1551,25 @@
路由前缀
</summary>
</member>
<member name="T:MiaoYu.Api.Admin.Controllers.Systems.CosController">
<summary>
腾讯云COS控制器
</summary>
</member>
<member name="M:MiaoYu.Api.Admin.Controllers.Systems.CosController.GetCosSign">
<summary>
获取COS签名
</summary>
<returns></returns>
</member>
<member name="M:MiaoYu.Api.Admin.Controllers.Systems.CosController.GetGenerateTemporaryKey(System.String,System.String)">
<summary>
获取临时密钥
</summary>
<param name="fileName">文件名</param>
<param name="modelName">模型名称</param>
<returns></returns>
</member>
<member name="T:MiaoYu.Api.Admin.Controllers.Systems.PersonalCenterController">
<summary>
个人中心
@ -2124,36 +2192,6 @@
</summary>
<returns></returns>
</member>
<member name="T:MiaoYu.Api.Admin.Models.Dtos.Apps.Cos.GenerateTemporaryModel">
<summary>
cos临时密钥
</summary>
</member>
<member name="P:MiaoYu.Api.Admin.Models.Dtos.Apps.Cos.GenerateTemporaryModel.Bucket">
<summary>
存储桶名称
</summary>
</member>
<member name="P:MiaoYu.Api.Admin.Models.Dtos.Apps.Cos.GenerateTemporaryModel.Region">
<summary>
关于地域的详情见
</summary>
</member>
<member name="P:MiaoYu.Api.Admin.Models.Dtos.Apps.Cos.GenerateTemporaryModel.Prefixes">
<summary>
前缀
</summary>
</member>
<member name="P:MiaoYu.Api.Admin.Models.Dtos.Apps.Cos.GenerateTemporaryModel.FilePath">
<summary>
文件路径
</summary>
</member>
<member name="P:MiaoYu.Api.Admin.Models.Dtos.Apps.Cos.GenerateTemporaryModel.DomainName">
<summary>
域名
</summary>
</member>
<member name="T:MiaoYu.Api.Admin.Models.Dtos.DevelopmentTool.DataSourceDto">
<summary>
数据源信息 DTO

View File

@ -1,36 +0,0 @@
using MiaoYu.Core.Cos.Models;
namespace MiaoYu.Api.Admin.Models.Dtos.Apps.Cos
{
/// <summary>
/// cos临时密钥
/// </summary>
public class GenerateTemporaryModel : CodeCosGenerateTemporaryKeyEntity
{
/// <summary>
/// 存储桶名称
/// </summary>
public string Bucket { get; set; }
/// <summary>
/// 关于地域的详情见
/// </summary>
public string Region { get; set; }
/// <summary>
/// 前缀
/// </summary>
public string Prefixes { get; set; }
/// <summary>
/// 文件路径
/// </summary>
public string FilePath { get; set; }
/// <summary>
/// 域名
/// </summary>
public string DomainName { get; set; }
}
}

View File

@ -83,4 +83,4 @@ global using System.ComponentModel;
global using System.Reflection;
global using System.Text;
global using System.Text.Encodings.Web;
global using System.Text.Unicode;
global using System.Text.Unicode;

View File

@ -0,0 +1,44 @@
using MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
namespace MiaoYu.Repository.ChatAI.Admin
{
/// <summary>
/// 后台管理系统数据库上下文
/// </summary>
[DbContextConfig($"Repository.*.Entities.*")]
public class ChatAdminDbContext : DbContext, IBaseDbContext
{
/// <summary>
/// 工作单元
/// </summary>
public IUnitOfWork UnitOfWork { get; }
public ChatAdminDbContext(DbContextOptions<ChatAdminDbContext> dbContextOptions) : base(dbContextOptions)
{
UnitOfWork = new UnitOfWorkImpl<ChatAdminDbContext>(this);
}
/// <summary>
/// 模型创建
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
#region
//OnModelCreatingPartial(modelBuilder);
//ModelBuilderExtensions.Seed(modelBuilder);
#endregion
var dbContextConfigAttribute = GetType().GetCustomAttribute<DbContextConfigAttribute>()!;
var t = dbContextConfigAttribute.GetModelTypes(GetType());
dbContextConfigAttribute!.OnModelCreating(modelBuilder, t);
}
}
}

View File

@ -0,0 +1,139 @@
using MiaoYu.Repository.ChatAI.Admin.Models;
namespace MiaoYu.Repository.ChatAI.Admin
{
/// <summary>
/// 程序启动器
/// </summary>
[ImportStartupModule<CoreEntityFrameworkStartup>]
public class ChatAdminRepositoryStartup : StartupModule<ChatAdminRepositoryStartup>
{
/// <summary>
/// 程序启动器
/// </summary>
/// <param name="webApplicationBuilder"></param>
public override void ConfigureServices(WebApplicationBuilder webApplicationBuilder)
{
var configuration = webApplicationBuilder.Configuration;
var services = webApplicationBuilder.Services;
var webHostEnvironment = webApplicationBuilder.Environment;
var repositoriesOptions = configuration
.GetSection(nameof(ChatAdminRepositoryOptions))
.Get<ChatAdminRepositoryOptions>() ?? throw new Exception("配置对象 空 异常!");
var connectionString = repositoriesOptions?.ConnectionString;
connectionString = string.IsNullOrWhiteSpace(connectionString) ?
configuration["ConnectionStrings:" + repositoriesOptions!.DefaultDatabaseType.ToString()] :
connectionString;
services.AddDbContextFactory<ChatAdminDbContext>(optionsBuilder =>
{
switch (repositoriesOptions.DefaultDatabaseType)
{
case DefaultDatabaseType.SqlServer:
optionsBuilder
.UseSqlServer(connectionString, w => w.MinBatchSize(1).MaxBatchSize(1000))
;
break;
case DefaultDatabaseType.MySql:
optionsBuilder
.UseMySql(connectionString, MySqlServerVersion.LatestSupportedServerVersion, w => w.MinBatchSize(1).MaxBatchSize(1000))
;
break;
case DefaultDatabaseType.PostgreSql:
//EnableLegacyTimestampBehavior 启动旧行为,避免时区问题,存储时间报错
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
optionsBuilder
.UseNpgsql(connectionString, w => w.MinBatchSize(1).MaxBatchSize(1000))
;
break;
case DefaultDatabaseType.Oracle:
optionsBuilder
.UseOracle(connectionString, w => w.MinBatchSize(1).MaxBatchSize(1000))
;
break;
default:
break;
}
if (webHostEnvironment.IsDevelopment())
{
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
// sql 日志写入控制台
optionsBuilder.UseLoggerFactory(loggerFactory);
}
// 懒加载代理
//options.UseLazyLoadingProxies();
//添加 EFCore 监控 和 动态表名
optionsBuilder.AddEntityFrameworkMonitor(repositoriesOptions.IsMonitorEFCore);
optionsBuilder.AddInterceptors(new AuditInterceptor());
});
services.AddEntityFrameworkRepositories<ChatAdminDbContext>(repositoriesOptions, (auditOptions) =>
{
// 你的自定义审计字段 ...
//auditOptions.Add(new AuditOptions()
//{
// CreationTimeFieldName = nameof(ICreateEntityV2.CreateTime),
// CreatorUserIdFieldName = "",
// LastModificationTimeFieldName = nameof(IUpdateEntityV2.UpdateTime),
// LastModifierUserIdFieldName = "",
// DeletionTimeFieldName = "UpdateTime",
// DeleterUserIdFieldName = "UpdateBy",
// IsDeletedFieldName = "DelFlag",
//});
}, (freesqlOptions) =>
{
freesqlOptions.FreeSqlAuditAopList?.Add(new FreeSqlAuditAop());
freesqlOptions.FreeSqlAction = (freeSql) =>
{
freeSql.Aop.CurdAfter += (object? sender, FreeSql.Aop.CurdAfterEventArgs curdAfter) =>
{
var stringBuilder = new StringBuilder();
stringBuilder.Append($"\r\n====[FreeSql 开始 耗时: {curdAfter.ElapsedMilliseconds} ms]=========");
stringBuilder.Append($"\r\n{curdAfter.Sql}");
stringBuilder.Append($"\r\n====[FreeSql 结束 线程Id:{Environment.CurrentManagedThreadId}]=========");
LogUtil.Log.Warning(stringBuilder.ToString());
};
};
});
}
/// <summary>
/// Configure
/// </summary>
/// <param name="webApplication"></param>
public override void Configure(WebApplication webApplication)
{
// 使用 DbContext
#region
//if (webApplication.Environment.IsDevelopment())
//{
// // 自动迁移 (如果迁移文件有变动)
// using var scope = webApplication.Services.CreateScope();
// using var adminDbContext = scope.ServiceProvider.GetService<ChatAdminDbContext>();
// if (adminDbContext!.Database.GetPendingMigrations().Count() > 0)
// {
// try
// {
// adminDbContext.Database.Migrate();
// }
// catch (Exception ex)
// {
// LogUtil.Log.Error(ex.Message, ex);
// }
// }
//}
#endregion
}
}
}

View File

@ -0,0 +1,36 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 存储不同音乐风格的信息。
/// </summary>
[EntityDescription(FieldIgnored = true)]
[Table("M_MusicGenres")]
public class M_MusicGenres : DefaultEntityV4
{
/// <summary>
/// 音乐风格名称 => 备注: 音乐风格名称
/// </summary>
public string? GenreName { get; set; }
/// <summary>
/// 音乐风格描述 => 备注: 音乐风格描述
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 排序 => 备注: 排序
/// </summary>
public Int32 OrderId { get; set; }
/// <summary>
/// 是否启用 => 备注: 是否启用
/// </summary>
public Boolean IsEnabled { get; set; }
}

View File

@ -0,0 +1,90 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 存储所有生成的歌曲的信息。
/// </summary>
[EntityDescription(FieldIgnored = true)]
[Table("M_Songs")]
public class M_Songs : DefaultEntityV4
{
/// <summary>
/// 歌曲名称 => 备注: 歌曲名称
/// </summary>
public string? Title { get; set; }
/// <summary>
/// 用户Id => 备注: 歌曲作者ID
/// </summary>
public Int32 AuthorId { get; set; }
/// <summary>
/// 音乐风格 => 备注: 音乐风格
/// </summary>
public string? Genre { get; set; }
/// <summary>
/// 歌词内容 => 备注: 歌词内容
/// </summary>
public string? Lyrics { get; set; }
/// <summary>
/// 歌曲是否公开展示 => 备注: 歌曲是否公开展示
/// </summary>
public Boolean IsPublic { get; set; }
/// <summary>
/// 歌曲创建时间 => 备注: 歌曲创建时间
/// </summary>
public DateTime CreationTimestamp { get; set; }
/// <summary>
/// 歌曲时长 => 备注: 歌曲时长
/// </summary>
public TimeSpan? Duration { get; set; }
/// <summary>
/// 播放次数 => 备注: 播放次数
/// </summary>
public Int32 PlayCount { get; set; }
/// <summary>
/// 点赞次数 => 备注: 点赞次数
/// </summary>
public Int32 LikeCount { get; set; }
/// <summary>
/// 下载次数 => 备注: 下载次数
/// </summary>
public Int32 DownloadCount { get; set; }
/// <summary>
/// 音乐下载地址 => 备注: 音乐下载地址
/// </summary>
public string? MusicAddress { get; set; }
/// <summary>
/// 封面图 => 备注: 封面图
/// </summary>
public string? CoverImage { get; set; }
/// <summary>
/// 音乐风格Id => 备注: 音乐风格Id
/// </summary>
public Int32? GenreId { get; set; }
}

View File

@ -0,0 +1,65 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 发现页类别菜单
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Category_Child_Menu : DefaultEntityV4
{
/// <summary>
/// 菜单类型 => 备注: 菜单类型banner,热门推荐,热门小说)
/// </summary>
public string? Type { get; set; }
/// <summary>
/// 名称 => 备注: 名称
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 动作I => 备注: 动作Id
/// </summary>
public string? ActionId { get; set; }
/// <summary>
/// 动作类型 => 备注: 动作类型
/// </summary>
public string? ActionType { get; set; }
/// <summary>
/// 图片Id => 备注: 图片Id
/// </summary>
public Int32 ImageId { get; set; }
/// <summary>
/// 排序 => 备注: 排序
/// </summary>
public Int32 OrderById { get; set; }
/// <summary>
/// 图片补位 => 备注: 图片补位
/// </summary>
public string? ImageUrl { get; set; }
/// <summary>
/// 是否启用 => 备注: IsEnabled
/// </summary>
public Boolean IsEnabled { get; set; }
/// <summary>
/// 副标题 => 备注: SubTitle
/// </summary>
public string? SubTitle { get; set; }
}

View File

@ -0,0 +1,95 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 人物表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Character : DefaultEntityV4
{
/// <summary>
/// 人物名字 => 备注: 人物名字
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 人物简介 => 备注: 人物简介
/// </summary>
public string? Biography { get; set; }
/// <summary>
/// 开场白,剧情 => 备注: 开场白,剧情
/// </summary>
public string? Prologue { get; set; }
/// <summary>
/// 模型Id => 备注: 模型Id
/// </summary>
public Int32 ModelConfigId { get; set; }
/// <summary>
/// 公开/私密 0公开 1私密 => 备注: 公开/私密 0公开 1私密
/// </summary>
public Boolean Visibility { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime? CreateTime { get; set; }
/// <summary>
/// 更新时间 => 备注: 更新时间
/// </summary>
public DateTime? UpdateTime { get; set; }
/// <summary>
/// 性别0男1女2其他 => 备注: 性别0男1女2其他
/// </summary>
public Int32 Gender { get; set; }
/// <summary>
/// 人物初始设定 => 备注: 人物初始设定
/// </summary>
public string? System { get; set; }
/// <summary>
/// 背景图片 => 备注: 背景图片
/// </summary>
public Int32? BgImg { get; set; }
/// <summary>
/// 角色头像是id => 备注: 角色头像是id
/// </summary>
public Int32? IconImg { get; set; }
/// <summary>
/// 对话名字 => 备注: 对话名字
/// </summary>
public string? UserName { get; set; }
/// <summary>
/// 对话性别 => 备注: 对话性别
/// </summary>
public string? UserSex { get; set; }
/// <summary>
/// system最大的token数 => 备注: system最大的token数
/// </summary>
public Int32? Token { get; set; }
}

View File

@ -0,0 +1,35 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 角色标签表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Character_Label : DefaultEntityV4
{
/// <summary>
/// 标签名称 => 备注: 标签名称
/// </summary>
public string? LabelName { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新时间 => 备注: 更新时间
/// </summary>
public DateTime UpdateTime { get; set; }
/// <summary>
/// 标签值 => 备注: 标签值
/// </summary>
public string? LabelValue { get; set; }
}

View File

@ -0,0 +1,35 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 关联角色和标签
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Character_Label_Relation : DefaultEntityV4
{
/// <summary>
/// 人物Id => 备注: 人物Id
/// </summary>
public Int32 CharacterId { get; set; }
/// <summary>
/// 人物标签id => 备注: 人物标签id
/// </summary>
public Int32 CharacterLabelId { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新时间 => 备注: 更新时间
/// </summary>
public DateTime UpdateTime { get; set; }
}

View File

@ -0,0 +1,35 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 角色性格表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Character_Personality : DefaultEntityV4
{
/// <summary>
/// 性格名称 => 备注: 性格名称
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 性格值 => 备注: 性格值
/// </summary>
public string? Value { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改时间 => 备注: 修改时间
/// </summary>
public DateTime UpdateTime { get; set; }
}

View File

@ -0,0 +1,29 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 角色和性格关联表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Character_Personality_Relation : DefaultEntityV4
{
/// <summary>
/// 性格Id => 备注: 性格Id
/// </summary>
public Int32 PersonalityId { get; set; }
/// <summary>
/// 角色Id => 备注: 角色Id
/// </summary>
public Int32 CharacterId { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
}

View File

@ -0,0 +1,41 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 发现页类型分类
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Character_Type : DefaultEntityV4
{
/// <summary>
/// 类型名称 => 备注: 类型名称
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新时间 => 备注: 更新时间
/// </summary>
public DateTime UpdateTime { get; set; }
/// <summary>
/// 分类页不显示 => 备注: 分类页不显示
/// </summary>
public Boolean IsNotCategoryShow { get; set; }
/// <summary>
/// 序号 => 备注: 序号
/// </summary>
public Int32 OrderBy { get; set; }
}

View File

@ -0,0 +1,41 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 角色和角色类型关联表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Character_Type_Intimacy : DefaultEntityV4
{
/// <summary>
/// 列表Id => 备注: 列表Id
/// </summary>
public Int32 TypeId { get; set; }
/// <summary>
/// 角色Id => 备注: 角色Id
/// </summary>
public Int32 CharacterId { get; set; }
/// <summary>
/// 修改时间 => 备注: 修改时间
/// </summary>
public DateTime UpdateTIme { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 类别表排序 => 备注: 类别表排序
/// </summary>
public Int32 OrderBy { get; set; }
}

View File

@ -0,0 +1,113 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 聊天记录表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Chat : DefaultEntityV4
{
/// <summary>
/// 聊天内容 => 备注: 聊天内容
/// </summary>
public Int32 UserId { get; set; }
/// <summary>
/// 消息内容 => 备注: 消息内容
/// </summary>
public string? Content { get; set; }
/// <summary>
/// 发送时间 => 备注: 发送时间
/// </summary>
public DateTime TimeStamp { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新时间 => 备注: 更新时间
/// </summary>
public DateTime UpdateTime { get; set; }
/// <summary>
/// 输入token => 备注: 输入token
/// </summary>
public Int32 Input_tokens { get; set; }
/// <summary>
/// 输出token => 备注: 输出token
/// </summary>
public Int32 Output_tokens { get; set; }
/// <summary>
/// 人物表Id => 备注: 人物表Id
/// </summary>
public Int32 CharacterId { get; set; }
/// <summary>
/// 角色 => 备注: user/assistant
/// </summary>
public string? Role { get; set; }
/// <summary>
/// 会话Id => 备注: SessionId
/// </summary>
public Guid SessionId { get; set; }
/// <summary>
/// 发送消息 => 备注: 发送消息,天
/// </summary>
public Int64 SendDateDay { get; set; }
/// <summary>
/// 发送消息时间戳 => 备注: 发送消息时间戳
/// </summary>
public Int64 SendMessageDay { get; set; }
/// <summary>
/// 消息状态 => 备注: 0正常1重新生成2 删除
/// </summary>
public Int32 Type { get; set; }
/// <summary>
/// 消息类型 => 备注: 聊天返回的消息的类型
/// </summary>
public string? ClaudeType { get; set; }
/// <summary>
/// ClaudeId => 备注: 聊天返回的Id
/// </summary>
public string? ClaudeId { get; set; }
/// <summary>
/// 人物模型 => 备注: 人物模型,聊天返回的模型
/// </summary>
public string? ClaudeModel { get; set; }
/// <summary>
/// 总Tokens => 备注: 消耗的token
/// </summary>
public Int32? Tokens { get; set; }
}

View File

@ -0,0 +1,28 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 图片表
/// </summary>
public class T_Image_Config : DefaultEntityV4
{
/// <summary>
/// 图片Id => 备注: 图片Id
/// </summary>
public Int32 ImageId { get; set; }
/// <summary>
/// 图片名称 => 备注: 图片名称
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 图片地址 => 备注: 图片地址
/// </summary>
public string? Url { get; set; }
}

View File

@ -0,0 +1,92 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 模型配置表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Model_Config : DefaultEntityV4
{
/// <summary>
/// 模型名称 => 备注: 模型名称
/// </summary>
public string? ModelName { get; set; }
/// <summary>
/// 模型model => 备注: 模型model
/// </summary>
public string? Model { get; set; }
/// <summary>
/// max_tokens => 备注: 模型运行最大的max_tokens
/// </summary>
public Int32 MaxTokens { get; set; }
/// <summary>
/// key x-api-key => 备注: 模型key x-api-key
/// </summary>
public string? ApiKey { get; set; }
/// <summary>
/// 模型请求地址 => 备注: 模型请求地址
/// </summary>
public string? Url { get; set; }
/// <summary>
/// 模型版本 => 备注: 模型版本 anthropic-version
/// </summary>
public string? AnthropicVersion { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改时间 => 备注: 修改时间
/// </summary>
public DateTime UpdateTime { get; set; }
/// <summary>
/// 上下文模板 => 备注: system上下文模板
/// </summary>
public string? SystemTemplate { get; set; }
/// <summary>
/// 请求模板 => 备注: 请求模板
/// </summary>
public string? RequestTemplate { get; set; }
/// <summary>
/// headers对象 => 备注: headers对象
/// </summary>
public string? HeadersTemplate { get; set; }
/// <summary>
/// 返回数据模板 => 备注: 返回数据模板
/// </summary>
public string? ResponseTemplate { get; set; }
/// <summary>
/// 是否默认 => 备注: 是否默认
/// </summary>
public Boolean? IsDefabult { get; set; }
/// <summary>
/// 其它的模板
/// </summary>
public virtual string? OtherTemplate { get; set; }
}

View File

@ -0,0 +1,77 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 订单完成表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Order : DefaultEntityV4
{
/// <summary>
/// 订单编号 => 备注: 订单编号
/// </summary>
public string? OrderId { get; set; }
/// <summary>
/// 用户Id => 备注: 用户Id
/// </summary>
public Int32 UserId { get; set; }
/// <summary>
/// 订单创建时间 => 备注: 订单创建时间
/// </summary>
public DateTime OrderDate { get; set; }
/// <summary>
/// 订单支付时间 => 备注: 订单支付时间
/// </summary>
public DateTime PaymentDate { get; set; }
/// <summary>
/// 订单支付方式 => 备注: 订单支付方式
/// </summary>
public string? PaymentMethod { get; set; }
/// <summary>
/// 购买的产品Id => 备注: 购买的产品Id
/// </summary>
public string? ProductId { get; set; }
/// <summary>
/// 价格 => 备注: 价格
/// </summary>
public Decimal TotalPrice { get; set; }
/// <summary>
/// 订单状态 => 备注: 订单状态
/// </summary>
public Int32 Status { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreatedAt { get; set; }
/// <summary>
/// 修改时间 => 备注: 修改时间
/// </summary>
public DateTime UpdatedAt { get; set; }
/// <summary>
/// 订单创建天 => 备注: 订单创建天
/// </summary>
public DateTime PaymentDay { get; set; }
}

View File

@ -0,0 +1,54 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 订单详情表
/// </summary>
[EntityDescription(FieldIgnored = true)]
[Table("T_OrderItems")]
public class T_OrderItems : DefaultEntityV4
{
/// <summary>
/// 产品id => 备注: 产品id
/// </summary>
public string? ProductId { get; set; }
/// <summary>
/// 订单id => 备注: 订单id
/// </summary>
public string? OrderId { get; set; }
/// <summary>
/// 发放奖励信息 => 备注: 发放奖励信息
/// </summary>
public string? RewardInfo { get; set; }
/// <summary>
/// 产品id、主键 => 备注: 产品id、主键
/// </summary>
public Int32 Product { get; set; }
/// <summary>
/// 支付信息 => 备注: 支付信息
/// </summary>
public string? PaymentInfo { get; set; }
/// <summary>
/// 发放奖励提示 => 备注: 发放奖励提示
/// </summary>
public string? RewardTips { get; set; }
/// <summary>
/// 支付地址 => 备注: 支付地址
/// </summary>
public string? PayUrl { get; set; }
}

View File

@ -0,0 +1,86 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 商城表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Products : DefaultEntityV4
{
/// <summary>
/// 道具Id => 备注: 道具Id
/// </summary>
public string? ProductId { get; set; }
/// <summary>
/// 道具名称 => 备注: 道具名称
/// </summary>
public string? ProductName { get; set; }
/// <summary>
/// 道具类型 => 备注: 道具类型0商城1商店
/// </summary>
public Int32 ProductType { get; set; }
/// <summary>
/// 道具描述 => 备注: 道具描述
/// </summary>
public string? ProductDesc { get; set; }
/// <summary>
/// 价格 => 备注: 价格
/// </summary>
public Decimal Price { get; set; }
/// <summary>
/// 道具图片 => 备注: 道具图片配置 图片id
/// </summary>
public Int32 ProductImgId { get; set; }
/// <summary>
/// 商品状态 => 备注: 商品是否下架 0否1是
/// </summary>
public Int32 IsProductDelisting { get; set; }
/// <summary>
/// 首充 => 备注: 是否有首充
/// </summary>
public Boolean IsFirstCharge { get; set; }
/// <summary>
/// 首充图片 => 备注: 首充图片
/// </summary>
public Int32? FirstChargeImgId { get; set; }
/// <summary>
/// 首充价格 => 备注: 首充价格
/// </summary>
public Decimal? FirstChargePrice { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新时间 => 备注: 更新时间
/// </summary>
public DateTime? UpdateTime { get; set; }
/// <summary>
/// 排序 => 备注: 排序
/// </summary>
public Int32? OrderById { get; set; }
}

View File

@ -0,0 +1,41 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 产品表奖励
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Products_Reward : DefaultEntityV4
{
/// <summary>
/// 奖励类型 => 备注: 奖励类型
/// </summary>
public Int32 CurrencyType { get; set; }
/// <summary>
/// 送多少奖励 => 备注: 送多少奖励
/// </summary>
public Int32 Money { get; set; }
/// <summary>
/// 所属商品 => 备注: 所属商品
/// </summary>
public Int32 T_ProductId { get; set; }
/// <summary>
/// 首充送多少奖励 => 备注: 首充送多少奖励
/// </summary>
public Int32? FirstChargeMoney { get; set; }
/// <summary>
/// 所属商品 => 备注: 所属商品
/// </summary>
public string? ProductId { get; set; }
}

View File

@ -0,0 +1,86 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 用户表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_User : DefaultEntityV4
{
/// <summary>
/// 用户昵称 => 备注: 用户昵称
/// </summary>
public string? NickName { get; set; }
/// <summary>
/// 用户姓名 => 备注: 用户姓名
/// </summary>
public string? UserName { get; set; }
/// <summary>
/// 手机号 => 备注: 绑定的手机号
/// </summary>
public string? PhoneNum { get; set; }
/// <summary>
/// 邮箱 => 备注: 绑定的邮箱
/// </summary>
public string? Email { get; set; }
/// <summary>
/// 是否活跃 => 备注: 是否活跃
/// </summary>
public Boolean IsActive { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreatedAt { get; set; }
/// <summary>
/// 最后一次登录方式,1手机号 => 备注: 最后一次登录方式,1手机号
/// </summary>
public Int32 LastLoginTypeAt { get; set; }
/// <summary>
/// 登录时间 => 备注: 最后一次登录时间
/// </summary>
public DateTime LastLoginAt { get; set; }
/// <summary>
/// 修改时间 => 备注: 修改时间
/// </summary>
public DateTime UpdatedAt { get; set; }
/// <summary>
/// 首次注册方式 => 备注: 首次注册方式
/// </summary>
public Int32 RegisterType { get; set; }
/// <summary>
/// Ip地址 => 备注: Ip地址
/// </summary>
public string? Ip { get; set; }
/// <summary>
/// 0正常1注销
/// </summary>
public virtual int State { get; set; }
/// <summary>
/// 是否是测试账号
/// </summary>
public virtual bool? IsTest { get; set; }
}

View File

@ -0,0 +1,47 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 用户货币表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_User_Currency : DefaultEntityV4
{
/// <summary>
/// 货币类型 => 备注: 货币类型
/// </summary>
public Int32 CurrencyType { get; set; }
/// <summary>
/// 货币名称 => 备注: 货币名称
/// </summary>
public string? CurrencyName { get; set; }
/// <summary>
/// 货币余额 => 备注: 货币余额
/// </summary>
public Decimal CurrencyMoney { get; set; }
/// <summary>
/// 修改时间 => 备注: 修改时间
/// </summary>
public DateTime UpdateAt { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateAt { get; set; }
/// <summary>
/// 用户Id => 备注: 用户Id
/// </summary>
public Int32 UserId { get; set; }
}

View File

@ -0,0 +1,53 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 用户金额记录表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_User_Currency_Log : DefaultEntityV4
{
/// <summary>
/// 用户 => 备注: 用户
/// </summary>
public Int32 UserId { get; set; }
/// <summary>
/// 金额类型 => 备注: 金额类型
/// </summary>
public Int32 CurrencyType { get; set; }
/// <summary>
/// 金额 => 备注: 金额
/// </summary>
public Decimal Consume { get; set; }
/// <summary>
/// 消耗类型 => 备注: 消耗类型,0消耗1增加
/// </summary>
public Int32 ConsumeType { get; set; }
/// <summary>
/// 备注 => 备注: 备注
/// </summary>
public string? Remarks { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改时间 => 备注: 修改时间
/// </summary>
public DateTime UpdateTime { get; set; }
}

View File

@ -0,0 +1,78 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 意向订单表
/// </summary>
[EntityDescription(FieldIgnored = true)]
[Table("T_User_IntentOrder")]
public class T_User_IntentOrder : DefaultEntityV4
{
/// <summary>
/// 用户Id => 备注: 用户Id
/// </summary>
public Int32 UserId { get; set; }
/// <summary>
/// 产品id => 备注: 产品id
/// </summary>
public string? ProductId { get; set; }
/// <summary>
/// 支付方式 => 备注: 支付方式
/// </summary>
public string? Method { get; set; }
/// <summary>
/// 价格 => 备注: 价格
/// </summary>
public Decimal Price { get; set; }
/// <summary>
/// 数量 => 备注: 数量
/// </summary>
public Int32 Quantity { get; set; }
/// <summary>
/// 状态 => 备注: 状态
/// </summary>
public Int32 Status { get; set; }
/// <summary>
/// 备注 => 备注: 备注
/// </summary>
public string? Notes { get; set; }
/// <summary>
/// 订单创建时间 => 备注: 订单创建时间
/// </summary>
public DateTime IntentDate { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreatedAt { get; set; }
/// <summary>
/// 修改时间 => 备注: 修改时间
/// </summary>
public DateTime UpdatedAt { get; set; }
/// <summary>
/// 订单Id => 备注: 订单Id
/// </summary>
public string? OrderId { get; set; }
}

View File

@ -0,0 +1,55 @@
using MiaoYu.Core.EntityFramework.Models;
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 手机号登录表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_User_Phone_Account : DefaultEntityV4
{
/// <summary>
/// 用户Id => 备注: 用户Id
/// </summary>
public Int32 UserId { get; set; }
/// <summary>
/// 手机号 => 备注: 手机号
/// </summary>
public string? PhoneNum { get; set; }
/// <summary>
/// 验证码 => 备注: 验证码
/// </summary>
public string? VerificationCode { get; set; }
/// <summary>
/// 最后一次登录时间 => 备注: 最后一次登录时间
/// </summary>
public DateTime LastLoginAt { get; set; }
/// <summary>
/// 修改时间 => 备注: 修改时间
/// </summary>
public DateTime CreatedAt { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime UpdatedAt { get; set; }
/// <summary>
/// 用户昵称 => 备注: 用户昵称
/// </summary>
public string? NikeName { get; set; }
}

View File

@ -0,0 +1,53 @@
namespace MiaoYu.Repository.ChatAI.Admin.Entities.Apps;
/// <summary>
/// 验证码表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public class T_Verification_Code : DefaultEntityV4
{
/// <summary>
/// 手机号或者邮箱 => 备注: 手机号或者邮箱
/// </summary>
public string? Key { get; set; }
/// <summary>
/// 验证码 => 备注: 验证码
/// </summary>
public string? Code { get; set; }
/// <summary>
/// 创建天 => 备注: 创建天
/// </summary>
public Int32 CreateDay { get; set; }
/// <summary>
/// 过期时间 => 备注: 过期时间
/// </summary>
public DateTime ExpireAt { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateAt { get; set; }
/// <summary>
/// 备注 => 备注: 备注
/// </summary>
public string? Remarks { get; set; }
/// <summary>
/// 0手机1邮箱 => 备注: 0手机1邮箱
/// </summary>
public Int32 VerificationType { get; set; }
}

View File

@ -0,0 +1,72 @@
using FreeSql.DatabaseModel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Newtonsoft.Json;
using FreeSql.DataAnnotations;
using MiaoYu.Core.EntityFramework.Models;
namespace MiaoYu.Repository.ChatAI.Admin.Entities
{
/// <summary>
/// 图片表
/// </summary>
[EntityDescription(FieldIgnored = true)]
public partial class T_Image_Config : DefaultEntityV4
{
/// <summary>
/// 图片Id
/// </summary>
public int ImageId { get; set; }
/// <summary>
/// 图片名称
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// 图片地址
/// </summary>
public string Url { get; set; } = null!;
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateAt { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public DateTime UpdateAt { get; set; }
/// <summary>
/// oss存放路径
/// </summary>
public string? OssPath { get; set; }
/// <summary>
/// 存储桶
/// </summary>
public string? Bucket { get; set; }
/// <summary>
/// 地域
/// </summary>
public string? Region { get; set; }
/// <summary>
/// 图片类型
/// </summary>
public int ImageType { get; set; }
}
}

View File

@ -0,0 +1,67 @@
using FreeSql.DatabaseModel;@{
var gen = Model as RazorModel;
Func<string, string> GetAttributeString = attr => {
if (string.IsNullOrEmpty(attr)) return "";
return string.Concat(", ", attr.Trim('[', ']'));
};
Func<string, string> GetDefaultValue = defval => {
if (string.IsNullOrEmpty(defval)) return "";
return " = " + defval + ";";
};
}@{
switch (gen.fsql.Ado.DataType) {
case FreeSql.DataType.PostgreSQL:
@:using System;
@:using System.Collections;
@:using System.Collections.Generic;
@:using System.Linq;
@:using System.Reflection;
@:using System.Threading.Tasks;
@:using Newtonsoft.Json;
@:using FreeSql.DataAnnotations;
@:using System.Net;
@:using Newtonsoft.Json.Linq;
@:using System.Net.NetworkInformation;
@:using NpgsqlTypes;
@:using Npgsql.LegacyPostgis;
break;
case FreeSql.DataType.SqlServer:
case FreeSql.DataType.MySql:
default:
@:using System;
@:using System.Collections;
@:using System.Collections.Generic;
@:using System.Linq;
@:using System.Reflection;
@:using System.Threading.Tasks;
@:using Newtonsoft.Json;
@:using FreeSql.DataAnnotations;
break;
}
}
namespace @gen.NameSpace {
@if (string.IsNullOrEmpty(gen.table.Comment) == false) {
@:/// <summary>
@:/// @gen.table.Comment.Replace("\r\n", "\n").Replace("\n", "\r\n /// ")
@:/// </summary>
}
[JsonObject(MemberSerialization.OptIn)@GetAttributeString(gen.GetTableAttribute())]
public partial class @gen.GetCsName(gen.FullTableName) {
@foreach (var col in gen.columns) {
if (string.IsNullOrEmpty(col.Comment) == false) {
@:/// <summary>
@:/// @col.Comment.Replace("\r\n", "\n").Replace("\n", "\r\n /// ")
@:/// </summary>
}
@:@("[JsonProperty" + GetAttributeString(gen.GetColumnAttribute(col, true)) + "]")
@:public @gen.GetCsType(col) @gen.GetCsName(col.Name) { get; set; }@GetDefaultValue(gen.GetColumnDefaultValue(col, false))
@:
}
}
@gen.GetMySqlEnumSetDefine()
}

View File

@ -0,0 +1,2 @@

FreeSql.Generator -Razor "__razor.cshtml.txt" -NameOptions 1,0,0,0 -NameSpace MiaoYu.Repository.ChatAI.Admin.Entities -DB "SqlServer,data source=192.168.195.2;initial catalog=MiaoYu;User Id=zpc;Password=zpc;TrustServerCertificate=true;pooling=true;max pool size=2" -FileName "{name}.cs"

View File

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Rougamo />
</Weavers>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="Rougamo" minOccurs="0" maxOccurs="1" type="xs:anyType" />
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<DocumentationFile>$(MSBuildProjectName).xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Entities\Apps\T_Image_Config.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Rougamo.Fody" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MiaoYu.Core.EntityFramework\MiaoYu.Core.EntityFramework.csproj" />
<ProjectReference Include="..\MiaoYu.Core.Logs\MiaoYu.Core.Logs.csproj" />
<ProjectReference Include="..\MiaoYu.Core.Quartz\MiaoYu.Core.Quartz.csproj" />
<ProjectReference Include="..\MiaoYu.Core\MiaoYu.Core.csproj" />
<ProjectReference Include="..\MiaoYu.Core.CodeGenerator\MiaoYu.Core.CodeGenerator.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Entities\Apps\" />
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,60 @@
using MiaoYu.Repository.ChatAI.Admin.Entities;
#nullable disable
namespace MiaoYu.Repository.ChatAI.Admin.Migrations
{
[DbContext(typeof(ChatAdminDbContext))]
public class ChatAdminDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity<T_Image_Config>(entity =>
{
entity.HasKey(e => e.Id).HasName("PK__T_Image___3214EC072BCFE4E5");
entity.ToTable(tb => tb.HasComment("图片表"));
entity.Property(e => e.Bucket)
.HasMaxLength(100)
.HasComment("存储桶");
entity.Property(e => e.CreateAt)
.HasComment("创建时间")
.HasColumnType("datetime");
entity.Property(e => e.ImageId).HasComment("图片Id");
entity.Property(e => e.Name)
.HasMaxLength(50)
.HasComment("图片名称");
entity.Property(e => e.OssPath)
.HasMaxLength(200)
.HasComment("oss存放路径");
entity.Property(e => e.Region)
.HasMaxLength(100)
.HasComment("地域");
entity.Property(e => e.TenantId).HasComment("租户");
entity.Property(e => e.UpdateAt)
.HasComment("修改时间")
.HasColumnType("datetime");
entity.Property(e => e.Url)
.HasMaxLength(500)
.HasComment("图片地址");
//添加全局筛选器
//if (this.TenantInfo != null)
//{
// entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId);
//}
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,8 @@
namespace MiaoYu.Repository.ChatAI.Admin.Models;
public class ChatAdminRepositoryOptions : RepositoryOptions
{
}

View File

@ -0,0 +1,78 @@
namespace MiaoYu.Repository.ChatAI.Admin.Providers;
/// <summary>
/// MiaoYuChat 数据源提供者
/// </summary>
[Component]
public class MiaoYuChatDataSourceProvider : IDataSourceProvider, IScopedDependency
{
private readonly IRepository<M_Songs> _repository;
public MiaoYuChatDataSourceProvider(IRepository<M_Songs> repository)
{
_repository = repository;
}
public DataSourceConfig Config => new DataSourceConfig
{
DatabaseKey = DataSourceConstants.MiaoYuChat,
DisplayName = "妙语聊天",
EntityNamespace = typeof(ChatAdminRepositoryStartup).Namespace!,
ServiceNamespace = "MiaoYu.Api.Admin.ApplicationServices.Apps",
ControllerNamespace = "MiaoYu.Api.Admin.Controllers.Apps",
ClientServiceNamespace = "",
ModelPathTemplate = "{RootPath}\\{Namespace}\\Entities\\Apps\\{EntityNamePlural}",
ServicePathTemplate = "{AppPath}\\ApplicationServices\\Apps\\ChatAI\\{EntityNamePlural}",
ControllerPathTemplate = "{AppPath}\\Controllers\\Apps\\ChatAI\\{EntityNamePlural}",
ClientIndexPathTemplate = "{RootPath}\\admin-client\\src\\views\\apps\\chatai\\{TableNameLower}s",
ClientInfoPathTemplate = "{RootPath}\\admin-client\\src\\views\\apps\\chatai\\{TableNameLower}s",
ClientServicePathTemplate = "{RootPath}\\admin-client\\src\\services\\apps\\chatai\\{TableNameLower}s",
MenuPathTemplate = "views/apps/chatai/{TableNameLower}s/Index.vue",
RouterPathTemplate = "/apps/chatai/{TableNameLower}s",
TemplatePath = "/wwwroot/code_generation/template/",
NamingStrategy = EntityNamingStrategy.ToPascalCase,
Order = 2,
EnableEntityPrefix = false,
EntityPrefix = "",
UsesPluralPath = true
};
public List<CoreDbTableInfo> GetTables()
{
var freeSqlTables = _repository.UnitOfWork.FreeSqlOrm.DbFirst.GetTablesByDatabase();
return ConvertToDbTableInfoList(freeSqlTables);
}
public object GetDbContext() => _repository.GetContext()!;
private List<CoreDbTableInfo> ConvertToDbTableInfoList(List<FreeSql.DatabaseModel.DbTableInfo> freeSqlTables)
{
var result = new List<CoreDbTableInfo>();
foreach (var table in freeSqlTables)
{
var dbTableInfo = new CoreDbTableInfo
{
DataBase = Config.DatabaseKey,
Schema = table.Schema,
Name = table.Name,
Type = table.Type.ToString(),
Comment = table.Comment,
Columns = table.Columns?.Select(c => new CoreDbColumnInfo
{
Name = c.Name,
Comment = c.Comment,
IsPrimary = c.IsPrimary,
IsIdentity = c.IsIdentity,
IsNullable = c.IsNullable,
Position = c.Position,
DbType = c.DbTypeTextFull,
CsType = c.CsType?.Name,
MaxLength = c.MaxLength
}).ToList()
};
result.Add(dbTableInfo);
}
return result;
}
}

View File

@ -0,0 +1,33 @@
global using MiaoYu.Core.EntityFramework;
global using MiaoYu.Core.EntityFramework.Interceptors;
global using MiaoYu.Core.Quartz.Models;
global using HZY.Framework.Core.AspNetCore;
global using HZY.Framework.Core.Quartz;
global using HZY.Framework.Repository.EntityFramework;
global using HZY.Framework.Repository.EntityFramework.Attributes;
global using HZY.Framework.Repository.EntityFramework.Models;
global using HZY.Framework.Repository.EntityFramework.Models.Enums;
global using HZY.Framework.Repository.EntityFramework.Models.Standard;
global using HZY.Framework.Repository.EntityFramework.Repositories;
global using HZY.Framework.Repository.EntityFramework.Repositories.Impl;
global using Microsoft.AspNetCore.Builder;
global using Microsoft.AspNetCore.Hosting;
global using Microsoft.EntityFrameworkCore;
global using Microsoft.EntityFrameworkCore.Infrastructure;
global using Microsoft.Extensions.Caching.Memory;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Hosting;
global using Microsoft.Extensions.Logging;
global using System.ComponentModel.DataAnnotations;
global using System.ComponentModel.DataAnnotations.Schema;
global using System.Reflection;
global using MiaoYu.Core.Logs;
global using System.Text;
global using MiaoYu.Core.EntityFramework.Models;
global using HZY.Framework.DependencyInjection;
global using HZY.Framework.DependencyInjection.Attributes;
global using MiaoYu.Core.CodeGenerator.Abstractions;
global using CoreDbTableInfo = MiaoYu.Core.CodeGenerator.Models.DbTableInfo;
global using CoreDbColumnInfo = MiaoYu.Core.CodeGenerator.Models.DbColumnInfo;
global using MiaoYu.Repository.ChatAI.Admin.Entities.Apps;

View File

@ -0,0 +1,264 @@
# 腾讯云COS服务接口迁移文档
## 📋 更新概述
本次更新将腾讯云COS相关接口从 `TImageConfigController` 迁移到独立的 `CosController`实现服务分离COS服务不再与业务数据库关联。
---
## 🆕 一、新增接口
### 1.1 获取COS签名
**接口信息:**
- **请求路径**`GET /api/v1/admin/Cos/GetCosSign`
- **请求方法**`GET`
- **是否需要认证**:是
- **描述**获取腾讯云COS预签名URL
**请求参数:**
**响应示例:**
```json
"https://cos.ap-shanghai.myqcloud.com/miaoyu-1308826010/exampleobject?sign=..."
```
**响应字段说明:**
- 返回类型:`string`
- 说明预签名的COS上传URL
---
### 1.2 获取临时密钥
**接口信息:**
- **请求路径**`GET /api/v1/admin/Cos/GetGenerateTemporaryKey`
- **请求方法**`GET`
- **是否需要认证**:是
- **描述**获取腾讯云COS临时访问密钥STS
**请求参数:**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| fileName | string | 否 | 文件名,不传则生成时间戳文件名 |
| modelName | string | 否 | 模型名称,默认值为 "images" |
**请求示例:**
```http
GET /api/v1/admin/Cos/GetGenerateTemporaryKey?fileName=test.jpg&modelName=images
```
**响应示例:**
```json
{
"credentials": {
"token": "xxx",
"tmpSecretId": "xxx",
"tmpSecretKey": "xxx"
},
"expiration": "2024-12-07T10:00:00Z",
"expiredTime": 1701936000,
"startTime": 1701935400,
"requestId": "xxx",
"bucket": "miaoyu-1308826010",
"region": "ap-shanghai",
"prefixes": "miaoyu",
"filePath": "miaoyu/images/20241207/1701936000.jpg",
"domainName": "https://cos.shhuanmeng.com/"
}
```
**响应字段说明:**
| 字段名 | 类型 | 说明 |
|--------|------|------|
| credentials | object | 临时访问凭证 |
| credentials.token | string | 临时Token |
| credentials.tmpSecretId | string | 临时SecretId |
| credentials.tmpSecretKey | string | 临时SecretKey |
| expiration | string | 过期时间ISO8601格式 |
| expiredTime | number | 过期时间Unix时间戳 |
| startTime | number | 开始时间Unix时间戳 |
| requestId | string | 请求ID |
| bucket | string | 存储桶名称 |
| region | string | 地域 |
| prefixes | string | 路径前缀 |
| filePath | string | 文件路径 |
| domainName | string | 访问域名 |
---
## ⚠️ 二、废弃接口
以下接口已废弃,请使用新的接口替代:
### 2.1 废弃获取COS签名
- **旧接口路径**`GET /api/v1/admin/TImageConfig/GetCosSign`
- **新接口路径**`GET /api/v1/admin/Cos/GetCosSign`
- **状态**:❌ 已废弃,请使用新接口
### 2.2 废弃:获取临时密钥
- **旧接口路径**`GET /api/v1/admin/TImageConfig/GetGenerateTemporaryKey`
- **新接口路径**`GET /api/v1/admin/Cos/GetGenerateTemporaryKey`
- **状态**:❌ 已废弃,请使用新接口
---
## 🔄 三、接口迁移对照表
| 功能 | 旧接口 | 新接口 | 状态 |
|------|--------|--------|------|
| 获取COS签名 | `GET /api/v1/admin/TImageConfig/GetCosSign` | `GET /api/v1/admin/Cos/GetCosSign` | ✅ 已迁移 |
| 获取临时密钥 | `GET /api/v1/admin/TImageConfig/GetGenerateTemporaryKey` | `GET /api/v1/admin/Cos/GetGenerateTemporaryKey` | ✅ 已迁移 |
---
## 📝 四、前端修改说明
### 4.1 接口地址变更
**修改前:**
```typescript
// 获取COS签名
const getCosSign = async () => {
return axios.get('/api/v1/admin/TImageConfig/GetCosSign');
};
// 获取临时密钥
const getTemporaryKey = async (fileName?: string, modelName?: string) => {
return axios.get('/api/v1/admin/TImageConfig/GetGenerateTemporaryKey', {
params: { fileName, modelName }
});
};
```
**修改后:**
```typescript
// 获取COS签名
const getCosSign = async () => {
return axios.get('/api/v1/admin/Cos/GetCosSign');
};
// 获取临时密钥
const getTemporaryKey = async (fileName?: string, modelName?: string) => {
return axios.get('/api/v1/admin/Cos/GetGenerateTemporaryKey', {
params: { fileName, modelName }
});
};
```
### 4.2 API服务更新
**建议更新 API 服务文件:**
```typescript
// api/cos.ts
export const cosApi = {
// 获取COS签名
getCosSign: (): Promise<string> => {
return axios.get('/api/v1/admin/Cos/GetCosSign').then(res => res.data);
},
// 获取临时密钥
getTemporaryKey: (params?: {
fileName?: string;
modelName?: string;
}): Promise<GenerateTemporaryModel> => {
return axios.get('/api/v1/admin/Cos/GetGenerateTemporaryKey', {
params
}).then(res => res.data);
}
};
```
### 4.3 类型定义(如需要)
```typescript
// types/cos.ts
export interface GenerateTemporaryModel {
credentials: {
token: string;
tmpSecretId: string;
tmpSecretKey: string;
};
expiration: string;
expiredTime: number;
startTime: number;
requestId: string;
bucket: string;
region: string;
prefixes: string;
filePath: string;
domainName: string;
}
```
---
## ✨ 五、注意事项
### 5.1 接口兼容性
- **旧接口已完全废弃**,不再可用
- **新接口的参数和返回值与旧接口完全一致**,仅路径变更
- **无需修改业务逻辑**,只需更新接口地址
### 5.2 权限控制
- 新接口需要认证(`[Authorize]`
- 权限控制规则与旧接口一致
- 如果旧接口有特殊权限配置,新接口保持相同配置
### 5.3 错误处理
- 错误响应格式保持不变
- 错误码和错误信息保持一致
- 前端错误处理逻辑无需修改
---
## 🔍 六、验证清单
请确认以下内容已完成:
- [ ] 更新所有调用 `TImageConfig/GetCosSign` 的代码
- [ ] 更新所有调用 `TImageConfig/GetGenerateTemporaryKey` 的代码
- [ ] 更新 API 服务文件中的接口地址
- [ ] 测试新接口是否正常工作
- [ ] 移除对旧接口的引用
- [ ] 更新相关文档和注释
---
## 📞 七、技术支持
如有疑问,请联系后端开发团队。
**文档版本**v1.0
**更新日期**2024年12月
**后端版本**COS服务分离重构版本
---
## 📚 附录:完整接口列表
### 新接口列表
1. **获取COS签名**
- `GET /api/v1/admin/Cos/GetCosSign`
2. **获取临时密钥**
- `GET /api/v1/admin/Cos/GetGenerateTemporaryKey?fileName={fileName}&modelName={modelName}`
### 已废弃接口列表
1. ~~`GET /api/v1/admin/TImageConfig/GetCosSign`~~
2. ~~`GET /api/v1/admin/TImageConfig/GetGenerateTemporaryKey`~~
---
**文档结束**