-- Generic, extensible "archive kind" (档案模式) framework. -- Instead of a dedicated detail table per domain (food/electronics/drug/...), -- each category belongs to an archive_kind, and a metadata table (kind_field) -- describes the editable spec fields for that kind. Non-food spec values live -- in the existing product.attributes JSONB. Adding a new domain later (drug, -- machinery, ...) is just: seed kind_field rows + a category subtree. ALTER TABLE category ADD COLUMN archive_kind VARCHAR(24) NOT NULL DEFAULT 'generic'; -- The existing seeded tree is the food domain. UPDATE category SET archive_kind = 'food' WHERE path <@ 'food'; -- Field template per archive kind: drives the dynamic admin form and the -- kind-aware completeness/qualified computation. CREATE TABLE kind_field ( kind VARCHAR(24) NOT NULL, field_key VARCHAR(64) NOT NULL, group_label TEXT NOT NULL DEFAULT '', label_zh TEXT NOT NULL, field_type VARCHAR(16) NOT NULL DEFAULT 'text', unit TEXT, options TEXT[] NOT NULL DEFAULT '{}', placeholder TEXT, sort_order INT NOT NULL DEFAULT 0, qualified BOOLEAN NOT NULL DEFAULT false, PRIMARY KEY (kind, field_key), CONSTRAINT kind_field_type_chk CHECK (field_type IN ('text','number','textarea','select','list')) ); -- Seed the electronics (3C) field template. INSERT INTO kind_field (kind, field_key, group_label, label_zh, field_type, unit, sort_order, qualified) VALUES ('electronics','model_number', '基础规格','型号', 'text', NULL, 10, true), ('electronics','ccc_cert', '基础规格','3C认证号(CCC)','text', NULL, 20, true), ('electronics','color', '基础规格','颜色', 'text', NULL, 30, false), ('electronics','release_year', '基础规格','发布年份', 'number', NULL, 40, false), ('electronics','warranty_months','基础规格','保修期', 'number', '月', 50, false), ('electronics','dimensions', '外形','尺寸(长x宽x高)', 'text', 'mm', 60, false), ('electronics','weight', '外形','重量', 'number', 'g', 70, false), ('electronics','power', '外形','电源/功率', 'text', NULL, 80, false), ('electronics','os', '关键参数','操作系统', 'text', NULL, 90, false), ('electronics','cpu', '关键参数','处理器', 'text', NULL, 100, false), ('electronics','ram', '关键参数','内存', 'text', NULL, 110, false), ('electronics','storage', '关键参数','存储', 'text', NULL, 120, false), ('electronics','screen_size', '关键参数','屏幕尺寸', 'text', NULL, 130, true), ('electronics','battery', '关键参数','电池容量', 'text', NULL, 140, false), ('electronics','ports', '关键参数','接口', 'text', NULL, 150, false); -- Seed the 3C category tree. INSERT INTO category (name_zh, name_en, parent_id, path, level, archive_kind) VALUES ('电子数码', 'Electronics', NULL, 'electronics', 0, 'electronics'); INSERT INTO category (name_zh, name_en, parent_id, path, level, archive_kind) SELECT v.name_zh, v.name_en, c.id, v.path::ltree, 1, 'electronics' FROM (VALUES ('手机', 'Smartphone', 'electronics.phone'), ('笔记本电脑', 'Laptop', 'electronics.laptop'), ('平板电脑', 'Tablet', 'electronics.tablet'), ('智能手表', 'Smartwatch', 'electronics.watch'), ('耳机', 'Headphone', 'electronics.headphone'), ('相机', 'Camera', 'electronics.camera'), ('电视', 'TV', 'electronics.tv'), ('家用电器', 'Home appliance', 'electronics.appliance') ) AS v(name_zh, name_en, path) JOIN category c ON c.path = 'electronics';