feat(web+api): 贡献表单按 archive_kind 动态生成字段 #32

Merged
lixu merged 1 commits from devin/1782295354-contribution-form-dynamic into main 2026-06-24 18:07:05 +08:00
Owner

Summary

贡献商品档案表单此前写死食品营养字段,与现有多品类(食品/药品/3C/通用)不匹配。本 PR 让表单按所选品类的 archive_kind 动态渲染对应字段,并打通后端落库。除「商品名称」外全部字段改为选填,支持只提供少量信息提交。

后端

  • ListCategories 返回每个品类的 archive_kind(COALESCE(archive_kind,'generic'))。
  • 新增公开只读接口 GET /api/v1/kind-fields?kind=X(限流),返回 kind_field 字段模板(label/类型/单位/选项/排序/qualified),供前端驱动表单。
  • SubmissionInput 新增通用 attributes map[string]any,与既有 nutriments 并存(完全向后兼容)。
  • ApproveSubmissionattributes 写入 product.attributes JSONB:新建用 COALESCE($n::jsonb,'{}'),更新用 attributes = product.attributes || COALESCE($n::jsonb,'{}') 合并,不覆盖既有键。
  • food_detail 改为条件 upsert——仅当投稿含食品数据(nutriments/配料/营养基准/份量/nutri_score 任一)时才写入,药品/3C/通用不再产生空 food_detail 行。

前端 (Contribute.tsx)

  • 选定品类后由其 archive_kind 推导 kind;非食品/通用时拉取 kindFields(kind)
  • field_type 渲染:select(下拉+选项)、textarealist(按换行/逗号/顿号拆成数组)、number(parseFloat)、text;按 group_label 分组;qualified 字段标 *
  • food 显示营养区(走 nutriments);其余 kind 收集为 attributes
选品类 → kind=archive_kind
  food        → 营养区(nutriments)         → food_detail
  drug        → kind-fields 18 字段(attributes) → product.attributes
  electronics → kind-fields 字段(attributes)    → product.attributes
  generic     → 仅基础信息

验证

本地 ephemeral Postgres 跑全部迁移(33 个 kind_field / 37 个品类),起 server+admin 实测:

  • GET /api/v1/categories 返回 archive_kind;/api/v1/kind-fields?kind=drug 返回 18 字段(含 select 选项),electronics 返回 15 字段。
  • 投稿药品 attributes → 审核通过 → product.attributes 正确写入,且产生 food_detail 行。
  • 投稿食品 nutriments → 审核通过 → food_detail 正确写入,product.attributes 为空(向后兼容)。
  • go build ./... && go vet ./... 通过;前端 npm run build(tsc+vite)通过。
## Summary 贡献商品档案表单此前写死食品营养字段,与现有多品类(食品/药品/3C/通用)不匹配。本 PR 让表单按所选品类的 `archive_kind` 动态渲染对应字段,并打通后端落库。除「商品名称」外全部字段改为选填,支持只提供少量信息提交。 **后端** - `ListCategories` 返回每个品类的 `archive_kind`(`COALESCE(archive_kind,'generic')`)。 - 新增公开只读接口 `GET /api/v1/kind-fields?kind=X`(限流),返回 `kind_field` 字段模板(label/类型/单位/选项/排序/qualified),供前端驱动表单。 - `SubmissionInput` 新增通用 `attributes map[string]any`,与既有 `nutriments` 并存(完全向后兼容)。 - `ApproveSubmission` 把 `attributes` 写入 `product.attributes` JSONB:新建用 `COALESCE($n::jsonb,'{}')`,更新用 `attributes = product.attributes || COALESCE($n::jsonb,'{}')` 合并,不覆盖既有键。 - `food_detail` 改为**条件 upsert**——仅当投稿含食品数据(nutriments/配料/营养基准/份量/nutri_score 任一)时才写入,药品/3C/通用不再产生空 food_detail 行。 **前端 (`Contribute.tsx`)** - 选定品类后由其 `archive_kind` 推导 kind;非食品/通用时拉取 `kindFields(kind)`。 - 按 `field_type` 渲染:`select`(下拉+选项)、`textarea`、`list`(按换行/逗号/顿号拆成数组)、`number`(parseFloat)、`text`;按 `group_label` 分组;`qualified` 字段标 `*`。 - 仅 `food` 显示营养区(走 `nutriments`);其余 kind 收集为 `attributes`。 ```text 选品类 → kind=archive_kind food → 营养区(nutriments) → food_detail drug → kind-fields 18 字段(attributes) → product.attributes electronics → kind-fields 字段(attributes) → product.attributes generic → 仅基础信息 ``` ## 验证 本地 ephemeral Postgres 跑全部迁移(33 个 `kind_field` / 37 个品类),起 server+admin 实测: - `GET /api/v1/categories` 返回 archive_kind;`/api/v1/kind-fields?kind=drug` 返回 18 字段(含 select 选项),`electronics` 返回 15 字段。 - 投稿药品 attributes → 审核通过 → `product.attributes` 正确写入,且**未**产生 food_detail 行。 - 投稿食品 nutriments → 审核通过 → `food_detail` 正确写入,`product.attributes` 为空(向后兼容)。 - `go build ./... && go vet ./...` 通过;前端 `npm run build`(tsc+vite)通过。
lixu added 1 commit 2026-06-24 18:04:41 +08:00
feat(web+api): 贡献表单按 archive_kind 动态生成字段
CI / Go (api) (pull_request) Successful in 1m3s
CI / Python (ingestion) (pull_request) Successful in 23s
CI / Migrations (postgres) (pull_request) Successful in 26s
bd1d3bde7c
- categories 接口返回 archive_kind
- 新增公开只读接口 /api/v1/kind-fields?kind=X 返回字段模板
- 投稿 payload 支持通用 attributes,审核通过写入 product.attributes (JSONB 合并)
- food_detail 仅在含食品数据时才 upsert (药品/3C/通用不再产生空行)
- 前端 Contribute 按所选品类 archive_kind 动态渲染字段
  (食品营养 / 药品 18 字段 / 3C / 通用),除商品名外均选填

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
lixu merged commit 3aec0b84fe into main 2026-06-24 18:07:05 +08:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: lixu/goods#32