feat: 实现微信登录和用户信息管理功能
- 添加微信登录功能,支持通过微信小程序登录 - 实现用户信息管理接口,包括获取用户信息和统计数据 - 新增投资组合列表和总资产统计接口 - 完善JWT令牌生成逻辑,支持可选用户名 - 添加数据库初始化配置和连接字符串 - 移除传统登录和注册功能,专注微信登录方案
This commit is contained in:
parent
2fe0b0c134
commit
d39a6347cd
@ -4,6 +4,8 @@ using AssetManager.Services.Services;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using AssetManager.Data;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace AssetManager.API.Controllers;
|
namespace AssetManager.API.Controllers;
|
||||||
|
|
||||||
@ -14,69 +16,16 @@ public class AuthController : ControllerBase
|
|||||||
private readonly ILogger<AuthController> _logger;
|
private readonly ILogger<AuthController> _logger;
|
||||||
private readonly WechatService _wechatService;
|
private readonly WechatService _wechatService;
|
||||||
private readonly JwtService _jwtService;
|
private readonly JwtService _jwtService;
|
||||||
|
private readonly DatabaseService _databaseService;
|
||||||
|
|
||||||
public AuthController(ILogger<AuthController> logger, WechatService wechatService, JwtService jwtService)
|
public AuthController(ILogger<AuthController> logger, WechatService wechatService, JwtService jwtService, DatabaseService databaseService)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_wechatService = wechatService;
|
_wechatService = wechatService;
|
||||||
_jwtService = jwtService;
|
_jwtService = jwtService;
|
||||||
|
_databaseService = databaseService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("login")]
|
|
||||||
public ActionResult<ApiResponse<LoginResponse>> Login([FromBody] LoginRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_logger.LogInformation($"Login attempt for user: {request.Email}");
|
|
||||||
|
|
||||||
// 模拟登录验证
|
|
||||||
if (request.Email == "test@example.com" && request.Password == "password123")
|
|
||||||
{
|
|
||||||
// 生成真实的JWT令牌
|
|
||||||
var token = _jwtService.GenerateToken("1", "Test User", request.Email);
|
|
||||||
|
|
||||||
var response = new LoginResponse
|
|
||||||
{
|
|
||||||
Token = token,
|
|
||||||
ExpireAt = DateTime.Now.AddHours(24).ToString("yyyy-MM-dd HH:mm:ss"),
|
|
||||||
User = new UserBasicInfo
|
|
||||||
{
|
|
||||||
UserName = "Test User",
|
|
||||||
Email = request.Email
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_logger.LogInformation($"Login successful for user: {request.Email}");
|
|
||||||
|
|
||||||
return Ok(new ApiResponse<LoginResponse>
|
|
||||||
{
|
|
||||||
code = AssetManager.Models.StatusCodes.Success,
|
|
||||||
data = response,
|
|
||||||
message = "Login successful"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogWarning($"Login failed for user: {request.Email}");
|
|
||||||
|
|
||||||
return Unauthorized(new ApiResponse<LoginResponse>
|
|
||||||
{
|
|
||||||
code = AssetManager.Models.StatusCodes.Unauthorized,
|
|
||||||
data = null,
|
|
||||||
message = "Invalid email or password"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Error during login");
|
|
||||||
|
|
||||||
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<LoginResponse>
|
|
||||||
{
|
|
||||||
code = AssetManager.Models.StatusCodes.InternalServerError,
|
|
||||||
data = null,
|
|
||||||
message = ex.Message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("wechat-login")]
|
[HttpPost("wechat-login")]
|
||||||
public async Task<ActionResult<ApiResponse<WechatLoginResponse>>> WechatLogin([FromBody] WechatLoginRequest request)
|
public async Task<ActionResult<ApiResponse<WechatLoginResponse>>> WechatLogin([FromBody] WechatLoginRequest request)
|
||||||
@ -99,8 +48,43 @@ public class AuthController : ControllerBase
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从数据库中查找用户
|
||||||
|
var db = _databaseService.GetDb();
|
||||||
|
var user = db.Queryable<User>().Where(u => u.OpenId == authResult.OpenId).First();
|
||||||
|
|
||||||
|
// 如果用户不存在,创建一个新用户
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
user = new User
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid().ToString(),
|
||||||
|
OpenId = authResult.OpenId,
|
||||||
|
UserName = request.NickName ?? "Wechat User",
|
||||||
|
Email = $"{authResult.OpenId}@wechat.com",
|
||||||
|
MemberLevel = "普通会员",
|
||||||
|
RunningDays = 0,
|
||||||
|
SignalsCaptured = 0,
|
||||||
|
WinRate = 0,
|
||||||
|
TotalTrades = 0,
|
||||||
|
TotalReturn = 0,
|
||||||
|
CreatedAt = DateTime.Now,
|
||||||
|
UpdatedAt = DateTime.Now
|
||||||
|
};
|
||||||
|
db.Insertable(user).ExecuteCommand();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 更新用户信息
|
||||||
|
if (!string.IsNullOrEmpty(request.NickName) && user.UserName != request.NickName)
|
||||||
|
{
|
||||||
|
user.UserName = request.NickName;
|
||||||
|
user.UpdatedAt = DateTime.Now;
|
||||||
|
db.Updateable(user).ExecuteCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 生成真实的JWT令牌
|
// 生成真实的JWT令牌
|
||||||
var token = _jwtService.GenerateToken(authResult.OpenId, request.NickName ?? "Wechat User", $"{authResult.OpenId}@wechat.com");
|
var token = _jwtService.GenerateToken(user.Id, user.UserName, user.Email);
|
||||||
|
|
||||||
var response = new WechatLoginResponse
|
var response = new WechatLoginResponse
|
||||||
{
|
{
|
||||||
@ -108,13 +92,14 @@ public class AuthController : ControllerBase
|
|||||||
ExpireAt = DateTime.Now.AddHours(24).ToString("yyyy-MM-dd HH:mm:ss"),
|
ExpireAt = DateTime.Now.AddHours(24).ToString("yyyy-MM-dd HH:mm:ss"),
|
||||||
User = new UserBasicInfo
|
User = new UserBasicInfo
|
||||||
{
|
{
|
||||||
UserName = request.NickName ?? "Wechat User",
|
UserName = user.UserName,
|
||||||
Email = $"{authResult.OpenId}@wechat.com"
|
Email = user.Email
|
||||||
},
|
},
|
||||||
OpenId = authResult.OpenId
|
OpenId = authResult.OpenId,
|
||||||
|
UserId = user.Id
|
||||||
};
|
};
|
||||||
|
|
||||||
_logger.LogInformation($"Wechat login successful for user: {authResult.OpenId}");
|
_logger.LogInformation($"Wechat login successful for user: {user.Id}");
|
||||||
|
|
||||||
return Ok(new ApiResponse<WechatLoginResponse>
|
return Ok(new ApiResponse<WechatLoginResponse>
|
||||||
{
|
{
|
||||||
@ -135,40 +120,4 @@ public class AuthController : ControllerBase
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("register")]
|
|
||||||
public ActionResult<ApiResponse<RegisterResponse>> Register([FromBody] RegisterRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_logger.LogInformation($"Registration attempt for user: {request.Email}");
|
|
||||||
|
|
||||||
// 模拟注册
|
|
||||||
var response = new RegisterResponse
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid().ToString(),
|
|
||||||
Status = "success"
|
|
||||||
};
|
|
||||||
|
|
||||||
_logger.LogInformation($"Registration successful for user: {request.Email}");
|
|
||||||
|
|
||||||
return Ok(new ApiResponse<RegisterResponse>
|
|
||||||
{
|
|
||||||
code = AssetManager.Models.StatusCodes.Success,
|
|
||||||
data = response,
|
|
||||||
message = "Registration successful"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Error during registration");
|
|
||||||
|
|
||||||
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<RegisterResponse>
|
|
||||||
{
|
|
||||||
code = AssetManager.Models.StatusCodes.InternalServerError,
|
|
||||||
data = null,
|
|
||||||
message = ex.Message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -52,6 +52,68 @@ public class PortfolioController : ControllerBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public ActionResult<ApiResponse<GetPortfoliosResponse>> GetPortfolios()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Request to get portfolios");
|
||||||
|
|
||||||
|
var response = _portfolioService.GetPortfolios();
|
||||||
|
|
||||||
|
_logger.LogInformation("Portfolios retrieved successfully");
|
||||||
|
|
||||||
|
return Ok(new ApiResponse<GetPortfoliosResponse>
|
||||||
|
{
|
||||||
|
code = AssetManager.Models.StatusCodes.Success,
|
||||||
|
data = response,
|
||||||
|
message = "success"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error retrieving portfolios");
|
||||||
|
|
||||||
|
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<GetPortfoliosResponse>
|
||||||
|
{
|
||||||
|
code = AssetManager.Models.StatusCodes.InternalServerError,
|
||||||
|
data = null,
|
||||||
|
message = ex.Message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("assets")]
|
||||||
|
public ActionResult<ApiResponse<TotalAssetsResponse>> GetTotalAssets()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Request to get total assets");
|
||||||
|
|
||||||
|
var response = _portfolioService.GetTotalAssets();
|
||||||
|
|
||||||
|
_logger.LogInformation("Total assets retrieved successfully");
|
||||||
|
|
||||||
|
return Ok(new ApiResponse<TotalAssetsResponse>
|
||||||
|
{
|
||||||
|
code = AssetManager.Models.StatusCodes.Success,
|
||||||
|
data = response,
|
||||||
|
message = "success"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error retrieving total assets");
|
||||||
|
|
||||||
|
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<TotalAssetsResponse>
|
||||||
|
{
|
||||||
|
code = AssetManager.Models.StatusCodes.InternalServerError,
|
||||||
|
data = null,
|
||||||
|
message = ex.Message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public ActionResult<ApiResponse<PortfolioDetailResponse>> GetPortfolioById(string id)
|
public ActionResult<ApiResponse<PortfolioDetailResponse>> GetPortfolioById(string id)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using AssetManager.Models;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using AssetManager.Data;
|
||||||
|
|
||||||
namespace AssetManager.API.Controllers;
|
namespace AssetManager.API.Controllers;
|
||||||
|
|
||||||
@ -12,10 +13,12 @@ namespace AssetManager.API.Controllers;
|
|||||||
public class UserController : ControllerBase
|
public class UserController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ILogger<UserController> _logger;
|
private readonly ILogger<UserController> _logger;
|
||||||
|
private readonly DatabaseService _databaseService;
|
||||||
|
|
||||||
public UserController(ILogger<UserController> logger)
|
public UserController(ILogger<UserController> logger, DatabaseService databaseService)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_databaseService = databaseService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("info")]
|
[HttpGet("info")]
|
||||||
@ -25,14 +28,40 @@ public class UserController : ControllerBase
|
|||||||
{
|
{
|
||||||
_logger.LogInformation("Request to get user info");
|
_logger.LogInformation("Request to get user info");
|
||||||
|
|
||||||
// 模拟返回用户信息
|
// 从JWT中获取用户ID
|
||||||
|
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(userId))
|
||||||
|
{
|
||||||
|
return Unauthorized(new ApiResponse<UserInfoResponse>
|
||||||
|
{
|
||||||
|
code = AssetManager.Models.StatusCodes.Unauthorized,
|
||||||
|
data = null,
|
||||||
|
message = "User not authenticated"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从数据库中获取用户信息
|
||||||
|
var db = _databaseService.GetDb();
|
||||||
|
var user = db.Queryable<User>().Where(u => u.Id == userId).First();
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return NotFound(new ApiResponse<UserInfoResponse>
|
||||||
|
{
|
||||||
|
code = AssetManager.Models.StatusCodes.NotFound,
|
||||||
|
data = null,
|
||||||
|
message = "User not found"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var response = new UserInfoResponse
|
var response = new UserInfoResponse
|
||||||
{
|
{
|
||||||
UserName = "Test User",
|
UserName = user.UserName,
|
||||||
MemberLevel = "高级会员",
|
MemberLevel = user.MemberLevel,
|
||||||
RunningDays = 180,
|
RunningDays = user.RunningDays,
|
||||||
Avatar = "https://example.com/avatar.jpg",
|
Avatar = user.Avatar,
|
||||||
Email = "test@example.com"
|
Email = user.Email
|
||||||
};
|
};
|
||||||
|
|
||||||
_logger.LogInformation("User info retrieved successfully");
|
_logger.LogInformation("User info retrieved successfully");
|
||||||
@ -64,13 +93,39 @@ public class UserController : ControllerBase
|
|||||||
{
|
{
|
||||||
_logger.LogInformation("Request to get user stats");
|
_logger.LogInformation("Request to get user stats");
|
||||||
|
|
||||||
// 模拟返回用户统计数据
|
// 从JWT中获取用户ID
|
||||||
|
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(userId))
|
||||||
|
{
|
||||||
|
return Unauthorized(new ApiResponse<UserStatsResponse>
|
||||||
|
{
|
||||||
|
code = AssetManager.Models.StatusCodes.Unauthorized,
|
||||||
|
data = null,
|
||||||
|
message = "User not authenticated"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从数据库中获取用户信息
|
||||||
|
var db = _databaseService.GetDb();
|
||||||
|
var user = db.Queryable<User>().Where(u => u.Id == userId).First();
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return NotFound(new ApiResponse<UserStatsResponse>
|
||||||
|
{
|
||||||
|
code = AssetManager.Models.StatusCodes.NotFound,
|
||||||
|
data = null,
|
||||||
|
message = "User not found"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var response = new UserStatsResponse
|
var response = new UserStatsResponse
|
||||||
{
|
{
|
||||||
SignalsCaptured = 125,
|
SignalsCaptured = user.SignalsCaptured,
|
||||||
WinRate = 68.5,
|
WinRate = (double)user.WinRate,
|
||||||
TotalTrades = 320,
|
TotalTrades = user.TotalTrades,
|
||||||
AverageProfit = 5.2
|
AverageProfit = user.TotalTrades > 0 ? (double)user.TotalReturn / user.TotalTrades : 0
|
||||||
};
|
};
|
||||||
|
|
||||||
_logger.LogInformation("User stats retrieved successfully");
|
_logger.LogInformation("User stats retrieved successfully");
|
||||||
@ -102,11 +157,42 @@ public class UserController : ControllerBase
|
|||||||
{
|
{
|
||||||
_logger.LogInformation($"Request to update user info: {request.UserName}");
|
_logger.LogInformation($"Request to update user info: {request.UserName}");
|
||||||
|
|
||||||
// 模拟更新用户信息
|
// 从JWT中获取用户ID
|
||||||
|
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(userId))
|
||||||
|
{
|
||||||
|
return Unauthorized(new ApiResponse<UpdateUserResponse>
|
||||||
|
{
|
||||||
|
code = AssetManager.Models.StatusCodes.Unauthorized,
|
||||||
|
data = null,
|
||||||
|
message = "User not authenticated"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从数据库中获取用户信息
|
||||||
|
var db = _databaseService.GetDb();
|
||||||
|
var user = db.Queryable<User>().Where(u => u.Id == userId).First();
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return NotFound(new ApiResponse<UpdateUserResponse>
|
||||||
|
{
|
||||||
|
code = AssetManager.Models.StatusCodes.NotFound,
|
||||||
|
data = null,
|
||||||
|
message = "User not found"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新用户信息
|
||||||
|
user.UserName = request.UserName;
|
||||||
|
user.UpdatedAt = DateTime.Now;
|
||||||
|
db.Updateable(user).ExecuteCommand();
|
||||||
|
|
||||||
var response = new UpdateUserResponse
|
var response = new UpdateUserResponse
|
||||||
{
|
{
|
||||||
Status = "updated",
|
Status = "updated",
|
||||||
UserName = request.UserName
|
UserName = user.UserName
|
||||||
};
|
};
|
||||||
|
|
||||||
_logger.LogInformation("User info updated successfully");
|
_logger.LogInformation("User info updated successfully");
|
||||||
|
|||||||
@ -75,6 +75,9 @@ builder.Logging.AddDebug();
|
|||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// 初始化数据库
|
||||||
|
app.Services.InitializeDatabase();
|
||||||
|
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseSwagger();
|
app.UseSwagger();
|
||||||
|
|||||||
@ -5,5 +5,8 @@
|
|||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*",
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnection": "server=localhost;Database=assetmanager;Uid=root;Pwd=your_password;CharSet=utf8mb4;"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ public class SqlSugarConfig
|
|||||||
{
|
{
|
||||||
return new SqlSugarScope(new ConnectionConfig()
|
return new SqlSugarScope(new ConnectionConfig()
|
||||||
{
|
{
|
||||||
ConnectionString = "server=localhost;Database=assetmanager;Uid=root;Pwd=your_password;CharSet=utf8mb4;",
|
ConnectionString = "server=43.167.226.216;Database=assetmanager;Uid=AssetManager;Pwd=2XpcnYGTpB5BhJyG;CharSet=utf8mb4;",
|
||||||
DbType = DbType.MySql,
|
DbType = DbType.MySql,
|
||||||
IsAutoCloseConnection = true,
|
IsAutoCloseConnection = true,
|
||||||
InitKeyType = InitKeyType.Attribute,
|
InitKeyType = InitKeyType.Attribute,
|
||||||
|
|||||||
@ -4,14 +4,6 @@ public class LoginRequest
|
|||||||
{
|
{
|
||||||
public string Email { get; set; }
|
public string Email { get; set; }
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
public string OpenId { get; set; }
|
|
||||||
public string Nickname { get; set; }
|
|
||||||
public string AvatarUrl { get; set; }
|
|
||||||
public int Gender { get; set; }
|
|
||||||
public string Country { get; set; }
|
|
||||||
public string Province { get; set; }
|
|
||||||
public string City { get; set; }
|
|
||||||
public string Language { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LoginResponse
|
public class LoginResponse
|
||||||
@ -19,7 +11,7 @@ public class LoginResponse
|
|||||||
public string Token { get; set; }
|
public string Token { get; set; }
|
||||||
public string ExpireAt { get; set; }
|
public string ExpireAt { get; set; }
|
||||||
public UserBasicInfo User { get; set; }
|
public UserBasicInfo User { get; set; }
|
||||||
public UserInfo UserInfo { get; set; }
|
public string UserId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UserBasicInfo
|
public class UserBasicInfo
|
||||||
@ -28,44 +20,17 @@ public class UserBasicInfo
|
|||||||
public string Email { get; set; }
|
public string Email { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UserInfo
|
|
||||||
{
|
|
||||||
public string Id { get; set; }
|
|
||||||
public string UserName { get; set; }
|
|
||||||
public string Email { get; set; }
|
|
||||||
public string Avatar { get; set; }
|
|
||||||
public string MemberLevel { get; set; }
|
|
||||||
public int RunningDays { get; set; }
|
|
||||||
public int SignalsCaptured { get; set; }
|
|
||||||
public double WinRate { get; set; }
|
|
||||||
public int TotalTrades { get; set; }
|
|
||||||
public double TotalReturn { get; set; }
|
|
||||||
public string CreatedAt { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class WechatLoginResponse
|
public class WechatLoginResponse
|
||||||
{
|
{
|
||||||
public string Token { get; set; }
|
public string Token { get; set; }
|
||||||
public string ExpireAt { get; set; }
|
public string ExpireAt { get; set; }
|
||||||
public UserBasicInfo User { get; set; }
|
public UserBasicInfo User { get; set; }
|
||||||
public string OpenId { get; set; }
|
public string OpenId { get; set; }
|
||||||
}
|
public string UserId { get; set; }
|
||||||
|
|
||||||
public class RegisterRequest
|
|
||||||
{
|
|
||||||
public string Email { get; set; }
|
|
||||||
public string Password { get; set; }
|
|
||||||
public string UserName { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RegisterResponse
|
|
||||||
{
|
|
||||||
public string Id { get; set; }
|
|
||||||
public string Status { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WechatLoginRequest
|
public class WechatLoginRequest
|
||||||
{
|
{
|
||||||
public string Code { get; set; }
|
public string Code { get; set; }
|
||||||
public string NickName { get; set; }
|
public string? NickName { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -109,3 +109,33 @@ public class CreateTransactionResponse
|
|||||||
public string status { get; set; }
|
public string status { get; set; }
|
||||||
public string createdAt { get; set; }
|
public string createdAt { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class PortfolioListItem
|
||||||
|
{
|
||||||
|
public string id { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public string tags { get; set; }
|
||||||
|
public string status { get; set; }
|
||||||
|
public string statusType { get; set; }
|
||||||
|
public string iconChar { get; set; }
|
||||||
|
public string iconBgClass { get; set; }
|
||||||
|
public string iconTextClass { get; set; }
|
||||||
|
public double value { get; set; }
|
||||||
|
public string currency { get; set; }
|
||||||
|
public double returnRate { get; set; }
|
||||||
|
public string returnType { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetPortfoliosResponse
|
||||||
|
{
|
||||||
|
public List<PortfolioListItem> items { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TotalAssetsResponse
|
||||||
|
{
|
||||||
|
public double totalValue { get; set; }
|
||||||
|
public string currency { get; set; }
|
||||||
|
public double todayProfit { get; set; }
|
||||||
|
public string todayProfitCurrency { get; set; }
|
||||||
|
public double totalReturnRate { get; set; }
|
||||||
|
}
|
||||||
|
|||||||
@ -8,4 +8,6 @@ public interface IPortfolioService
|
|||||||
PortfolioDetailResponse GetPortfolioById(string id);
|
PortfolioDetailResponse GetPortfolioById(string id);
|
||||||
GetTransactionsResponse GetTransactions(string portfolioId, int limit, int offset);
|
GetTransactionsResponse GetTransactions(string portfolioId, int limit, int offset);
|
||||||
CreateTransactionResponse CreateTransaction(CreateTransactionRequest request);
|
CreateTransactionResponse CreateTransaction(CreateTransactionRequest request);
|
||||||
|
GetPortfoliosResponse GetPortfolios();
|
||||||
|
TotalAssetsResponse GetTotalAssets();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,4 +108,73 @@ public class PortfolioService : IPortfolioService
|
|||||||
createdAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
|
createdAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GetPortfoliosResponse GetPortfolios()
|
||||||
|
{
|
||||||
|
// 模拟获取投资组合列表
|
||||||
|
return new GetPortfoliosResponse
|
||||||
|
{
|
||||||
|
items = new List<PortfolioListItem>
|
||||||
|
{
|
||||||
|
new PortfolioListItem
|
||||||
|
{
|
||||||
|
id = "hfea-001",
|
||||||
|
name = "美股全天候杠杆",
|
||||||
|
tags = "HFEA · 季度调仓",
|
||||||
|
status = "监控中",
|
||||||
|
statusType = "green",
|
||||||
|
iconChar = "H",
|
||||||
|
iconBgClass = "bg-green-100",
|
||||||
|
iconTextClass = "text-green-700",
|
||||||
|
value = 156240,
|
||||||
|
currency = "USD",
|
||||||
|
returnRate = 42.82,
|
||||||
|
returnType = "positive"
|
||||||
|
},
|
||||||
|
new PortfolioListItem
|
||||||
|
{
|
||||||
|
id = "ma-002",
|
||||||
|
name = "纳指双均线趋势",
|
||||||
|
tags = "趋势跟踪 · 日线",
|
||||||
|
status = "等待信号",
|
||||||
|
statusType = "gray",
|
||||||
|
iconChar = "T",
|
||||||
|
iconBgClass = "bg-blue-100",
|
||||||
|
iconTextClass = "text-blue-700",
|
||||||
|
value = 412500,
|
||||||
|
currency = "USD",
|
||||||
|
returnRate = -1.79,
|
||||||
|
returnType = "negative"
|
||||||
|
},
|
||||||
|
new PortfolioListItem
|
||||||
|
{
|
||||||
|
id = "hk-003",
|
||||||
|
name = "港股价值投资",
|
||||||
|
tags = "价值投资 · 蓝筹",
|
||||||
|
status = "持有中",
|
||||||
|
statusType = "green",
|
||||||
|
iconChar = "H",
|
||||||
|
iconBgClass = "bg-green-100",
|
||||||
|
iconTextClass = "text-green-700",
|
||||||
|
value = 896000,
|
||||||
|
currency = "HKD",
|
||||||
|
returnRate = 12.56,
|
||||||
|
returnType = "positive"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public TotalAssetsResponse GetTotalAssets()
|
||||||
|
{
|
||||||
|
// 模拟获取总资产情况
|
||||||
|
return new TotalAssetsResponse
|
||||||
|
{
|
||||||
|
totalValue = 1284592.4,
|
||||||
|
currency = "CNY",
|
||||||
|
todayProfit = 12482,
|
||||||
|
todayProfitCurrency = "CNY",
|
||||||
|
totalReturnRate = 24.82
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,14 +21,19 @@ public class JwtService
|
|||||||
|
|
||||||
public string GenerateToken(string userId, string userName, string email)
|
public string GenerateToken(string userId, string userName, string email)
|
||||||
{
|
{
|
||||||
var claims = new[]
|
var claims = new List<Claim>
|
||||||
{
|
{
|
||||||
new Claim(JwtRegisteredClaimNames.Sub, userId),
|
new Claim(JwtRegisteredClaimNames.Sub, userId ?? ""),
|
||||||
new Claim(JwtRegisteredClaimNames.Name, userName),
|
new Claim(JwtRegisteredClaimNames.Email, email ?? ""),
|
||||||
new Claim(JwtRegisteredClaimNames.Email, email),
|
|
||||||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 如果userName不为null,添加到claims中
|
||||||
|
if (!string.IsNullOrEmpty(userName))
|
||||||
|
{
|
||||||
|
claims.Add(new Claim(JwtRegisteredClaimNames.Name, userName));
|
||||||
|
}
|
||||||
|
|
||||||
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secretKey));
|
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secretKey));
|
||||||
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
|
|||||||
@ -13,8 +13,8 @@ public class WechatService
|
|||||||
public WechatService(HttpClient httpClient)
|
public WechatService(HttpClient httpClient)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_appId = "your-wechat-app-id"; // 替换为实际的微信小程序AppId
|
_appId = "wx245f0f3ebcfcf5a7"; // 替换为实际的微信小程序AppId
|
||||||
_appSecret = "your-wechat-app-secret"; // 替换为实际的微信小程序AppSecret
|
_appSecret = "809c740129bc8b434177ce12ef292dd0"; // 替换为实际的微信小程序AppSecret
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<WechatAuthResult> GetOpenIdAsync(string code)
|
public async Task<WechatAuthResult> GetOpenIdAsync(string code)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user