新增农户功能升级:身份证OCR/OSS上传、头像采集、同名村检测、Region热度排序及表单体验优化
- Region 表新增热度列,热门省份优先显示 - 区县下拉按地级市分组、已录区县优先、支持全省搜索 - 组选择内置一组至二十组 - 银行卡号独立行+粗体预览,开户行独立行 - 新增农户类型:农户/个体户/合作社/经营集体/公司 - 身份证正反面支持高拍仪/摄像头OCR与手机扫码上传,附件存本地/OSS - 新增农户头像采集组件(摄像头/本地上传),预留人脸识别收购扩展 - 同名村弹窗提醒(防选错乡镇) - 编辑窗体禁止遮罩/Esc误关,整体加宽适配高频操作 - 修复二维码局域网手机无法访问(监听0.0.0.0、局域网IP识别、Vite代理兜底)
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
using AgriculturalPlatform.Api.Data;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace AgriculturalPlatform.Api.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 行政区划接口:
|
||||
/// 省、市、县、乡镇来自 AreaCity 全国公开行政区划数据(Regions 表,深 0~3);
|
||||
/// 村、组来自农户档案表(Famers 表已录入数据,去重后作为下拉选项)。
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/regions")]
|
||||
[Authorize]
|
||||
public class RegionsController(AppDbContext db) : ControllerBase
|
||||
{
|
||||
/// <summary>省(自治区/直辖市)列表,热门省份(热度值高)优先</summary>
|
||||
[HttpGet("provinces")]
|
||||
public async Task<ActionResult<string[]>> Provinces()
|
||||
{
|
||||
var items = await db.Regions
|
||||
.Where(r => r.Deep == 0)
|
||||
.OrderByDescending(r => r.Hot)
|
||||
.ThenBy(r => r.Id)
|
||||
.Select(r => r.ExtName)
|
||||
.ToListAsync();
|
||||
return Ok(items);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按省获取县(区/县级市)列表,附带所属地级市(city)用于前端分组,
|
||||
/// used=true 表示数据库农户表中已录入过该区县(前端优先展示)。
|
||||
/// </summary>
|
||||
[HttpGet("counties")]
|
||||
public async Task<ActionResult> Counties(string? province)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(province)) return BadRequest(new { message = "请先选择省份" });
|
||||
var prov = await db.Regions.FirstOrDefaultAsync(r => r.Deep == 0 && r.ExtName == province);
|
||||
if (prov == null) return Ok(Array.Empty<object>());
|
||||
|
||||
var items = await (from c in db.Regions
|
||||
join city in db.Regions on c.Pid equals city.Id
|
||||
where city.Pid == prov.Id && c.Deep == 2
|
||||
orderby city.Id, c.Id
|
||||
select new { name = c.ExtName, city = city.ExtName })
|
||||
.ToListAsync();
|
||||
|
||||
var usedNames = await db.Farmers
|
||||
.Where(f => f.County != null && f.County != "")
|
||||
.Select(f => f.County)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
var used = new HashSet<string>(usedNames, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
return Ok(items.Select(c => new { c.name, c.city, used = used.Contains(c.name) }));
|
||||
}
|
||||
|
||||
/// <summary>按县获取乡镇(街道)列表(公开数据 + 农户表已录入数据补充)</summary>
|
||||
[HttpGet("townships")]
|
||||
public async Task<ActionResult<string[]>> Townships(string? county, string? city)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(county)) return BadRequest(new { message = "请先选择县(区)" });
|
||||
|
||||
var countyQuery = db.Regions.Where(r => r.Deep == 2 && r.ExtName == county);
|
||||
if (!string.IsNullOrWhiteSpace(city))
|
||||
{
|
||||
var cityRow = await db.Regions.FirstOrDefaultAsync(r => r.Deep == 1 && r.ExtName == city);
|
||||
if (cityRow != null) countyQuery = countyQuery.Where(r => r.Pid == cityRow.Id);
|
||||
}
|
||||
var ids = await countyQuery.Select(r => r.Id).ToListAsync();
|
||||
|
||||
var builtin = ids.Count > 0
|
||||
? await db.Regions.Where(r => r.Deep == 3 && ids.Contains(r.Pid))
|
||||
.OrderBy(r => r.Id).Select(r => r.ExtName).ToListAsync()
|
||||
: [];
|
||||
|
||||
var fromDb = await db.Farmers
|
||||
.Where(f => f.County == county && f.Township != null && f.Township != "")
|
||||
.Select(f => f.Township)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
return Ok(builtin.Union(fromDb).OrderBy(x => x).ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 村列表(来自农户表,按县/乡镇过滤去重),返回 { name, township } 对象数组。
|
||||
/// 不传 township 时返回全县所有村(含所属乡镇),供前端做同名村检测。
|
||||
/// </summary>
|
||||
[HttpGet("villages")]
|
||||
public async Task<ActionResult> Villages(string? county, string? township)
|
||||
{
|
||||
var q = db.Farmers.Where(f => f.Village != null && f.Village != "");
|
||||
if (!string.IsNullOrWhiteSpace(township))
|
||||
q = q.Where(f => f.Township == township);
|
||||
else if (!string.IsNullOrWhiteSpace(county))
|
||||
q = q.Where(f => f.County == county);
|
||||
var items = await q
|
||||
.Select(f => new { f.Village, f.Township })
|
||||
.Distinct()
|
||||
.OrderBy(x => x.Village)
|
||||
.ToListAsync();
|
||||
return Ok(items.Select(x => new { name = x.Village, township = x.Township ?? "" }));
|
||||
}
|
||||
|
||||
/// <summary>组列表(来自农户表,按县/乡镇/村过滤去重)</summary>
|
||||
[HttpGet("groups")]
|
||||
public async Task<ActionResult<string[]>> Groups(string? county, string? township, string? village)
|
||||
{
|
||||
var q = db.Farmers.Where(f => f.GroupName != null && f.GroupName != "");
|
||||
if (!string.IsNullOrWhiteSpace(village))
|
||||
q = q.Where(f => f.Village == village);
|
||||
else if (!string.IsNullOrWhiteSpace(township))
|
||||
q = q.Where(f => f.Township == township);
|
||||
else if (!string.IsNullOrWhiteSpace(county))
|
||||
q = q.Where(f => f.County == county);
|
||||
var items = await q.Select(f => f.GroupName).Distinct().OrderBy(x => x).ToListAsync();
|
||||
return Ok(items);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user