新增农户功能升级:身份证OCR/OSS上传、头像采集、同名村检测、Region热度排序及表单体验优化
- Region 表新增热度列,热门省份优先显示 - 区县下拉按地级市分组、已录区县优先、支持全省搜索 - 组选择内置一组至二十组 - 银行卡号独立行+粗体预览,开户行独立行 - 新增农户类型:农户/个体户/合作社/经营集体/公司 - 身份证正反面支持高拍仪/摄像头OCR与手机扫码上传,附件存本地/OSS - 新增农户头像采集组件(摄像头/本地上传),预留人脸识别收购扩展 - 同名村弹窗提醒(防选错乡镇) - 编辑窗体禁止遮罩/Esc误关,整体加宽适配高频操作 - 修复二维码局域网手机无法访问(监听0.0.0.0、局域网IP识别、Vite代理兜底)
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
using AgriculturalPlatform.Api.Data;
|
||||
using AgriculturalPlatform.Api.Dtos;
|
||||
using AgriculturalPlatform.Api.Models;
|
||||
using AgriculturalPlatform.Api.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace AgriculturalPlatform.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/users")]
|
||||
[Authorize]
|
||||
public class UsersController(AppDbContext db, DataScopeService scope, CurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
/// <summary>用户列表(分页 + 数据权限)</summary>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<PagedResult<UserDto>>> List(
|
||||
string? role, string? orgId,
|
||||
[FromQuery] int page = 1, [FromQuery] int pageSize = 20, [FromQuery] string? keyword = null)
|
||||
{
|
||||
var visible = await scope.GetVisibleOrgIdsAsync(currentUser.Get());
|
||||
var query = db.Users.Include(u => u.Org).AsQueryable();
|
||||
if (visible is not null)
|
||||
query = query.Where(u => u.OrgId != null && visible.Contains(u.OrgId.Value));
|
||||
if (!string.IsNullOrWhiteSpace(role) && Enum.TryParse<UserRole>(role, out var userRole))
|
||||
query = query.Where(u => u.Role == userRole);
|
||||
if (int.TryParse(orgId, out var oid))
|
||||
query = query.Where(u => u.OrgId == oid);
|
||||
if (!string.IsNullOrWhiteSpace(keyword))
|
||||
query = query.Where(u => u.Username.Contains(keyword) || u.RealName.Contains(keyword) || u.Phone.Contains(keyword));
|
||||
|
||||
var total = await query.CountAsync();
|
||||
var items = await query.OrderByDescending(u => u.Id)
|
||||
.Skip((page - 1) * pageSize).Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
return Ok(new PagedResult<UserDto>(items.ToDtos(), total));
|
||||
}
|
||||
|
||||
/// <summary>新增用户</summary>
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<UserDto>> Create(UserSaveRequest req)
|
||||
{
|
||||
if (await db.Users.AnyAsync(u => u.Username == req.Username))
|
||||
return BadRequest(new { message = "用户名已存在" });
|
||||
if (!Enum.TryParse<UserRole>(req.Role, out var role))
|
||||
return BadRequest(new { message = "角色不正确" });
|
||||
|
||||
var user = new User
|
||||
{
|
||||
Username = req.Username,
|
||||
PasswordHash = BCrypt.Net.BCrypt.HashPassword(req.Password ?? "123456"),
|
||||
RealName = req.RealName,
|
||||
Phone = req.Phone,
|
||||
Role = role,
|
||||
OrgId = req.OrgId,
|
||||
IsActive = req.IsActive
|
||||
};
|
||||
db.Users.Add(user);
|
||||
await db.SaveChangesAsync();
|
||||
return Ok((await db.Users.Include(u => u.Org).FirstAsync(u => u.Id == user.Id)).ToDto());
|
||||
}
|
||||
|
||||
/// <summary>修改用户</summary>
|
||||
[HttpPut("{id:int}")]
|
||||
public async Task<ActionResult<UserDto>> Update(int id, UserSaveRequest req)
|
||||
{
|
||||
var user = await db.Users.FindAsync(id);
|
||||
if (user is null) return NotFound();
|
||||
if (req.Username != user.Username && await db.Users.AnyAsync(u => u.Username == req.Username))
|
||||
return BadRequest(new { message = "用户名已存在" });
|
||||
|
||||
user.Username = req.Username;
|
||||
user.RealName = req.RealName;
|
||||
user.Phone = req.Phone;
|
||||
if (Enum.TryParse<UserRole>(req.Role, out var role)) user.Role = role;
|
||||
user.OrgId = req.OrgId;
|
||||
user.IsActive = req.IsActive;
|
||||
if (!string.IsNullOrWhiteSpace(req.Password))
|
||||
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(req.Password);
|
||||
await db.SaveChangesAsync();
|
||||
return Ok((await db.Users.Include(u => u.Org).FirstAsync(u => u.Id == user.Id)).ToDto());
|
||||
}
|
||||
|
||||
/// <summary>重置密码</summary>
|
||||
[HttpPut("{id:int}/reset-password")]
|
||||
public async Task<IActionResult> ResetPassword(int id, [FromBody] string? newPassword = null)
|
||||
{
|
||||
var user = await db.Users.FindAsync(id);
|
||||
if (user is null) return NotFound();
|
||||
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(newPassword ?? "123456");
|
||||
await db.SaveChangesAsync();
|
||||
return Ok(new { message = "密码已重置为 " + (newPassword ?? "123456") });
|
||||
}
|
||||
|
||||
/// <summary>删除用户(禁止删除自己)</summary>
|
||||
[HttpDelete("{id:int}")]
|
||||
public async Task<IActionResult> Delete(int id)
|
||||
{
|
||||
var cu = currentUser.Get()!;
|
||||
if (id == cu.Id) return BadRequest(new { message = "不能删除当前登录账号" });
|
||||
var user = await db.Users.FindAsync(id);
|
||||
if (user is null) return NotFound();
|
||||
db.Users.Remove(user);
|
||||
await db.SaveChangesAsync();
|
||||
return Ok(new { message = "删除成功" });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user