This commit is contained in:
2026-03-30 11:07:30 +08:00
parent 2c44b3a4b2
commit d4a8e71733
74 changed files with 1751 additions and 421 deletions

View File

@@ -2,6 +2,7 @@ using System.Data.Common;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using StopShopping.EF;
using StopShopping.Services.Models;
using StopShopping.Services.Models.Req;
using StopShopping.Services.Models.Resp;
@@ -182,8 +183,8 @@ public class CategoryService : ICategoryService
{
Id = model.Id,
LogoUrl = string.IsNullOrWhiteSpace(model.Logo)
? ""
: _fileService.GetFileUrl(Models.UploadScences.Category, model.Logo),
? ""
: _fileService.GetFileUrl(UploadScences.Category, model.Logo),
Name = model.Name,
Order = model.Order,
ParentId = model.ParentId,

View File

@@ -41,13 +41,13 @@ public class ClaimsService : IClaimsService
return claimsIdentity;
}
public int GetCurrentUserId()
public int? GetCurrentUserId()
{
var currUserId = _httpContextAccessor.HttpContext
?.User.FindFirstValue(JwtRegisteredClaimNames.Sub);
if (string.IsNullOrWhiteSpace(currUserId))
throw new InvalidOperationException("在错误的位置获取当前登录用户");
return null;
return Convert.ToInt32(currUserId);
}

View File

@@ -1,4 +1,9 @@
using Microsoft.AspNetCore.Hosting;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using StopShopping.Services.Extensions;
using StopShopping.Services.Models;
@@ -9,50 +14,66 @@ namespace StopShopping.Services.Implementions;
public class FileService : IFileService
{
public FileService(IOptions<AppOptions> appOptions,
IWebHostEnvironment webHostEnvironment)
public FileService(
IHttpClientFactory httpClientFactory,
IOptions<AppOptions> options,
ILogger<FileService> logger)
{
_appOptions = appOptions.Value;
_env = webHostEnvironment;
_fileClient = httpClientFactory.CreateClient(Consts.FILE_API_CLIENT_NAME);
_options = options.Value;
_logger = logger;
}
private readonly AppOptions _appOptions;
private readonly IWebHostEnvironment _env;
private readonly HttpClient _fileClient;
private readonly AppOptions _options;
private readonly ILogger<FileService> _logger;
public async Task<ApiResponse<FileUpload>> UploadFileAsync(UploadParams payload)
private const string UPLOAD_PATH = "/upload";
public async Task<ApiResponse<FileUploadResp>> UploadFileAsync(UploadParams payload)
{
var newName = Guid.NewGuid().ToString("N").ToLower();
var extension = Path.GetExtension(payload.File!.FileName);
var newFullName = $"{newName}{extension}";
var relativeToRootPath = GetRelativeToRootPath(payload.Scences, newFullName);
var targetPath = Path.Combine(_env.WebRootPath, GetRelativeToRootPath(payload.Scences));
if (!Directory.Exists(targetPath))
try
{
Directory.CreateDirectory(targetPath);
var formData = new MultipartFormDataContent
{
{ new StringContent(((int)payload.Scences).ToString()), nameof(payload.Scences) },
};
var fileContent = new StreamContent(payload.File!.OpenReadStream());
fileContent.Headers.ContentType = new MediaTypeHeaderValue(payload.File.ContentType);
formData.Add(fileContent, nameof(payload.File), payload.File.FileName);
var resp = await _fileClient.PostAsync(UPLOAD_PATH, formData);
if (resp.IsSuccessStatusCode)
{
var deserialized = await resp.Content.ReadFromJsonAsync<ApiResponse<FileUploadResp>>();
if (null == deserialized)
throw new JsonException("上传失败");
return deserialized;
}
else
{
var deserialized = await resp.Content.ReadFromJsonAsync<ProblemDetails>();
if (null == deserialized)
throw new BadHttpRequestException("上传失败", (int)resp.StatusCode);
throw new BadHttpRequestException(
deserialized.Title ?? deserialized.Detail ?? "上传失败",
deserialized.Status ?? StatusCodes.Status400BadRequest);
}
}
using var file = new FileStream(
Path.Combine(_env.WebRootPath, relativeToRootPath),
FileMode.CreateNew,
FileAccess.Write);
await payload.File.CopyToAsync(file);
FileUpload result = new()
catch (Exception e)
{
NewName = newFullName,
Url = GetFileUrl(payload.Scences, newFullName)
};
return new ApiResponse<FileUpload>(result);
_logger.LogError(e, "上传失败");
throw;
}
}
public string GetFileUrl(UploadScences scences, string fileName)
{
var relativeToRootPath = GetRelativeToRootPath(scences, fileName);
return $"{_appOptions.DomainPath}/{relativeToRootPath.Replace(Path.DirectorySeparatorChar, '/')}";
return string.IsNullOrWhiteSpace(fileName)
? ""
: $"{_options.FileApiDomain}/{GetRelativeToRootPath(scences, fileName)
.Replace(Path.DirectorySeparatorChar, '/')}";
}
private string GetRelativeToRootPath(UploadScences scences, string fileName = "")

View File

@@ -44,7 +44,9 @@ public class ProductService : IProductService
var qry = _dbContext.Products
.AsNoTracking()
.Include(p => p.Category)
.Where(p => !p.Deleted && p.UserId == userId);
.Where(p => !p.Deleted);
if (userId.HasValue)
qry = qry.Where(p => p.UserId == userId);
if (model.CategoryId > 0)
{
var categoryPath = (await _dbContext.Categories
@@ -74,7 +76,8 @@ public class ProductService : IProductService
public async Task<ApiResponse> EditAsync(EditProductParams model)
{
var userId = _claimsService.GetCurrentUserId();
var userId = _claimsService.GetCurrentUserId()!.Value;
EF.Models.Product? product = null;
if (model.Id > 0)
{
@@ -112,7 +115,7 @@ public class ProductService : IProductService
public async Task<ApiResponse> DeleteAsync(ProductIdParams model)
{
var userId = _claimsService.GetCurrentUserId();
var userId = _claimsService.GetCurrentUserId()!.Value;
var product = await _dbContext.Products
.FirstOrDefaultAsync(p =>
p.Id == model.ProductId
@@ -169,11 +172,11 @@ public class ProductService : IProductService
CreateTime = product.CreateTime.ToFormatted(),
Description = product.Description,
Id = product.Id,
LogoUrl = _fileService.GetFileUrl(Models.UploadScences.Product, product.Logo),
MinimumUnit = product.MinimumUnit,
Name = product.Name,
UnitPrice = product.UnitPrice,
SoldAmount = product.SoldAmount,
LogoUrl = _fileService.GetFileUrl(Models.UploadScences.Product, product.Logo)
};
if (result is ProductInfo)
{
@@ -184,10 +187,5 @@ public class ProductService : IProductService
return result;
}
private string BuildCategoryPath(int categoryId)
{
return $"/{categoryId}/";
}
#endregion
}

View File

@@ -58,7 +58,7 @@ public class ReplyService : IReplyService
public async Task<ApiResponse> ReplyAsync(ReplyParams model)
{
var userId = _claimsService.GetCurrentUserId();
var userId = _claimsService.GetCurrentUserId()!.Value;
using var trans = await _dbContext.Database.BeginTransactionAsync();
try

View File

@@ -26,7 +26,7 @@ public class RequestService : IRequestService
public async Task<ApiResponse> PublishRequestAsync(CreateRequestParams model)
{
var serialNo = _serialNoGenerator.GenerateRequestNo();
var userId = _claimService.GetCurrentUserId();
var userId = _claimService.GetCurrentUserId()!.Value;
EF.Models.Request req = new()
{
@@ -62,7 +62,7 @@ public class RequestService : IRequestService
public async Task<ApiResponse> DeleteRequestAsync(RequestIdParams model)
{
var userId = _claimService.GetCurrentUserId();
var userId = _claimService.GetCurrentUserId()!.Value;
var request = await _dbContext.Requests
.Include(r => r.Replies)
@@ -126,7 +126,7 @@ public class RequestService : IRequestService
if (userRoles.HasValue)
{
var userId = _claimService.GetCurrentUserId();
var userId = _claimService.GetCurrentUserId()!.Value;
qry = userRoles.Value switch
{
UserRoles.Seller => qry.Where(q => q.Replies.Any(r => r.UserId == userId)),

View File

@@ -150,7 +150,7 @@ public class UserService : IUserService
public async Task<ApiResponse> ChangePasswordAsync(ChangePasswordParams model)
{
int userId = _claimsService.GetCurrentUserId();
int userId = _claimsService.GetCurrentUserId()!.Value;
var user = await _dbContext.Users
.FirstAsync(u => u.Id == userId);
@@ -166,7 +166,7 @@ public class UserService : IUserService
public async Task<ApiResponse<User>> GetUserInfoAsync()
{
var userId = _claimsService.GetCurrentUserId();
var userId = _claimsService.GetCurrentUserId()!.Value;
var model = await _dbContext.Users
.FirstAsync(u => u.Id == userId);
@@ -187,7 +187,7 @@ public class UserService : IUserService
public async Task<ApiResponse> EditAsync(EditUserParams model)
{
int userId = _claimsService.GetCurrentUserId();
int userId = _claimsService.GetCurrentUserId()!.Value;
var user = await _dbContext.Users.FirstAsync(u => u.Id == userId);
if (!string.IsNullOrWhiteSpace(model.AvatarFileName))
@@ -205,7 +205,7 @@ public class UserService : IUserService
public ApiResponse<List<Address>> GetAddresses()
{
var userId = _claimsService.GetCurrentUserId();
var userId = _claimsService.GetCurrentUserId()!.Value;
var addresses = _dbContext.Addresses
.Where(a => a.UserId == userId)
@@ -221,7 +221,7 @@ public class UserService : IUserService
{
EF.Models.Address? address = null;
var userId = _claimsService.GetCurrentUserId();
var userId = _claimsService.GetCurrentUserId()!.Value;
if (model.Id.HasValue && model.Id > 0)
{
@@ -253,7 +253,7 @@ public class UserService : IUserService
public async Task<ApiResponse> DeleteAddressAsync(int id)
{
var userId = _claimsService.GetCurrentUserId();
var userId = _claimsService.GetCurrentUserId()!.Value;
await _dbContext.Addresses
.Where(a => a.Id == id && a.UserId == userId)
.ExecuteDeleteAsync();