This commit is contained in:
2026-07-15 23:04:46 +08:00
parent 4ef892e15e
commit c94b3ce200
28 changed files with 562 additions and 10 deletions

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<Content Update="applicationsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Service\Application.Domain.Entity\Application.Domain.Entity.csproj" />
<ProjectReference Include="..\Service\Application.Domain\Application.Domain.csproj" />
<ProjectReference Include="..\Service\Application.Service.Pub\Application.Service.Pub.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Areas\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,89 @@
using Microsoft.AspNetCore.Mvc;
namespace Application.Web.Admin.Controllers;
public class AccMoneyController : Controller
{
private readonly IUnitUserAccService _accService;
private readonly IUnitUserService _userService;
private readonly IMessageService _messageService;
public AccMoneyController(IUnitUserAccService accService, IUnitUserService userService,
IMessageService messageService)
{
_accService = accService;
_userService = userService;
_messageService = messageService;
}
// GET
public IActionResult Index()
{
return View();
}
[HttpPost]
public async Task<IActionResult> UpAcc(string u, long c, string t, string r, string p)
{
string url = "/AccMoney/Index";
var user = await _userService.GetUserInfoByUserNo(u);
if (user == null)
{
TempData["msg"] = "用户不存在!";
return Redirect(url);
}
if (await _accService.UpdateUserAccBath(user.userId, 1, t, c, p, r))
{
TempData["msg"] = "发放成功!";
string accName = GetCurrName(t);
string msg =$"亲爱的玩家,您的【{accName}】账户有变动,账户额度+{c},备注:[{r}];祝您驰骋四海,纵横天下!";
await _messageService.SendMaill(user.userId, "账户操作通知", msg, new List<TowerGet>());
return Redirect(url);
}
else
{
TempData["msg"] = "发放失败!";
return Redirect(url);
}
}
public static string GetCurrName(string accType)
{
string result = string.Empty;
switch (accType)
{
case "copper":
result = "铜贝";
break;
case "cowry":
result = "金贝";
break;
case "gold":
result = "金元";
break;
case "teach":
result = "师德";
break;
case "renown":
result = "声望";
break;
case "charm":
result = "魅力";
break;
case "enemy":
result = "罪恶值";
break;
}
return result;
}
}

View File

@@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
namespace Application.Web.Admin.Controllers;
public class IndexController : Controller
{
// GET
public IActionResult Index()
{
return View();
}
}

View File

@@ -0,0 +1,97 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace Application.Web.Admin.Controllers;
public class SendMailController : Controller
{
private readonly IMessageService _messageService;
private readonly IGameGoodsService _goodsService;
private readonly IUnitUserService _userService;
public SendMailController(IMessageService messageService,IGameGoodsService goodsService,IUnitUserService userService)
{
_messageService = messageService;
_goodsService = goodsService;
_userService = userService;
}
// GET
public IActionResult Index()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Send(string id, string name, string sign, string awData, int goods, int count, string remark, int type)
{
string url = "/SendMail/Index";
List<TowerGet> award = new List<TowerGet>();
if (string.IsNullOrEmpty(awData))
{
if (goods != 0)
{
var goodsInfo = await _goodsService.GetGoodsInfo(goods);
if (goodsInfo == null)
{
TempData["msg"] = "物品不存在!";
return Redirect(url);
}
TowerGet add = new TowerGet();
add.code = GameEnum.PropCode.Goods.ToString();
add.name = goodsInfo.goodsName;
add.parameter = goods.ToString();
add.count = count;
award.Add(add);
}
}
else
{
award = JsonConvert.DeserializeObject<List<TowerGet>>(awData);
}
int index = 0;
List<string> users = new List<string>();
if (type == 0)
{
string[] ids = id.Split(',');
foreach (string item in ids)
{
var userInfo = await _userService.GetUserInfoByUserNo(item.Trim());
if (userInfo == null)
{
continue;
}
index++;
users.Add(userInfo.userId);
}
}
else if (type == 1)
{
DateTime time = TimeAssist.GetDateTimeYMD(0);
var data = await _userService.GetOnlineUserByTime(TimeExtend.GetTimeStampBySeconds(time));
foreach (var item in data)
{
users.Add(item.userId);
index++;
}
}
else
{
var data = await _userService.GetOnlineUserByTime(0);
foreach (var item in data)
{
users.Add(item.userId);
index++;
}
}
if (await _messageService.SendMaill(users, name, sign, award))
{
TempData["msg"] = string.Format("发放成功,共完成{0}个!", index);
return Redirect(url);
}
else
{
TempData["msg"] = "发放失败!";
return Redirect(url);
}
}
}

View File

@@ -0,0 +1,13 @@
global using Photon.Core;
global using Photon.Core.Jwt;
global using Photon.Core.Services;
global using Photon.Core.SqlSugar;
global using Photon.Core.Assist;
global using Photon.Core.Timer;
global using SqlSugar;
global using Application.Service.Pub;
global using Application.Domain;
global using Application.Domain.Entity;
global using Microsoft.AspNetCore.Authorization;
global using Microsoft.AspNetCore.Mvc;

View File

@@ -0,0 +1,65 @@
using Photon.Core.Redis;
var builder = WebApplication.CreateBuilder(args);
builder.Services.Inject(new List<string> {
"Application.Web.Admin","Application.Domain"
});//框架初始化
builder.Configuration.RegisterConfig();//注入配置
builder.Services.InjectRedis(builder.Configuration);
builder.Services.InjectSql(builder.Configuration);
//日志
builder.Logging.InjectLog();
// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
#region
builder.Services.AddCors(options =>
{
options.AddPolicy("all", builder =>
{
builder.AllowAnyOrigin() //允许任何来源的主机访问
.AllowAnyMethod()
.AllowAnyHeader();
});
});
#endregion
builder.Services.AddSignalR();
var app = builder.Build();
app.Services.UseInject();//启用框架
app.Configuration.UseConfig();//启用配置
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseCors("all");
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Index}/{action=Index}/{id?}")
.WithStaticAssets();
SnowflakeAssist.Initialize(0, 0);
app.Run();

View File

@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5270",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7023;http://localhost:5270",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,24 @@
<form method="post" action="/AccMoney/UpAcc">
ID:<input type="text" value="" name="u" /><br />
充值账户:
<select name="t">
<option value="copper">铜贝</option>
<option value="gold">金元</option>
<option value="cowry">金贝</option>
<option value="teach">师德</option>
<option value="renown">声望</option>
<option value="charm">魅力</option>
<option value="enemy">罪恶值</option>
</select><br />
金额:<input type="number" value="" name="c" /><br />
充值类型:
<select name="p">
<option value="其他">其他</option>
<option value="充值">充值</option>
</select><br />
备注:<input type="text" value="" name="r" /><br />
<input type="submit" value="发放" />
<div style="color:red">
* @TempData["msg"]
</div>
</form>

View File

@@ -0,0 +1,7 @@
<div>
1.<a href="/SendMail/Index">邮件发放</a>
</div>
<div>
2.<a href="/AccMoney/Index">账户充值</a>
</div>

View File

@@ -0,0 +1,26 @@
<div>
<form action="/SendMail/Send" method="post">
发送类型:<select name="type">
<option value="0">指定玩家</option>
<option value="1">当天在线</option>
<option value="2">全部玩家</option>
</select><br />
ID:<textarea name="id" cols="10" style="width:300px" rows="5"></textarea><br />
邮件主题:<input name="name" type="text" /> <br />
邮件内容:<textarea name="sign" cols="10" style="width:300px" rows="5"></textarea><br />
=======附件=====<br />
多附件字符:<textarea name="awData" cols="10" style="width:300px" rows="5"></textarea><br />
<br />
*当只有一个附件时,可以填写以下内容。
<br />
物品ID:<input name="goods" type="text" /><br />
数量:<input type="number" name="count" /><br />
说明:<input type="text" name="remark" /><br />
<br />
<br />
<input type="submit" value="发送" />
</form>
<div style="color:red">
* @TempData["msg"]
</div>
</div>

View File

@@ -0,0 +1,20 @@
@using Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="/css/table.css" asp-append-version="true" />
</head>
<body>
<div class="foot" style="margin-bottom:10px">
<a href="/">返回首页</a>
</div>
<div class="main">
@RenderBody()
</div>
</body>
</html>

View File

@@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

View File

@@ -0,0 +1,43 @@
{
"AutoProgram": 0,
"Redis": {
"connection": "81.70.212.61:6379,password=kx.20260711,defaultdatabase=5"
},
"SqlData": [
{
"type": 0,
"name": "Kg.SeaTime.Game",
"connect": "data source=81.70.212.61;database=kg.seatime.game;user id=root;password=1f5ozxRGE3Y;pooling=true;port=3306;sslmode=Required;charset=utf8mb4;"
},
{
"type": 0,
"name": "Kg.SeaTime.Resource",
"connect": "data source=81.70.212.61;database=kg.seatime.resource;user id=root;password=1f5ozxRGE3Y;pooling=true;port=3306;sslmode=Required;charset=utf8mb4;"
},
{
"type": 0,
"name": "Kg.SeaTime.Log",
"connect": "data source=81.70.212.61;database=kg.seatime.log;user id=root;password=1f5ozxRGE3Y;pooling=true;port=3306;sslmode=Required;charset=utf8mb4;"
}
],
"JwtTokenOptions": {
"Issuer": "kx.seatime",
"Audience": "kx.seatime",
"SecurityKey": "46055HR0n7FeNHhDKAYD2i9ZsdsYn4jn"
},
"ResUrl": {
"local": "http://192.168.0.142:5298",
"resUrl": "http://localhost:12206",
"imgCDN": "/",
"videoCDN": "/"
},
"Sms": {
"SmsType": 1,
"AccessKey": "AKIDVptgCRP5UcT4PTGm1yf5E6pKYVBajeKn",
"Secret": "FG2atxlKflcEclgKhnc9XeU3LM6YjdGf",
"signName": "探玩驿站",
"TemplateCode": "963929",
"SmsSdkAppId": "1400523979",
"SmsOnTime": 300
}
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -0,0 +1,25 @@
table {
border-collapse: collapse;
margin: 0 auto;
text-align: center;
margin-top: 20px;
}
table td, table th {
border: 1px solid #cad9ea;
color: #666;
height: 30px;
}
table thead th {
background-color: #CCE8EB;
width: 100px;
}
table tr:nth-child(odd) {
background: #fff;
}
table tr:nth-child(even) {
background: #F5FAFA;
}

View File

@@ -1,4 +1,5 @@
<Solution> <Solution>
<Project Path="Application.Web.Admin/Application.Web.Admin.csproj" />
<Project Path="Service/Application.Domain.Entity/Application.Domain.Entity.csproj" Id="2c4b3532-d29e-4dec-bcf3-eeceb1c374fc" /> <Project Path="Service/Application.Domain.Entity/Application.Domain.Entity.csproj" Id="2c4b3532-d29e-4dec-bcf3-eeceb1c374fc" />
<Project Path="Service/Application.Domain/Application.Domain.csproj" Id="78231809-eabc-4800-9c91-479adb485405" /> <Project Path="Service/Application.Domain/Application.Domain.csproj" Id="78231809-eabc-4800-9c91-479adb485405" />
<Project Path="Service/Application.Service.Pub/Application.Service.Pub.csproj" Id="3d90f467-0fcb-4074-bc96-33b36035ee23" /> <Project Path="Service/Application.Service.Pub/Application.Service.Pub.csproj" Id="3d90f467-0fcb-4074-bc96-33b36035ee23" />

View File

@@ -10,4 +10,8 @@
<ProjectReference Include="..\Application.Service.Pub\Application.Service.Pub.csproj" /> <ProjectReference Include="..\Application.Service.Pub\Application.Service.Pub.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="log\" />
</ItemGroup>
</Project> </Project>

View File

@@ -26,6 +26,9 @@ public interface IMessageService
Task<List<unit_user_mail>> GetUserMailData(string userId, int page, int limit, RefAsync<int> total); Task<List<unit_user_mail>> GetUserMailData(string userId, int page, int limit, RefAsync<int> total);
Task<unit_user_mail> GetMailInfo(string mailId); Task<unit_user_mail> GetMailInfo(string mailId);
Task<bool> SendMaill(string userId, string name, string sign, List<TowerGet> award, int days = 10); Task<bool> SendMaill(string userId, string name, string sign, List<TowerGet> award, int days = 10);
Task<bool> SendMaill(List<string> userIds, string name, string sign, List<TowerGet> award,
int days = 10);
Task<bool> UpdateMaillInfo(unit_user_mail data); Task<bool> UpdateMaillInfo(unit_user_mail data);
#endregion #endregion

View File

@@ -31,7 +31,7 @@ public interface IUnitUserService
#region #region
Task<int> GetOnlineCount(); Task<int> GetOnlineCount();
Task<List<unit_user_online>> GetOnlineUserByTime(long time);
#endregion #endregion

View File

@@ -194,7 +194,7 @@ public class MessageService(ISqlSugarClient DbClient, IRedisCache redis) : IMess
return count; return count;
} }
private async Task ClearMailCountCache(string userId) private async Task ClearMailCountCache(params string[] userId)
{ {
string key = string.Format(UserCache.BaseCacheKeys, "Message", "MailCount"); string key = string.Format(UserCache.BaseCacheKeys, "Message", "MailCount");
await redis.DelHashAsync(key, userId); await redis.DelHashAsync(key, userId);
@@ -240,6 +240,42 @@ public class MessageService(ISqlSugarClient DbClient, IRedisCache redis) : IMess
return result; return result;
} }
public async Task<bool> SendMaill(List<string> userIds, string name, string sign, List<TowerGet> award,
int days = 10)
{
List<unit_user_mail> data = new List<unit_user_mail>();
foreach (var userId in userIds)
{
unit_user_mail mail = new unit_user_mail();
mail.mailId = StringAssist.NewGuid;
mail.userId = userId;
mail.name = name;
mail.sign = sign;
mail.isRead = 0;
mail.isGet = award.Count > 0 ? 0 : 1;
mail.award = award;
mail.addTime = DateTime.Now;
mail.endTime = TimeExtend.GetTimeStampBySeconds(DateTime.Now.AddDays(days));
data.Add(mail);
}
if (data.Count > 0)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_mail>();
bool result = await db.Insertable(data).ExecuteCommandAsync() > 0;
if (result)
{
await ClearMailCountCache(userIds.ToArray());
}
return result;
}
else
{
return false;
}
}
public async Task<bool> UpdateMaillInfo(unit_user_mail data) public async Task<bool> UpdateMaillInfo(unit_user_mail data)
{ {
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_mail>(); var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_mail>();

View File

@@ -322,6 +322,12 @@ public class UnitUserService(ISqlSugarClient DbClient, IRedisCache redis) : IUni
return await db.Queryable<unit_user_online>().Where(it => it.upTime > time).CountAsync(); return await db.Queryable<unit_user_online>().Where(it => it.upTime > time).CountAsync();
} }
public async Task<List<unit_user_online>> GetOnlineUserByTime(long time)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_online>();
return await db.Queryable<unit_user_online>().Where(it => it.upTime > time).ToListAsync();
}
#endregion #endregion
#region #region

View File

@@ -1,6 +1,8 @@
using Photon.Core.Timer; using Jaina;
using Photon.Core.Redis;
using Photon.Core.Timer;
namespace Application.Domain; namespace Application.Web;
public class GameAutoJobService(ISqlSugarClient DbClient, IRedisCache redis, ITimerJobManager jobManager) public class GameAutoJobService(ISqlSugarClient DbClient, IRedisCache redis, ITimerJobManager jobManager)
: IGameAutoJobService, ITransient : IGameAutoJobService, ITransient

View File

@@ -1,4 +1,4 @@
namespace Application.Domain; namespace Application.Web;
public interface IGameAutoJobService public interface IGameAutoJobService
{ {

View File

@@ -186,17 +186,22 @@ public class TradeController : ControllerBase
if (info.code == nameof(GameEnum.PropCode.Equ)) if (info.code == nameof(GameEnum.PropCode.Equ))
{ {
unit_user_equ equInfo = JsonConvert.DeserializeObject<unit_user_equ>(info.content);
if (await _weightService.CheckUserWeight(userId, (int)equInfo.weight)==false)
{
return PoAction.Message("您的负重不足!");
}
var myAcc = await _accService.GetUserAccInfo(userId, nameof(AccEnum.AccType.copper)); var myAcc = await _accService.GetUserAccInfo(userId, nameof(AccEnum.AccType.copper));
if (myAcc < info.price) if (myAcc < info.price)
{ {
return PoAction.Message("您的铜贝不足!"); return PoAction.Message("您的铜贝不足!");
} }
if (await _accService.UpdateUserCopper(userId, 0, (long)info.price, $"交易支付:{info.name}")) if (await _accService.UpdateUserCopper(userId, 0, (long)info.price, $"交易支付:{info.name}"))
{ {
if (await _tradeService.UpdateTradeCount(info.tradeId, 0, 1, true)) if (await _tradeService.UpdateTradeCount(info.tradeId, 0, 1, true))
{ {
unit_user_equ equInfo = JsonConvert.DeserializeObject<unit_user_equ>(info.content);
equInfo.userId = userId; equInfo.userId = userId;
await _equService.AddUserEqu(equInfo, "交易获得"); await _equService.AddUserEqu(equInfo, "交易获得");
long GetCopper = Convert.ToInt64(info.price * 0.9M); long GetCopper = Convert.ToInt64(info.price * 0.9M);
@@ -220,6 +225,12 @@ public class TradeController : ControllerBase
} }
else if (info.code == nameof(GameEnum.PropCode.Goods)) else if (info.code == nameof(GameEnum.PropCode.Goods))
{ {
var goodsInfo = await _goodsService.GetGoodsInfo(Convert.ToInt32(info.propId));
int needWeight = (int)goodsInfo.weight * count;
if (await _weightService.CheckUserWeight(userId, needWeight)==false)
{
return PoAction.Message("您的负重不足!");
}
var myAcc = await _accService.GetUserAccInfo(userId, nameof(AccEnum.AccType.copper)); var myAcc = await _accService.GetUserAccInfo(userId, nameof(AccEnum.AccType.copper));
var needCopper = Convert.ToInt64(info.price) * count; var needCopper = Convert.ToInt64(info.price) * count;
if (myAcc < needCopper) if (myAcc < needCopper)

View File

@@ -1,6 +1,6 @@
using Photon.Core.Timer; using Photon.Core.Timer;
using Quartz; using Quartz;
namespace Application.Domain; namespace Application.Web;
public class AutoJob: ITimerAutoJob public class AutoJob: ITimerAutoJob
{ {

View File

@@ -2,7 +2,7 @@
using Quartz; using Quartz;
using Quartz.Spi; using Quartz.Spi;
namespace Application.Domain; namespace Application.Web;
public class JobStart: ITimerAutoStart public class JobStart: ITimerAutoStart
{ {
private readonly ISchedulerFactory _schedulerFactory; private readonly ISchedulerFactory _schedulerFactory;

View File

@@ -1,7 +1,7 @@
using Photon.Core.Timer; using Photon.Core.Timer;
using Quartz; using Quartz;
namespace Application.Domain; namespace Application.Web;
public class TimerJobManager : ITimerJobManager public class TimerJobManager : ITimerJobManager
{ {