campus-errand/server/Endpoints/ConfigEndpoints.cs
18631081161 5a04e003ca
All checks were successful
continuous-integration/drone/push Build is passing
聊天,金额,UI
2026-04-01 21:26:13 +08:00

219 lines
8.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using CampusErrand.Data;
using CampusErrand.Models;
using CampusErrand.Models.Dtos;
using Microsoft.EntityFrameworkCore;
namespace CampusErrand.Endpoints;
public static class ConfigEndpoints
{
public static void MapConfigEndpoints(this WebApplication app)
{
// 获取页面顶图配置
app.MapGet("/api/config/page-banner/{page}", async (string page, AppDbContext db) =>
{
var key = $"page_banner_{page}";
var config = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == key);
return Results.Ok(new ConfigResponse
{
Key = key,
Value = config?.Value ?? "",
UpdatedAt = config?.UpdatedAt ?? DateTime.MinValue
});
});
// 获取客服二维码
app.MapGet("/api/config/qrcode", async (AppDbContext db) =>
{
var config = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == "qrcode");
return Results.Ok(new ConfigResponse
{
Key = "qrcode",
Value = config?.Value ?? "",
UpdatedAt = config?.UpdatedAt ?? DateTime.MinValue
});
});
// 获取用户协议
app.MapGet("/api/config/agreement", async (AppDbContext db) =>
{
var config = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == "agreement");
return Results.Ok(new ConfigResponse
{
Key = "agreement",
Value = config?.Value ?? "",
UpdatedAt = config?.UpdatedAt ?? DateTime.MinValue
});
});
// 获取隐私政策
app.MapGet("/api/config/privacy", async (AppDbContext db) =>
{
var config = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == "privacy");
return Results.Ok(new ConfigResponse
{
Key = "privacy",
Value = config?.Value ?? "",
UpdatedAt = config?.UpdatedAt ?? DateTime.MinValue
});
});
// 获取跑腿协议
app.MapGet("/api/config/runner-agreement", async (AppDbContext db) =>
{
var config = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == "runner_agreement");
return Results.Ok(new ConfigResponse
{
Key = "runner_agreement",
Value = config?.Value ?? "",
UpdatedAt = config?.UpdatedAt ?? DateTime.MinValue
});
});
// 获取提现说明
app.MapGet("/api/config/withdrawal-guide", async (AppDbContext db) =>
{
var config = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == "withdrawal_guide");
return Results.Ok(new ConfigResponse
{
Key = "withdrawal_guide",
Value = config?.Value ?? "",
UpdatedAt = config?.UpdatedAt ?? DateTime.MinValue
});
});
// 获取最低佣金配置
app.MapGet("/api/config/min-commission", async (AppDbContext db) =>
{
var config = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == "min_commission");
return Results.Ok(new ConfigResponse
{
Key = "min_commission",
Value = config?.Value ?? "1.0",
UpdatedAt = config?.UpdatedAt ?? DateTime.MinValue
});
});
// 获取最低提现金额配置
app.MapGet("/api/config/min-withdrawal", async (AppDbContext db) =>
{
var config = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == "min_withdrawal");
return Results.Ok(new ConfigResponse
{
Key = "min_withdrawal",
Value = config?.Value ?? "1",
UpdatedAt = config?.UpdatedAt ?? DateTime.MinValue
});
});
// 管理端获取指定配置
app.MapGet("/api/admin/config/{key}", async (string key, AppDbContext db) =>
{
var config = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == key);
return Results.Ok(new ConfigResponse
{
Key = key,
Value = config?.Value ?? "",
UpdatedAt = config?.UpdatedAt ?? DateTime.MinValue
});
}).RequireAuthorization("AdminOnly");
// 管理端更新系统配置
app.MapPut("/api/admin/config/{key}", async (string key, UpdateConfigRequest request, AppDbContext db) =>
{
// 允许的配置键白名单
var allowedKeys = new HashSet<string>
{
"qrcode", "agreement", "privacy", "runner_agreement", "withdrawal_guide", "freeze_days",
"min_commission", "min_withdrawal",
"page_banner_pickup", "page_banner_delivery", "page_banner_help", "page_banner_purchase", "page_banner_food",
"page_banner_order-hall"
};
if (!allowedKeys.Contains(key))
return Results.BadRequest(new { code = 400, message = $"不支持的配置键: {key}" });
var config = await db.SystemConfigs.FirstOrDefaultAsync(c => c.Key == key);
if (config == null)
{
config = new SystemConfig
{
Key = key,
Value = request.Value,
UpdatedAt = DateTime.UtcNow
};
db.SystemConfigs.Add(config);
}
else
{
config.Value = request.Value;
config.UpdatedAt = DateTime.UtcNow;
}
await db.SaveChangesAsync();
return Results.Ok(new ConfigResponse
{
Key = config.Key,
Value = config.Value,
UpdatedAt = config.UpdatedAt
});
}).RequireAuthorization("AdminOnly");
// 图片上传接口
app.MapPost("/api/upload/image", async (IFormFile file, IConfiguration config) =>
{
if (file == null || file.Length == 0)
return Results.BadRequest(new { code = 400, message = "请选择要上传的图片" });
// 文件大小校验(默认 5MB
var maxSize = config.GetValue<long>("Upload:MaxFileSizeBytes", 5242880);
if (file.Length > maxSize)
return Results.BadRequest(new { code = 400, message = $"图片大小不能超过 {maxSize / 1024 / 1024}MB" });
// 文件扩展名校验
var allowedExtensions = config.GetSection("Upload:AllowedExtensions").Get<string[]>()
?? new[] { ".jpg", ".jpeg", ".png", ".gif", ".webp" };
var ext = Path.GetExtension(file.FileName).ToLowerInvariant();
if (!allowedExtensions.Contains(ext))
return Results.BadRequest(new { code = 400, message = $"不支持的图片格式,仅支持 {string.Join(", ", allowedExtensions)}" });
// 上传到腾讯云 COS
var cosConfig = new COSXML.CosXmlConfig.Builder()
.IsHttps(true)
.SetRegion(config["COS:Region"])
.Build();
var credential = new COSXML.Auth.DefaultQCloudCredentialProvider(
config["COS:SecretId"], config["COS:SecretKey"], 600);
var cosXml = new COSXML.CosXmlServer(cosConfig, credential);
var bucket = config["COS:Bucket"]!;
var cosKey = $"uploads/{DateTime.UtcNow:yyyyMMdd}/{Guid.NewGuid()}{ext}";
// 将上传文件写入临时文件
var tempPath = Path.GetTempFileName();
try
{
using (var stream = new FileStream(tempPath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
var putRequest = new COSXML.Model.Object.PutObjectRequest(bucket, cosKey, tempPath);
var putResult = cosXml.PutObject(putRequest);
if (putResult.httpCode != 200)
return Results.BadRequest(new { code = 400, message = "图片上传失败" });
var url = $"{config["COS:BaseUrl"]}/{cosKey}";
return Results.Ok(new UploadImageResponse { Url = url });
}
finally
{
if (File.Exists(tempPath)) File.Delete(tempPath);
}
}).RequireAuthorization()
.DisableAntiforgery();
}
}