新增农户功能升级:身份证OCR/OSS上传、头像采集、同名村检测、Region热度排序及表单体验优化
- Region 表新增热度列,热门省份优先显示 - 区县下拉按地级市分组、已录区县优先、支持全省搜索 - 组选择内置一组至二十组 - 银行卡号独立行+粗体预览,开户行独立行 - 新增农户类型:农户/个体户/合作社/经营集体/公司 - 身份证正反面支持高拍仪/摄像头OCR与手机扫码上传,附件存本地/OSS - 新增农户头像采集组件(摄像头/本地上传),预留人脸识别收购扩展 - 同名村弹窗提醒(防选错乡镇) - 编辑窗体禁止遮罩/Esc误关,整体加宽适配高频操作 - 修复二维码局域网手机无法访问(监听0.0.0.0、局域网IP识别、Vite代理兜底)
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
using AgriculturalPlatform.Api.Models;
|
||||
|
||||
namespace AgriculturalPlatform.Api.Data;
|
||||
|
||||
/// <summary>初始化数据(仅在空库时执行)</summary>
|
||||
public static class DbSeeder
|
||||
{
|
||||
public static void Seed(AppDbContext db)
|
||||
{
|
||||
if (db.Users.Any()) return;
|
||||
|
||||
var now = DateTime.Now;
|
||||
|
||||
// ---------- 组织 ----------
|
||||
var company = new Organization
|
||||
{
|
||||
Type = OrgType.Company,
|
||||
Name = "绿源农产品收购有限公司",
|
||||
ContactPerson = "王建国",
|
||||
Phone = "13800000001",
|
||||
Address = "河南省郑州市中牟县官渡大道66号",
|
||||
TaxNo = "91410100MA3X8K7Q2B",
|
||||
CreatedAt = now
|
||||
};
|
||||
var stationEast = new Organization
|
||||
{
|
||||
Type = OrgType.Station,
|
||||
Name = "城东收购站",
|
||||
ContactPerson = "李强",
|
||||
Phone = "13800000002",
|
||||
Address = "中牟县官渡镇城东村",
|
||||
CreatedAt = now
|
||||
};
|
||||
var stationWest = new Organization
|
||||
{
|
||||
Type = OrgType.Station,
|
||||
Name = "城西收购站",
|
||||
ContactPerson = "赵敏",
|
||||
Phone = "13800000003",
|
||||
Address = "中牟县韩寺镇城西村",
|
||||
CreatedAt = now
|
||||
};
|
||||
var individual = new Organization
|
||||
{
|
||||
Type = OrgType.Individual,
|
||||
Name = "张伟(个体收购)",
|
||||
ContactPerson = "张伟",
|
||||
Phone = "13800000004",
|
||||
Address = "中牟县刁家乡",
|
||||
TaxNo = "410122197501011234",
|
||||
CreatedAt = now
|
||||
};
|
||||
|
||||
db.Organizations.AddRange(company, stationEast, stationWest, individual);
|
||||
db.SaveChanges();
|
||||
stationEast.ParentId = company.Id;
|
||||
stationWest.ParentId = company.Id;
|
||||
db.SaveChanges();
|
||||
|
||||
// ---------- 用户(默认密码均为 123456) ----------
|
||||
var users = new List<User>
|
||||
{
|
||||
new() { Username = "admin", PasswordHash = BCrypt.Net.BCrypt.HashPassword("123456"), RealName = "系统管理员", Phone = "13800000000", Role = UserRole.SuperAdmin, CreatedAt = now },
|
||||
new() { Username = "company", PasswordHash = BCrypt.Net.BCrypt.HashPassword("123456"), RealName = "王建国", Phone = "13800000001", Role = UserRole.CompanyAdmin, OrgId = company.Id, CreatedAt = now },
|
||||
new() { Username = "station1", PasswordHash = BCrypt.Net.BCrypt.HashPassword("123456"), RealName = "李强", Phone = "13800000002", Role = UserRole.StationStaff, OrgId = stationEast.Id, CreatedAt = now },
|
||||
new() { Username = "station2", PasswordHash = BCrypt.Net.BCrypt.HashPassword("123456"), RealName = "赵敏", Phone = "13800000003", Role = UserRole.StationStaff, OrgId = stationWest.Id, CreatedAt = now },
|
||||
new() { Username = "individual", PasswordHash = BCrypt.Net.BCrypt.HashPassword("123456"), RealName = "张伟", Phone = "13800000004", Role = UserRole.Individual, OrgId = individual.Id, CreatedAt = now }
|
||||
};
|
||||
db.Users.AddRange(users);
|
||||
db.SaveChanges();
|
||||
|
||||
// ---------- 品种 ----------
|
||||
var products = new List<Product>
|
||||
{
|
||||
new() { Name = "小麦", Category = "粮食", Unit = "公斤", Spec = "水分≤13%,容重≥750g/L", Price = 2.42m },
|
||||
new() { Name = "玉米", Category = "粮食", Unit = "公斤", Spec = "水分≤14%,杂质≤1%", Price = 2.18m },
|
||||
new() { Name = "水稻", Category = "粮食", Unit = "公斤", Spec = "出糙率≥77%", Price = 2.68m },
|
||||
new() { Name = "花生", Category = "油料", Unit = "公斤", Spec = "果仁饱满,出仁率≥70%", Price = 7.80m },
|
||||
new() { Name = "大蒜", Category = "蔬菜", Unit = "公斤", Spec = "5cm以上,干度达标", Price = 4.50m },
|
||||
new() { Name = "西红柿", Category = "蔬菜", Unit = "公斤", Spec = "一级果,单果150g以上", Price = 2.60m },
|
||||
new() { Name = "苹果", Category = "水果", Unit = "公斤", Spec = "红富士,直径75mm以上", Price = 5.20m },
|
||||
new() { Name = "棉花", Category = "经济作物", Unit = "公斤", Spec = "衣分≥38%", Price = 15.60m }
|
||||
};
|
||||
db.Products.AddRange(products);
|
||||
db.SaveChanges();
|
||||
|
||||
// ---------- 农户 ----------
|
||||
var farmers = new List<Farmer>
|
||||
{
|
||||
new() { Name = "刘老汉", IdCard = "410122197003120011", Gender = "男", Phone = "13911110001", Village = "城东村一组", Address = "城东村一组12号", BankName = "中牟农商银行", BankAccount = "6228480012345678901", CreditScore = 92 },
|
||||
new() { Name = "陈秀英", IdCard = "410122196806250022", Gender = "女", Phone = "13911110002", Village = "城东村二组", Address = "城东村二组8号", BankName = "中牟农商银行", BankAccount = "6228480012345678902", CreditScore = 88 },
|
||||
new() { Name = "张铁柱", IdCard = "410122198204170033", Gender = "男", Phone = "13911110003", Village = "城西村一组", Address = "城西村一组21号", BankName = "农业银行", BankAccount = "6228480012345678903", CreditScore = 85 },
|
||||
new() { Name = "王翠花", IdCard = "410122197512080044", Gender = "女", Phone = "13911110004", Village = "城西村三组", Address = "城西村三组5号", BankName = "邮政储蓄银行", BankAccount = "6228480012345678904", CreditScore = 90 },
|
||||
new() { Name = "赵大勇", IdCard = "410122199003300055", Gender = "男", Phone = "13911110005", Village = "官渡镇贾庄村", Address = "贾庄村16号", BankName = "中牟农商银行", BankAccount = "6228480012345678905", CreditScore = 82 },
|
||||
new() { Name = "孙秀兰", IdCard = "410122196511150066", Gender = "女", Phone = "13911110006", Village = "韩寺镇马家村", Address = "马家村9号", BankName = "农业银行", BankAccount = "6228480012345678906", CreditScore = 78 },
|
||||
new() { Name = "李保田", IdCard = "410122197807210077", Gender = "男", Phone = "13911110007", Village = "刁家乡水沱寨村", Address = "水沱寨村3号", BankName = "邮政储蓄银行", BankAccount = "6228480012345678907", CreditScore = 86 },
|
||||
new() { Name = "周桂芳", IdCard = "410122198906060088", Gender = "女", Phone = "13911110008", Village = "官渡镇前于村", Address = "前于村28号", BankName = "中牟农商银行", BankAccount = "6228480012345678908", CreditScore = 91 }
|
||||
};
|
||||
db.Farmers.AddRange(farmers);
|
||||
db.SaveChanges();
|
||||
|
||||
// ---------- 历史收购单(近30天,用于报表与大屏演示) ----------
|
||||
var rnd = new Random(20260812);
|
||||
var purchaserIds = new[] { company.Id, stationEast.Id, stationWest.Id, individual.Id };
|
||||
var productIds = products.Select(p => p.Id).ToArray();
|
||||
var farmerIds = farmers.Select(f => f.Id).ToArray();
|
||||
var userIds = users.Select(u => u.Id).ToArray();
|
||||
|
||||
var orders = new List<PurchaseOrder>();
|
||||
for (int day = 29; day >= 0; day--)
|
||||
{
|
||||
int count = rnd.Next(3, 8);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var createAt = now.Date.AddDays(-day).AddHours(rnd.Next(7, 18)).AddMinutes(rnd.Next(0, 59));
|
||||
var productId = productIds[rnd.Next(productIds.Length)];
|
||||
var gross = rnd.Next(5000, 32000);
|
||||
var tare = rnd.Next(3200, 9000);
|
||||
var net = gross - tare;
|
||||
if (net <= 0) continue;
|
||||
var price = products.First(p => p.Id == productId).Price + (decimal)rnd.Next(-10, 10) / 10m;
|
||||
|
||||
orders.Add(new PurchaseOrder
|
||||
{
|
||||
OrderNo = $"CG{createAt:yyyyMMdd}-{(day * 10 + i):D4}",
|
||||
FarmerId = farmerIds[rnd.Next(farmerIds.Length)],
|
||||
ProductId = productId,
|
||||
PurchaserOrgId = purchaserIds[rnd.Next(purchaserIds.Length)],
|
||||
Grade = new[] { "一等", "二等", "三等" }[rnd.Next(3)],
|
||||
Unit = "公斤",
|
||||
UnitPrice = price,
|
||||
GrossWeight = gross,
|
||||
TareWeight = tare,
|
||||
NetWeight = net,
|
||||
Amount = Math.Round(net * price, 2),
|
||||
WeighCount = 2,
|
||||
Status = PurchaseStatus.Completed,
|
||||
OperatorId = userIds[rnd.Next(userIds.Length)],
|
||||
WeighInAt = createAt,
|
||||
WeighOutAt = createAt.AddMinutes(rnd.Next(15, 50)),
|
||||
CreatedAt = createAt,
|
||||
UpdatedAt = createAt
|
||||
});
|
||||
}
|
||||
}
|
||||
db.PurchaseOrders.AddRange(orders);
|
||||
db.SaveChanges();
|
||||
|
||||
// ---------- 历史付款(对应部分订单) ----------
|
||||
var payOrders = orders.Where(o => o.Status == PurchaseStatus.Completed)
|
||||
.OrderBy(o => o.CreatedAt).Take(120).ToList();
|
||||
var methods = new[] { PayMethod.Wechat, PayMethod.Alipay, PayMethod.BankTransfer, PayMethod.Cash };
|
||||
var payments = payOrders.Select((o, idx) => new PaymentRecord
|
||||
{
|
||||
PayNo = $"ZF{o.CreatedAt:yyyyMMdd}-{idx + 1:D4}",
|
||||
PurchaseOrderId = o.Id,
|
||||
FarmerId = o.FarmerId,
|
||||
Amount = o.Amount,
|
||||
Method = methods[rnd.Next(methods.Length)],
|
||||
Status = PayStatus.Success,
|
||||
TradeNo = $"TRADE{rnd.Next(100000000, 999999999)}",
|
||||
OperatorId = o.OperatorId,
|
||||
PaidAt = o.WeighOutAt,
|
||||
CreatedAt = o.WeighOutAt!.Value,
|
||||
Notes = $"收购单 {o.OrderNo} 货款结算"
|
||||
}).ToList();
|
||||
db.PaymentRecords.AddRange(payments);
|
||||
db.SaveChanges();
|
||||
|
||||
// ---------- 历史发票(对应部分订单,反向开票) ----------
|
||||
var invoiceOrders = orders.Where(o => o.Status == PurchaseStatus.Completed)
|
||||
.OrderByDescending(o => o.CreatedAt).Take(80).ToList();
|
||||
var invoices = invoiceOrders.Select((o, idx) => new Invoice
|
||||
{
|
||||
InvoiceNo = $"FP{o.CreatedAt:yyyyMMdd}-{idx + 1:D4}",
|
||||
InvoiceKind = "农产品收购发票",
|
||||
FarmerId = o.FarmerId,
|
||||
PurchaserOrgId = o.PurchaserOrgId,
|
||||
PurchaseOrderId = o.Id,
|
||||
ProductId = o.ProductId,
|
||||
Quantity = o.NetWeight,
|
||||
Unit = o.Unit,
|
||||
UnitPrice = o.UnitPrice,
|
||||
Amount = o.Amount,
|
||||
TaxRate = 0m,
|
||||
TaxAmount = 0m,
|
||||
IssueDate = o.WeighOutAt ?? o.CreatedAt,
|
||||
Status = InvoiceStatus.Issued,
|
||||
OperatorId = o.OperatorId,
|
||||
CreatedAt = o.WeighOutAt ?? o.CreatedAt
|
||||
}).ToList();
|
||||
db.Invoices.AddRange(invoices);
|
||||
db.SaveChanges();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user