chore: 批量完成项目多模块迭代优化

1. 废弃半成品库存表并统一库存主表
2. 修复列表排序与搜索大小写不敏感问题
3. 新增用户最近登录时间、工单BOM名称字段
4. 完善角色管理、工位选择器功能
5. 增加拧紧数据补录、成品自动回流WMS能力
6. 统一导出时间范围校验规则
7. 丰富物料/备料单筛选条件
8. 调整菜单与权限命名适配产品型号业务
This commit is contained in:
SunYF
2026-09-08 11:44:04 +08:00
parent 06689970e2
commit e852c7cd37
96 changed files with 4528 additions and 542 deletions
+44 -14
View File
@@ -13,6 +13,18 @@ import (
"github.com/xuri/excelize/v2"
)
// itemTypeLabel 物料品类标签(与 inventories.category 对应):1原材料/2半成品/3成品
func itemTypeLabel(t int) string {
switch t {
case invCatSemi:
return "半成品"
case invCatFinished:
return "成品"
default:
return "原材料"
}
}
// createMaterialHandler 创建物料档案
func createMaterialHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -133,28 +145,32 @@ func queryMaterialsHandler(ctx *svc.ServiceContext) http.HandlerFunc {
name := r.URL.Query().Get("name")
spec := r.URL.Query().Get("spec")
manageMode := atoi(r.URL.Query().Get("manageMode"), 0)
itemType := atoi(r.URL.Query().Get("itemType"), 0)
startDate := r.URL.Query().Get("startDate")
endDate := r.URL.Query().Get("endDate")
keyword := r.URL.Query().Get("keyword") // 兼容旧版,作为物料编码/名称兜底
q := ctx.EntClient.Material.Query()
if materialCode != "" {
q = q.Where(material.CodeContains(materialCode))
q = q.Where(material.CodeContainsFold(materialCode))
}
if name != "" {
q = q.Where(material.NameContains(name))
q = q.Where(material.NameContainsFold(name))
}
if spec != "" {
q = q.Where(material.SpecContains(spec))
q = q.Where(material.SpecContainsFold(spec))
}
if manageMode != 0 {
q = q.Where(material.ManageModeEQ(manageMode))
}
if itemType != 0 {
q = q.Where(material.ItemTypeEQ(itemType))
}
if keyword != "" {
q = q.Where(
material.Or(
material.CodeContains(keyword),
material.NameContains(keyword),
material.CodeContainsFold(keyword),
material.NameContainsFold(keyword),
),
)
}
@@ -175,7 +191,7 @@ func queryMaterialsHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return
}
list, err := q.Order(ent.Desc("created_at"), ent.Desc("id")).
list, err := q.Order(ent.Asc("id")).
Offset((page - 1) * pageSize).
Limit(pageSize).
All(ctx0())
@@ -196,7 +212,7 @@ func queryMaterialsHandler(ctx *svc.ServiceContext) http.HandlerFunc {
// listMaterialsHandler 下拉框全量列表(不翻页)
func listMaterialsHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
list, err := ctx.EntClient.Material.Query().Order(ent.Desc("created_at"), ent.Desc("id")).All(ctx0())
list, err := ctx.EntClient.Material.Query().Order(ent.Desc("created_at"), ent.Desc("id")).Limit(100).All(ctx0())
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
@@ -273,23 +289,34 @@ func exportMaterialsHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
materialCode := r.URL.Query().Get("materialCode")
name := r.URL.Query().Get("name")
startDate, endDate, rerr := normalizeExportRange(r.URL.Query().Get("startDate"), r.URL.Query().Get("endDate"))
if rerr != nil {
fail(w, http.StatusBadRequest, rerr.Error())
return
}
startUnix, endUnix := exportRangeUnix(startDate, endDate)
spec := r.URL.Query().Get("spec")
manageMode := atoi(r.URL.Query().Get("manageMode"), 0)
itemType := atoi(r.URL.Query().Get("itemType"), 0)
q := ctx.EntClient.Material.Query()
q = q.Where(material.CreatedAtGTE(startUnix), material.CreatedAtLTE(endUnix))
if materialCode != "" {
q = q.Where(material.CodeContains(materialCode))
q = q.Where(material.CodeContainsFold(materialCode))
}
if name != "" {
q = q.Where(material.NameContains(name))
q = q.Where(material.NameContainsFold(name))
}
if spec != "" {
q = q.Where(material.SpecContains(spec))
q = q.Where(material.SpecContainsFold(spec))
}
if manageMode != 0 {
q = q.Where(material.ManageModeEQ(manageMode))
}
list, err := q.Order(ent.Desc("created_at"), ent.Desc("id")).All(ctx0())
if itemType != 0 {
q = q.Where(material.ItemTypeEQ(itemType))
}
list, err := q.Order(ent.Asc("id")).All(ctx0())
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
@@ -301,6 +328,7 @@ func exportMaterialsHandler(ctx *svc.ServiceContext) http.HandlerFunc {
ShortName string
Spec string
Unit string
ItemType int
ManageMode int
Description string
CreatedAt int64
@@ -309,17 +337,19 @@ func exportMaterialsHandler(ctx *svc.ServiceContext) http.HandlerFunc {
for _, m := range list {
rows = append(rows, exportRow{
Code: m.Code, Name: m.Name, ShortName: m.ShortName, Spec: m.Spec,
Unit: m.Unit, ManageMode: m.ManageMode, Description: m.Description, CreatedAt: m.CreatedAt,
Unit: m.Unit, ItemType: m.ItemType, ManageMode: m.ManageMode,
Description: m.Description, CreatedAt: m.CreatedAt,
})
}
if r.URL.Query().Get("format") == "xlsx" {
headers := []string{"物料编码", "名称", "简称", "规格", "单位", "类型", "说明", "创建时间"}
headers := []string{"物料编码", "名称", "简称", "规格", "单位", "品类", "类型", "说明", "创建时间"}
matrix := make([][]any, 0, len(rows))
for _, rr := range rows {
matrix = append(matrix, []any{
rr.Code, rr.Name, rr.ShortName, rr.Spec, rr.Unit,
manageModeLabel(rr.ManageMode), rr.Description, unixFmt(rr.CreatedAt),
itemTypeLabel(rr.ItemType), manageModeLabel(rr.ManageMode),
rr.Description, unixFmt(rr.CreatedAt),
})
}
sendExcel(w, xlsxFilename("物料档案"), headers, matrix)