feat: 可扩展档案模式框架 + 内置 3C(电子) 模式
- 新增 category.archive_kind 与 kind_field 字段模板表(迁移 0010) - 种子 electronics 字段模板 + 3C 品类树(手机/笔记本/平板等) - 后端按档案模式动态计算完整度/合格:食品沿用 food_detail, 其它模式走 product.attributes + kind_field - 新增 GET /api/kind-fields?kind= 接口 - 后台编辑页按品类模式动态渲染规格参数表单 - 公开详情页/接口输出带标签的规格表 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -96,11 +96,12 @@ func (s *Store) CreateCategory(ctx context.Context, actor string, in CategoryInp
|
||||
|
||||
parentPath := ""
|
||||
parentLevel := -1
|
||||
kind := DefaultKind
|
||||
var parentID *string
|
||||
if pid := trimPtr(in.ParentID); pid != nil {
|
||||
var path string
|
||||
var level int
|
||||
err := s.pool.QueryRow(ctx, "SELECT path::text, level FROM category WHERE id = $1", *pid).Scan(&path, &level)
|
||||
err := s.pool.QueryRow(ctx, "SELECT path::text, level, archive_kind FROM category WHERE id = $1", *pid).Scan(&path, &level, &kind)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, ErrInvalidParent
|
||||
}
|
||||
@@ -119,11 +120,11 @@ func (s *Store) CreateCategory(ctx context.Context, actor string, in CategoryInp
|
||||
|
||||
var c Category
|
||||
err := s.pool.QueryRow(ctx, `
|
||||
INSERT INTO category (name_zh, name_en, parent_id, path, gpc_brick_code, level)
|
||||
VALUES ($1, $2, $3, $4::ltree, $5, $6)
|
||||
RETURNING id, name_zh, name_en, path::text, level, parent_id::text, gpc_brick_code, 0`,
|
||||
name, trimPtr(in.NameEN), parentID, path, trimPtr(in.GPCBrickCode), level).
|
||||
Scan(&c.ID, &c.NameZH, &c.NameEN, &c.Path, &c.Level, &c.ParentID, &c.GPCBrickCode, &c.ProductCount)
|
||||
INSERT INTO category (name_zh, name_en, parent_id, path, gpc_brick_code, level, archive_kind)
|
||||
VALUES ($1, $2, $3, $4::ltree, $5, $6, $7)
|
||||
RETURNING id, name_zh, name_en, path::text, level, parent_id::text, gpc_brick_code, archive_kind, 0`,
|
||||
name, trimPtr(in.NameEN), parentID, path, trimPtr(in.GPCBrickCode), level, kind).
|
||||
Scan(&c.ID, &c.NameZH, &c.NameEN, &c.Path, &c.Level, &c.ParentID, &c.GPCBrickCode, &c.ArchiveKind, &c.ProductCount)
|
||||
if isUniqueViolation(err) {
|
||||
return nil, ErrDuplicatePath
|
||||
}
|
||||
@@ -273,10 +274,10 @@ func (s *Store) getCategory(ctx context.Context, id string) (*Category, error) {
|
||||
var c Category
|
||||
err := s.pool.QueryRow(ctx, `
|
||||
SELECT c.id, c.name_zh, c.name_en, c.path::text, c.level, c.parent_id::text,
|
||||
c.gpc_brick_code,
|
||||
c.gpc_brick_code, c.archive_kind,
|
||||
(SELECT count(*) FROM product p WHERE p.category_id = c.id)
|
||||
FROM category c WHERE c.id = $1`, id).
|
||||
Scan(&c.ID, &c.NameZH, &c.NameEN, &c.Path, &c.Level, &c.ParentID, &c.GPCBrickCode, &c.ProductCount)
|
||||
Scan(&c.ID, &c.NameZH, &c.NameEN, &c.Path, &c.Level, &c.ParentID, &c.GPCBrickCode, &c.ArchiveKind, &c.ProductCount)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user