Platform upgrade: login auth fix, OCR/OSS upload, system menus and dicts, weather dashboard, weighing and invoice modules

This commit is contained in:
2026-08-14 01:12:33 +08:00
parent c377421a3e
commit 8099ebae0a
75 changed files with 5611 additions and 473 deletions
@@ -0,0 +1,148 @@
using AgriculturalPlatform.Api.Data;
using AgriculturalPlatform.Api.Dtos;
using AgriculturalPlatform.Api.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace AgriculturalPlatform.Api.Controllers;
/// <summary>数据字典</summary>
[ApiController]
[Route("api/dicts")]
[Authorize]
public class DictsController(AppDbContext db) : ControllerBase
{
/// <summary>字典类型列表</summary>
[HttpGet]
public async Task<ActionResult<PagedResult<DictDto>>> List(string? keyword, [FromQuery] int page = 1, [FromQuery] int pageSize = 20)
{
var query = db.SysDicts.AsQueryable();
if (!string.IsNullOrWhiteSpace(keyword))
query = query.Where(d => d.Name.Contains(keyword) || d.Code.Contains(keyword));
var total = await query.CountAsync();
var items = await query.OrderBy(d => d.Sort).ThenByDescending(d => d.Id)
.Skip((page - 1) * pageSize).Take(pageSize)
.Select(d => new DictDto(d.Id, d.Name, d.Code, d.Remark, d.IsSystem, d.Sort,
d.Items.Count))
.ToListAsync();
return Ok(new PagedResult<DictDto>(items, total));
}
/// <summary>字典全部(含项,供下拉缓存使用)</summary>
[HttpGet("all")]
public async Task<ActionResult> All()
{
var items = await db.SysDicts.AsNoTracking()
.Include(d => d.Items.Where(i => i.Enabled))
.OrderBy(d => d.Sort)
.Select(d => new { d.Code, Items = d.Items.OrderBy(i => i.Sort)
.Select(i => new { i.Label, i.Value, i.Ext, i.IsDefault }) })
.ToListAsync();
return Ok(items);
}
/// <summary>字典详情(含字典项)</summary>
[HttpGet("{id:int}")]
public async Task<ActionResult<DictDetailDto>> Get(int id)
{
var dict = await db.SysDicts.Include(d => d.Items).FirstOrDefaultAsync(d => d.Id == id);
if (dict is null) return NotFound();
var dto = new DictDto(dict.Id, dict.Name, dict.Code, dict.Remark, dict.IsSystem, dict.Sort, dict.Items.Count);
var items = dict.Items.OrderBy(i => i.Sort)
.Select(i => new DictItemDto(i.Id, i.DictId, i.Label, i.Value, i.Ext, i.IsDefault, i.Enabled, i.Sort))
.ToList();
return Ok(new DictDetailDto(dto, items));
}
/// <summary>新增字典类型</summary>
[HttpPost]
public async Task<ActionResult<DictDto>> Create(DictSaveRequest req)
{
if (string.IsNullOrWhiteSpace(req.Code))
return BadRequest(new { message = "字典编码不能为空" });
if (await db.SysDicts.AnyAsync(d => d.Code == req.Code.Trim()))
return BadRequest(new { message = "字典编码已存在" });
var dict = new SysDict
{
Name = req.Name, Code = req.Code.Trim(), Remark = req.Remark, Sort = req.Sort, CreatedAt = DateTime.Now
};
db.SysDicts.Add(dict);
await db.SaveChangesAsync();
return Ok(new DictDto(dict.Id, dict.Name, dict.Code, dict.Remark, dict.IsSystem, dict.Sort, 0));
}
/// <summary>修改字典类型</summary>
[HttpPut("{id:int}")]
public async Task<ActionResult> Update(int id, DictSaveRequest req)
{
var dict = await db.SysDicts.FindAsync(id);
if (dict is null) return NotFound();
if (dict.Code != req.Code.Trim() && await db.SysDicts.AnyAsync(d => d.Code == req.Code.Trim()))
return BadRequest(new { message = "字典编码已存在" });
dict.Name = req.Name; dict.Code = req.Code.Trim(); dict.Remark = req.Remark; dict.Sort = req.Sort;
await db.SaveChangesAsync();
return Ok(new { message = "保存成功" });
}
/// <summary>删除字典类型(系统内置不可删除)</summary>
[HttpDelete("{id:int}")]
public async Task<IActionResult> Delete(int id)
{
var dict = await db.SysDicts.FindAsync(id);
if (dict is null) return NotFound();
if (dict.IsSystem) return BadRequest(new { message = "系统内置字典不可删除" });
db.SysDicts.Remove(dict);
await db.SaveChangesAsync();
return Ok(new { message = "删除成功" });
}
// ---------- 字典项 ----------
/// <summary>新增字典项</summary>
[HttpPost("{dictId:int}/items")]
public async Task<ActionResult<DictItemDto>> CreateItem(int dictId, DictItemSaveRequest req)
{
var dict = await db.SysDicts.FindAsync(dictId);
if (dict is null) return NotFound();
if (await db.SysDictItems.AnyAsync(i => i.DictId == dictId && i.Value == req.Value))
return BadRequest(new { message = "字典项值已存在" });
var item = new SysDictItem
{
DictId = dictId, Label = req.Label, Value = req.Value, Ext = req.Ext,
IsDefault = req.IsDefault, Enabled = req.Enabled, Sort = req.Sort
};
db.SysDictItems.Add(item);
await db.SaveChangesAsync();
return Ok(new DictItemDto(item.Id, item.DictId, item.Label, item.Value, item.Ext, item.IsDefault, item.Enabled, item.Sort));
}
/// <summary>修改字典项</summary>
[HttpPut("items/{id:int}")]
public async Task<ActionResult> UpdateItem(int id, DictItemSaveRequest req)
{
var item = await db.SysDictItems.FindAsync(id);
if (item is null) return NotFound();
item.Label = req.Label; item.Value = req.Value; item.Ext = req.Ext;
item.IsDefault = req.IsDefault; item.Enabled = req.Enabled; item.Sort = req.Sort;
await db.SaveChangesAsync();
return Ok(new { message = "保存成功" });
}
/// <summary>删除字典项</summary>
[HttpDelete("items/{id:int}")]
public async Task<IActionResult> DeleteItem(int id)
{
var item = await db.SysDictItems.FindAsync(id);
if (item is null) return NotFound();
db.SysDictItems.Remove(item);
await db.SaveChangesAsync();
return Ok(new { message = "删除成功" });
}
}