-- 医疗项目首页种子数据 -- 目标:补齐首页分类栏 + 首页商品流所需的基础数据 -- 适用:public.ml_categories / public.ml_brands / public.ml_products / public.ml_shops / public.ak_users -- 说明: -- 1. 首页分类栏读取 ml_categories -- 2. 首页商品流主要读取 ml_products_detail_view(底层为 ml_products 联表) -- 3. 本脚本可重复执行,使用固定 UUID + ON CONFLICT 保持幂等 -- 4. 服务首页当前仍是本地 mock,本脚本只覆盖“商城首页”数据 BEGIN; DO $$ DECLARE v_has_role BOOLEAN := FALSE; v_has_email BOOLEAN := FALSE; v_has_username BOOLEAN := FALSE; v_has_phone BOOLEAN := FALSE; v_has_avatar_url BOOLEAN := FALSE; v_has_status BOOLEAN := FALSE; v_has_registration_source BOOLEAN := FALSE; v_has_nickname BOOLEAN := FALSE; v_has_real_name BOOLEAN := FALSE; v_has_created_at BOOLEAN := FALSE; v_has_updated_at BOOLEAN := FALSE; v_cols TEXT; v_vals TEXT; v_index INTEGER; v_merchant_ids UUID[] := ARRAY[ '5f0e7c4d-7c8a-4f6f-9a16-100000000001'::uuid, '5f0e7c4d-7c8a-4f6f-9a16-100000000002'::uuid, '5f0e7c4d-7c8a-4f6f-9a16-100000000003'::uuid, '5f0e7c4d-7c8a-4f6f-9a16-100000000004'::uuid, '5f0e7c4d-7c8a-4f6f-9a16-100000000005'::uuid, '5f0e7c4d-7c8a-4f6f-9a16-100000000006'::uuid ]; v_usernames TEXT[] := ARRAY['医疗首页商家01', '医疗首页商家02', '医疗首页商家03', '医疗首页商家04', '医疗首页商家05', '医疗首页商家06']; v_nicknames TEXT[] := ARRAY['康养精选商家', '慢病管理商家', '营养保健商家', '康复护理商家', '本草调理商家', '银龄照护商家']; v_real_names TEXT[] := ARRAY['康养医疗馆', '慢病健康馆', '营养优选馆', '康复护理馆', '本草调理馆', '银龄照护馆']; v_emails TEXT[] := ARRAY['seed.medical.home01@local.test', 'seed.medical.home02@local.test', 'seed.medical.home03@local.test', 'seed.medical.home04@local.test', 'seed.medical.home05@local.test', 'seed.medical.home06@local.test']; v_phones TEXT[] := ARRAY['13900000001', '13900000002', '13900000003', '13900000004', '13900000005', '13900000006']; BEGIN SELECT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ak_users' AND column_name = 'role' ) INTO v_has_role; SELECT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ak_users' AND column_name = 'email' ) INTO v_has_email; SELECT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ak_users' AND column_name = 'username' ) INTO v_has_username; SELECT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ak_users' AND column_name = 'phone' ) INTO v_has_phone; SELECT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ak_users' AND column_name = 'avatar_url' ) INTO v_has_avatar_url; SELECT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ak_users' AND column_name = 'status' ) INTO v_has_status; SELECT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ak_users' AND column_name = 'registration_source' ) INTO v_has_registration_source; SELECT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ak_users' AND column_name = 'nickname' ) INTO v_has_nickname; SELECT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ak_users' AND column_name = 'real_name' ) INTO v_has_real_name; SELECT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ak_users' AND column_name = 'created_at' ) INTO v_has_created_at; SELECT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ak_users' AND column_name = 'updated_at' ) INTO v_has_updated_at; FOR v_index IN 1..array_length(v_merchant_ids, 1) LOOP v_cols := 'id'; v_vals := quote_literal(v_merchant_ids[v_index]::text) || '::uuid'; IF v_has_email THEN v_cols := v_cols || ', email'; v_vals := v_vals || ', ' || quote_literal(v_emails[v_index]); END IF; IF v_has_username THEN v_cols := v_cols || ', username'; v_vals := v_vals || ', ' || quote_literal(v_usernames[v_index]); END IF; IF v_has_nickname THEN v_cols := v_cols || ', nickname'; v_vals := v_vals || ', ' || quote_literal(v_nicknames[v_index]); END IF; IF v_has_real_name THEN v_cols := v_cols || ', real_name'; v_vals := v_vals || ', ' || quote_literal(v_real_names[v_index]); END IF; IF v_has_role THEN v_cols := v_cols || ', role'; v_vals := v_vals || ', ''merchant'''; END IF; IF v_has_phone THEN v_cols := v_cols || ', phone'; v_vals := v_vals || ', ' || quote_literal(v_phones[v_index]); END IF; IF v_has_avatar_url THEN v_cols := v_cols || ', avatar_url'; v_vals := v_vals || ', ' || quote_literal('https://picsum.photos/seed/medical-merchant-avatar-' || v_index::text || '/240/240'); END IF; IF v_has_status THEN v_cols := v_cols || ', status'; v_vals := v_vals || ', ''active'''; END IF; IF v_has_registration_source THEN v_cols := v_cols || ', registration_source'; v_vals := v_vals || ', ''seed'''; END IF; IF v_has_created_at THEN v_cols := v_cols || ', created_at'; v_vals := v_vals || ', NOW()'; END IF; IF v_has_updated_at THEN v_cols := v_cols || ', updated_at'; v_vals := v_vals || ', NOW()'; END IF; EXECUTE 'INSERT INTO public.ak_users (' || v_cols || ') VALUES (' || v_vals || ') ON CONFLICT (id) DO NOTHING'; END LOOP; END $$; INSERT INTO public.ml_shops ( merchant_id, shop_name, shop_logo, description, contact_name, contact_phone, status, product_count, rating_avg, rating_count, created_at, updated_at ) VALUES ('5f0e7c4d-7c8a-4f6f-9a16-100000000001', '康养医疗精选馆', 'https://picsum.photos/seed/medical-shop-logo-01/320/320', '主打家庭常备药与家用监测器械。', '康养精选商家', '13900000001', 1, 10, 4.8, 268, NOW(), NOW()), ('5f0e7c4d-7c8a-4f6f-9a16-100000000002', '安心慢病管理馆', 'https://picsum.photos/seed/medical-shop-logo-02/320/320', '覆盖慢病监测、呼吸护理与居家健康管理。', '慢病管理商家', '13900000002', 1, 10, 4.7, 196, NOW(), NOW()), ('5f0e7c4d-7c8a-4f6f-9a16-100000000003', '益寿营养保健馆', 'https://picsum.photos/seed/medical-shop-logo-03/320/320', '面向骨骼营养、免疫支持与恢复期补充。', '营养保健商家', '13900000003', 1, 10, 4.8, 212, NOW(), NOW()), ('5f0e7c4d-7c8a-4f6f-9a16-100000000004', '术后康复护理馆', 'https://picsum.photos/seed/medical-shop-logo-04/320/320', '提供术后恢复、伤口护理和家庭康复用品。', '康复护理商家', '13900000004', 1, 10, 4.9, 184, NOW(), NOW()), ('5f0e7c4d-7c8a-4f6f-9a16-100000000005', '本草理疗调养馆', 'https://picsum.photos/seed/medical-shop-logo-05/320/320', '主打艾灸理疗、草本贴敷和中式调理商品。', '本草调理商家', '13900000005', 1, 10, 4.7, 173, NOW(), NOW()), ('5f0e7c4d-7c8a-4f6f-9a16-100000000006', '银龄居家照护馆', 'https://picsum.photos/seed/medical-shop-logo-06/320/320', '覆盖长者行动辅助和居家安全防护商品。', '银龄照护商家', '13900000006', 1, 10, 4.8, 205, NOW(), NOW()) ON CONFLICT (merchant_id) DO UPDATE SET shop_name = EXCLUDED.shop_name, shop_logo = EXCLUDED.shop_logo, description = EXCLUDED.description, contact_name = EXCLUDED.contact_name, contact_phone = EXCLUDED.contact_phone, status = EXCLUDED.status, product_count = EXCLUDED.product_count, rating_avg = EXCLUDED.rating_avg, rating_count = EXCLUDED.rating_count, updated_at = NOW(); INSERT INTO public.ml_brands (id, name, logo_url, description, website, is_active, created_at, updated_at) VALUES ('6f0e7c4d-7c8a-4f6f-9a16-200000000001', '康宁健康', 'https://picsum.photos/seed/brand-kangning/240/240', '家庭医疗器械与健康监测品牌', 'https://example.com/brands/kangning', TRUE, NOW(), NOW()), ('6f0e7c4d-7c8a-4f6f-9a16-200000000002', '益寿本草', 'https://picsum.photos/seed/brand-yishou/240/240', '中医调理与养护品牌', 'https://example.com/brands/yishou', TRUE, NOW(), NOW()), ('6f0e7c4d-7c8a-4f6f-9a16-200000000003', '安护优选', 'https://picsum.photos/seed/brand-anhu/240/240', '康复护理与长者照护品牌', 'https://example.com/brands/anhu', TRUE, NOW(), NOW()), ('6f0e7c4d-7c8a-4f6f-9a16-200000000004', '呼吸康泰', 'https://picsum.photos/seed/brand-huxi/240/240', '呼吸护理与慢病监测设备品牌', 'https://example.com/brands/huxi', TRUE, NOW(), NOW()), ('6f0e7c4d-7c8a-4f6f-9a16-200000000005', '乐龄守护', 'https://picsum.photos/seed/brand-laoling/240/240', '银龄照护与辅助出行品牌', 'https://example.com/brands/laoling', TRUE, NOW(), NOW()), ('6f0e7c4d-7c8a-4f6f-9a16-200000000006', '家庭医伴', 'https://picsum.photos/seed/brand-yiban/240/240', '家庭常备药与日用健康用品品牌', 'https://example.com/brands/yiban', TRUE, NOW(), NOW()) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, logo_url = EXCLUDED.logo_url, description = EXCLUDED.description, website = EXCLUDED.website, is_active = EXCLUDED.is_active, updated_at = NOW(); INSERT INTO public.ml_categories ( id, parent_id, name, slug, description, icon_url, banner_url, sort_order, level, path, is_active, seo_title, seo_description, created_at, updated_at ) VALUES ('7f0e7c4d-7c8a-4f6f-9a16-300000000001', NULL, '常用药品', 'medical-common-medicine', '面向家庭常备、感冒发热、肠胃不适等常见场景的药品分类', 'https://picsum.photos/seed/cat-common-med/200/200', 'https://picsum.photos/seed/cat-common-med-banner/1200/400', 10, 1, ARRAY['常用药品'], TRUE, '常用药品分类', '家庭常备药、感冒发热、肠胃常用药', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000002', NULL, '医疗器械', 'medical-devices', '覆盖血压计、血糖仪、雾化器等家庭监测设备', 'https://picsum.photos/seed/cat-devices/200/200', 'https://picsum.photos/seed/cat-devices-banner/1200/400', 20, 1, ARRAY['医疗器械'], TRUE, '医疗器械分类', '血压计、血糖仪、雾化器等家庭器械', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000003', NULL, '营养保健', 'nutrition-care', '适合免疫增强、骨关节与长者营养补充的保健类商品', 'https://picsum.photos/seed/cat-nutrition/200/200', 'https://picsum.photos/seed/cat-nutrition-banner/1200/400', 30, 1, ARRAY['营养保健'], TRUE, '营养保健分类', '蛋白粉、钙片、维生素等营养保健品', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000004', NULL, '康复护理', 'rehab-care', '适合术后恢复、慢病管理和家庭护理的康复用品', 'https://picsum.photos/seed/cat-rehab/200/200', 'https://picsum.photos/seed/cat-rehab-banner/1200/400', 40, 1, ARRAY['康复护理'], TRUE, '康复护理分类', '术后恢复、压疮护理、日常护理用品', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000005', NULL, '中医调理', 'tcm-care', '包含理疗贴、艾灸养护和中式调理产品', 'https://picsum.photos/seed/cat-tcm/200/200', 'https://picsum.photos/seed/cat-tcm-banner/1200/400', 50, 1, ARRAY['中医调理'], TRUE, '中医调理分类', '艾灸、穴位贴、草本调理产品', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000006', NULL, '老年照护', 'elder-care', '适合长者居家照护、安全防护和辅助生活的商品', 'https://picsum.photos/seed/cat-elder/200/200', 'https://picsum.photos/seed/cat-elder-banner/1200/400', 60, 1, ARRAY['老年照护'], TRUE, '老年照护分类', '轮椅、助行器、防跌用品等长者照护商品', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000101', '7f0e7c4d-7c8a-4f6f-9a16-300000000001', '感冒发热', 'cold-fever', '退热、止痛、感冒常备药', 'https://picsum.photos/seed/sub-cold-fever/200/200', NULL, 11, 2, ARRAY['常用药品','感冒发热'], TRUE, '感冒发热用药', '适用于家庭常备的感冒发热场景', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000102', '7f0e7c4d-7c8a-4f6f-9a16-300000000001', '肠胃调理', 'digestive-care', '适合肠胃不适和日常调理', 'https://picsum.photos/seed/sub-digestive/200/200', NULL, 12, 2, ARRAY['常用药品','肠胃调理'], TRUE, '肠胃调理用药', '肠胃调理及胃肠不适场景用药', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000201', '7f0e7c4d-7c8a-4f6f-9a16-300000000002', '血压监测', 'blood-pressure-monitoring', '家庭血压监测设备', 'https://picsum.photos/seed/sub-bp/200/200', NULL, 21, 2, ARRAY['医疗器械','血压监测'], TRUE, '血压监测设备', '适用于家庭与长者的血压监测设备', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000202', '7f0e7c4d-7c8a-4f6f-9a16-300000000002', '呼吸理疗', 'respiratory-care', '雾化与呼吸辅助设备', 'https://picsum.photos/seed/sub-respiratory/200/200', NULL, 22, 2, ARRAY['医疗器械','呼吸理疗'], TRUE, '呼吸理疗设备', '雾化器、制氧及呼吸辅助商品', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000301', '7f0e7c4d-7c8a-4f6f-9a16-300000000003', '骨骼营养', 'bone-nutrition', '钙、维生素 D 等骨骼关节营养商品', 'https://picsum.photos/seed/sub-bone/200/200', NULL, 31, 2, ARRAY['营养保健','骨骼营养'], TRUE, '骨骼营养补充', '适合中老年与骨骼健康场景', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000302', '7f0e7c4d-7c8a-4f6f-9a16-300000000003', '免疫支持', 'immune-support', '蛋白、维生素与免疫支持产品', 'https://picsum.photos/seed/sub-immune/200/200', NULL, 32, 2, ARRAY['营养保健','免疫支持'], TRUE, '免疫支持营养', '适合日常营养补充与免疫支持', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000401', '7f0e7c4d-7c8a-4f6f-9a16-300000000004', '术后恢复', 'post-surgery-recovery', '适用于术后恢复阶段的护理产品', 'https://picsum.photos/seed/sub-postop/200/200', NULL, 41, 2, ARRAY['康复护理','术后恢复'], TRUE, '术后恢复护理', '术后康复、恢复期护理场景', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000402', '7f0e7c4d-7c8a-4f6f-9a16-300000000004', '伤口护理', 'wound-care', '敷料、护理包和伤口辅助用品', 'https://picsum.photos/seed/sub-wound/200/200', NULL, 42, 2, ARRAY['康复护理','伤口护理'], TRUE, '伤口护理用品', '家庭和术后伤口护理场景用品', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000501', '7f0e7c4d-7c8a-4f6f-9a16-300000000005', '艾灸理疗', 'moxa-therapy', '艾灸盒、艾条和温灸护理商品', 'https://picsum.photos/seed/sub-moxa/200/200', NULL, 51, 2, ARRAY['中医调理','艾灸理疗'], TRUE, '艾灸理疗用品', '家庭艾灸、温灸理疗商品', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000502', '7f0e7c4d-7c8a-4f6f-9a16-300000000005', '草本贴敷', 'herbal-patch', '草本热敷、穴位贴与理疗贴', 'https://picsum.photos/seed/sub-herbal-patch/200/200', NULL, 52, 2, ARRAY['中医调理','草本贴敷'], TRUE, '草本贴敷用品', '肩颈腰腿舒缓与理疗贴类商品', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000601', '7f0e7c4d-7c8a-4f6f-9a16-300000000006', '行动辅助', 'mobility-aid', '轮椅、助行器和起身辅助用品', 'https://picsum.photos/seed/sub-mobility/200/200', NULL, 61, 2, ARRAY['老年照护','行动辅助'], TRUE, '行动辅助用品', '长者安全出行与行动辅助商品', NOW(), NOW()), ('7f0e7c4d-7c8a-4f6f-9a16-300000000602', '7f0e7c4d-7c8a-4f6f-9a16-300000000006', '居家防护', 'home-safety', '防滑、防跌和床旁安全辅助用品', 'https://picsum.photos/seed/sub-home-safety/200/200', NULL, 62, 2, ARRAY['老年照护','居家防护'], TRUE, '居家防护用品', '适合长者家庭安全防护场景', NOW(), NOW()) ON CONFLICT (id) DO UPDATE SET parent_id = EXCLUDED.parent_id, name = EXCLUDED.name, slug = EXCLUDED.slug, description = EXCLUDED.description, icon_url = EXCLUDED.icon_url, banner_url = EXCLUDED.banner_url, sort_order = EXCLUDED.sort_order, level = EXCLUDED.level, path = EXCLUDED.path, is_active = EXCLUDED.is_active, seo_title = EXCLUDED.seo_title, seo_description = EXCLUDED.seo_description, updated_at = NOW(); WITH seed_templates AS ( SELECT * FROM ( VALUES (1, '5f0e7c4d-7c8a-4f6f-9a16-100000000001'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000006'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000101'::uuid, '家庭退热护理贴', '家庭常备退热护理,适合儿童与成人', '常用药品', 29.90, 4.50, 0.12, ARRAY['退热护理','家庭常备','首页推荐']::text[], '8片/盒', '直接贴敷于额头或太阳穴附近', '皮肤破损处慎用', '24个月', '阴凉干燥处保存', '粤械注准20261', '夜间应急降温与陪护', '儿童发热、成人低烧与家庭药箱场景', '家庭药箱、值班陪护、夜间临时应对', '贴敷型物理护理,不占用口服用药节奏'), (2, '5f0e7c4d-7c8a-4f6f-9a16-100000000001'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000006'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000102'::uuid, '草本暖胃调理贴', '腹部热敷舒缓,适合肠胃日常调理', '常用药品', 42.00, 5.00, 0.10, ARRAY['肠胃调理','草本贴敷','居家护理']::text[], '6贴/盒', '贴于腹部不适区域,每次4至6小时', '避免高温环境使用', '24个月', '阴凉处保存', '粤械注准20262', '餐后腹部热敷与换季调理', '久坐人群、饮食不规律人群与女性日常护理', '办公室抽屉、宿舍常备、出差随身护理', '贴敷型胃腹护理,更适合连续日常使用'), (3, '5f0e7c4d-7c8a-4f6f-9a16-100000000002'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000001'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000201'::uuid, '智能血压监测仪', '语音播报与大屏显示,适合居家监测', '医疗器械', 199.00, 18.00, 0.85, ARRAY['血压监测','家用器械','老人适用']::text[], '1台/盒', '绑好袖带后按开始键测量', '测量前请静坐5分钟', '长期', '干燥处保存', '粤械注准20263', '居家晨晚双时段血压记录', '长者家庭、慢病管理用户与社区随访场景', '卧室床头、客厅药柜、社区义诊随身箱', '适合作为家庭监测主设备,强调读数稳定和易读性'), (4, '5f0e7c4d-7c8a-4f6f-9a16-100000000002'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000004'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000202'::uuid, '静音雾化护理机', '家庭呼吸理疗,适合儿童与长者', '医疗器械', 239.00, 22.00, 1.20, ARRAY['呼吸护理','静音雾化','家庭理疗']::text[], '1台/盒', '加注溶液后按说明启动', '使用后及时清洁雾化杯', '长期', '干燥处保存', '粤械注准20264', '换季敏感期与夜间呼吸护理', '儿童鼻咽不适、长者呼吸护理与家庭理疗用户', '床旁护理区、儿童房、家庭护理角', '雾化颗粒更细,适合家庭安静环境连续使用'), (5, '5f0e7c4d-7c8a-4f6f-9a16-100000000003'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000002'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000301'::uuid, '高钙维D营养片', '骨骼营养补充,适合中老年日常使用', '营养保健', 79.00, 7.00, 0.28, ARRAY['骨骼营养','维D补充','长者营养']::text[], '60片/瓶', '每日1至2片,咀嚼后吞服', '勿超过推荐量服用', '24个月', '阴凉干燥处保存', '食健备G20265', '骨骼基础营养与长期补给', '中老年、久坐办公族与骨密度关注人群', '早餐后补充、家庭常备营养角、长周期回购', '更适合做月度补给型商品,强调长期规律使用'), (6, '5f0e7c4d-7c8a-4f6f-9a16-100000000003'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000006'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000302'::uuid, '乳清蛋白营养粉', '恢复期与长者补充营养更省心', '营养保健', 168.00, 15.00, 0.90, ARRAY['免疫支持','高蛋白','恢复期']::text[], '900g/罐', '温水冲调,每次20至30g', '开封后尽快食用', '18个月', '密封避光保存', '食健备G20266', '术后恢复与日常增补蛋白', '恢复期、体质偏弱、食量不足与长者营养支持人群', '早餐代餐、术后陪护、营养加餐和睡前补给', '更适合搭配恢复期护理场景,强调蛋白摄入效率'), (7, '5f0e7c4d-7c8a-4f6f-9a16-100000000004'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000003'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000401'::uuid, '术后支撑恢复带', '弹性支撑设计,辅助日常活动恢复', '康复护理', 128.00, 12.00, 0.42, ARRAY['术后恢复','支撑护具','康复护理']::text[], '1件/盒', '按说明固定于腰腹或术后恢复部位', '过紧佩戴会影响舒适度', '长期', '干燥通风处保存', '粤械注准20267', '术后起身支撑与短程活动辅助', '腹部术后、产后恢复与腰腹支撑需求人群', '住院陪护包、居家恢复期、复查往返途中', '更适合作为恢复阶段核心护理单品,强调支撑稳定'), (8, '5f0e7c4d-7c8a-4f6f-9a16-100000000004'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000003'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000402'::uuid, '无菌伤口护理包', '含敷料与清洁耗材,家庭护理更方便', '康复护理', 58.00, 6.00, 0.22, ARRAY['伤口护理','无菌敷料','家庭护理']::text[], '1包/套', '按说明进行伤口清洁与覆盖', '严重伤口请及时就医', '24个月', '阴凉干燥处保存', '粤械注准20268', '换药清洁与创面日常防护', '轻度创面护理、术后换药与家庭备用耗材需求人群', '居家药箱、门诊复诊、旅行应急护理包', '耗材组合更完整,适合作为高频消耗型护理商品'), (9, '5f0e7c4d-7c8a-4f6f-9a16-100000000005'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000002'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000501'::uuid, '家用艾灸温灸盒', '居家温灸理疗,适合肩颈腰腿舒缓', '中医调理', 88.00, 8.00, 0.35, ARRAY['艾灸理疗','居家调理','肩颈舒缓']::text[], '1套/盒', '放入艾柱后按说明固定使用', '避免直接接触烫伤', '长期', '干燥处保存', '粤械注准20269', '肩颈腰腿温灸放松与日常养护', '久坐办公族、居家理疗人群与中式养护偏好用户', '晚间放松、周末理疗、家庭保健角', '理疗氛围感更强,适合作为中式调养类主推单品'), (10, '5f0e7c4d-7c8a-4f6f-9a16-100000000005'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000002'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000502'::uuid, '肩颈草本热敷贴', '办公居家适用,帮助肩颈腰背舒缓', '中医调理', 49.90, 5.50, 0.16, ARRAY['草本贴敷','肩颈护理','居家理疗']::text[], '10贴/盒', '直接贴于肩颈腰背部位', '睡眠时不建议长时间贴敷', '24个月', '密封避光保存', '粤械注准20270', '久坐肩颈热敷与午后舒缓', '办公久坐、伏案学习与轻度劳损舒缓人群', '办公桌抽屉、车载收纳、差旅随行护理包', '贴敷便捷,适合作为通勤和办公场景高频复购商品'), (11, '5f0e7c4d-7c8a-4f6f-9a16-100000000006'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000005'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000601'::uuid, '折叠助行辅助器', '轻便稳固,适合长者居家外出', '老年照护', 268.00, 16.00, 2.80, ARRAY['行动辅助','长者照护','安全出行']::text[], '1台/件', '展开后调节合适高度使用', '地面湿滑时请减速慢行', '长期', '干燥环境保存', '粤械注准20271', '长者短距离行走与外出辅助', '腿脚无力长者、术后康复期与家庭陪护人群', '客厅日常使用、社区散步、医院复诊外出', '更适合作为银龄照护大件主推,强调折叠与稳固兼顾'), (12, '5f0e7c4d-7c8a-4f6f-9a16-100000000006'::uuid, '6f0e7c4d-7c8a-4f6f-9a16-200000000005'::uuid, '7f0e7c4d-7c8a-4f6f-9a16-300000000602'::uuid, '浴室防滑扶手套装', '长者洗浴与走道区域安全防护', '老年照护', 139.00, 11.00, 1.15, ARRAY['居家防护','防跌安全','长者必备']::text[], '2件/套', '安装于浴室或走道墙面', '安装前确认墙面承重', '长期', '常温保存', '粤械注准20272', '洗浴区起身借力与走道安全防护', '居家长者、术后行动不稳人群与家庭照护用户', '卫生间、卧室过道、床边起身点位', '更适合作为居家改造类商品,强调安装场景和防跌价值') ) AS t(template_index, merchant_id, brand_id, category_id, product_prefix, subtitle_base, scene_name, base_price, price_step, base_weight, tags, specification, usage, precautions, expiry_date, storage_conditions, approval_prefix, care_focus, audience_focus, usage_scene, merch_focus) ), image_map AS ( SELECT * FROM ( VALUES (1, 'https://upload.wikimedia.org/wikipedia/commons/2/20/Applying_transdermal_patch.jpg'), (2, 'https://images.unsplash.com/photo-1773747608435-0fa80d11a32f?q=80&w=627&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'), (3, 'https://images.unsplash.com/photo-1631815584191-0ed1723f0ead?q=80&w=678&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'), (4, 'https://images.unsplash.com/photo-1645273474824-1facac10c30c?q=80&w=687&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'), (5, 'https://images.unsplash.com/photo-1729700985369-c04bb4557431?q=80&w=687&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'), (6, 'https://images.unsplash.com/photo-1704650311190-7eeb9c4f6e11?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'), (7, 'https://images.unsplash.com/photo-1768839725129-98df1d51e4b7?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'), (8, 'https://images.unsplash.com/photo-1765996796562-ce301df337a0?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'), (9, 'https://upload.wikimedia.org/wikipedia/commons/f/f2/Ibuki_moxa_set.jpg'), (10, 'https://upload.wikimedia.org/wikipedia/commons/1/18/Kinesio_taping_on_neck.jpg'), (11, 'https://upload.wikimedia.org/wikipedia/commons/3/3a/Medical_Walker.JPG'), (12, 'https://images.unsplash.com/photo-1656646523834-dd1cc57d33c9?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D') ) AS t(template_index, image_url) ), seed_products AS ( SELECT ('8f0e7c4d-7c8a-4f6f-9a16-' || LPAD((((template_index - 1) * 5) + seq)::text, 12, '0'))::uuid AS id, merchant_id, category_id, brand_id, format('MEDHOME-20260520-%s', LPAD((((template_index - 1) * 5) + seq)::text, 3, '0')) AS product_code, product_prefix || CASE seq WHEN 1 THEN ' 标准款' WHEN 2 THEN ' 家庭常备装' WHEN 3 THEN ' 舒适加强款' WHEN 4 THEN ' 便携随行装' ELSE ' 臻选礼盒装' END AS name, subtitle_base || CASE seq WHEN 1 THEN ',适合作为日常基础护理选择' WHEN 2 THEN ',更适合居家储备与多人使用' WHEN 3 THEN ',覆盖更集中的护理与调理需求' WHEN 4 THEN ',适合通勤、陪护或外出携带' ELSE ',兼顾体验感与送礼陈列场景' END AS subtitle, scene_name || CASE seq WHEN 1 THEN '场景常规推荐款,适合门店首页稳定陈列与日常转化。' WHEN 2 THEN '场景家庭囤货款,强调使用周期更长、备货更省心。' WHEN 3 THEN '场景强化护理款,适合症状较集中或恢复阶段的重点选择。' WHEN 4 THEN '场景轻便出行款,方便通勤、探视、陪护和短期外带。' ELSE '场景升级体验款,适合首页活动位、礼赠位或高客单展示。' END || ' 核心关注:' || care_focus || '。适用人群:' || audience_focus || '。' AS description, image_map.image_url AS main_image_url, jsonb_build_array(image_map.image_url) AS image_urls, '[]'::jsonb AS video_urls, ROUND((base_price + ( CASE seq WHEN 1 THEN 0 WHEN 2 THEN price_step * 2.2 WHEN 3 THEN price_step * 4.8 WHEN 4 THEN price_step * 1.1 ELSE price_step * 7.4 END ))::numeric, 2)::numeric(10,2) AS base_price, ROUND((base_price + ( CASE seq WHEN 1 THEN price_step * 2.8 WHEN 2 THEN price_step * 5.2 WHEN 3 THEN price_step * 8.0 WHEN 4 THEN price_step * 3.9 ELSE price_step * 11.4 END ))::numeric, 2)::numeric(10,2) AS market_price, ROUND((base_price + ( CASE seq WHEN 1 THEN 0 WHEN 2 THEN price_step * 2.2 WHEN 3 THEN price_step * 4.8 WHEN 4 THEN price_step * 1.1 ELSE price_step * 7.4 END )) * 0.58, 2)::numeric(10,2) AS cost_price, CASE seq WHEN 1 THEN 160 + (template_index * 18) WHEN 2 THEN 240 + (template_index * 24) WHEN 3 THEN 130 + (template_index * 16) WHEN 4 THEN 210 + (template_index * 20) ELSE 96 + (template_index * 12) END AS total_stock, CASE seq WHEN 1 THEN 148 + (template_index * 16) WHEN 2 THEN 222 + (template_index * 20) WHEN 3 THEN 118 + (template_index * 14) WHEN 4 THEN 192 + (template_index * 18) ELSE 84 + (template_index * 10) END AS available_stock, 1 AS min_order_qty, CASE seq WHEN 1 THEN 3 WHEN 2 THEN 6 WHEN 3 THEN 2 WHEN 4 THEN 2 ELSE 1 END AS max_order_qty, (base_weight + ( CASE seq WHEN 1 THEN 0.00 WHEN 2 THEN 0.18 WHEN 3 THEN 0.32 WHEN 4 THEN -0.05 ELSE 0.46 END ))::numeric(10,2) AS weight, jsonb_build_object( 'length', 16 + template_index + CASE seq WHEN 2 THEN 4 WHEN 3 THEN 2 WHEN 4 THEN -1 ELSE 5 END, 'width', 10 + CASE seq WHEN 2 THEN 3 WHEN 3 THEN 2 WHEN 4 THEN 0 ELSE 4 END, 'height', 4 + CASE seq WHEN 2 THEN 2 WHEN 3 THEN 1 WHEN 4 THEN 0 ELSE 3 END + (template_index / 3) ) AS dimensions, 1 AS status, CASE WHEN seq IN (1, 2) THEN TRUE ELSE FALSE END AS is_featured, CASE WHEN seq IN (2, 4, 5) THEN TRUE ELSE FALSE END AS is_new, CASE WHEN seq IN (1, 3) THEN TRUE ELSE FALSE END AS is_hot, 1200 + (template_index * 280) + (seq * 160) AS view_count, 260 + (template_index * 80) + (seq * 45) AS sale_count, 48 + (template_index * 18) + (seq * 9) AS favorite_count, LEAST(4.9, 4.5 + (template_index * 0.02) + (seq * 0.05))::numeric(3,1) AS rating_avg, 60 + (template_index * 14) + (seq * 8) AS rating_count, tags || ARRAY[ CASE seq WHEN 1 THEN '标准护理' WHEN 2 THEN '家庭常备' WHEN 3 THEN '加强调理' WHEN 4 THEN '便携随行' ELSE '臻选礼盒' END, CASE WHEN scene_name = '常用药品' THEN '家庭药箱' WHEN scene_name = '医疗器械' THEN '居家监测' WHEN scene_name = '营养保健' THEN '营养补给' WHEN scene_name = '康复护理' THEN '恢复护理' WHEN scene_name = '中医调理' THEN '理疗养护' ELSE '银龄照护' END, '医疗首页' ] AS full_tags, jsonb_build_object( 'specification', specification || CASE seq WHEN 1 THEN ',标准单元配置,适合首次购买与基础日常使用' WHEN 2 THEN ',家庭周期装,单次备货覆盖时间更长' WHEN 3 THEN ',加强护理配置,核心用量或强度做了上调' WHEN 4 THEN ',便携小规格配置,适合外出或复诊随身携带' ELSE ',礼盒陈列配置,更适合作为高客单或送礼选择' END, 'usage', usage || CASE seq WHEN 1 THEN ',适合日常基础使用频率。' WHEN 2 THEN ',建议放置于家庭常用药箱、护理柜或床旁储物区。' WHEN 3 THEN ',适合恢复期、症状较集中阶段或连续护理周期使用。' WHEN 4 THEN ',适合外出、复诊、短期陪护或车载随手包场景携带。' ELSE ',适合首页活动展示、礼赠组合或高意向用户选购。' END, 'side_effects', CASE seq WHEN 3 THEN '个别人群可能出现短时不适,建议先小量体验' WHEN 5 THEN '首次使用建议阅读说明或咨询专业人员' ELSE '一般耐受良好' END, 'precautions', precautions || CASE seq WHEN 2 THEN ',启封后建议尽快按周期用完。' WHEN 4 THEN ',随身携带时注意防潮防压。' WHEN 5 THEN ',升级配置请结合实际需求选择。' ELSE '。' END, 'expiry_date', expiry_date, 'storage_conditions', storage_conditions, 'approval_number', approval_prefix || LPAD((((template_index - 1) * 5) + seq)::text, 4, '0'), 'target_population', CASE seq WHEN 1 THEN audience_focus || ',偏基础护理与首次购买' WHEN 2 THEN audience_focus || ',偏家庭常备与多人共享' WHEN 3 THEN audience_focus || ',偏重点护理与连续使用' WHEN 4 THEN audience_focus || ',偏短期外带与移动场景' ELSE audience_focus || ',偏礼赠、升级体验与高意向消费' END, 'selling_points', jsonb_build_array( CASE seq WHEN 1 THEN '入门门槛低,适合首页常规爆款位与首次下单' WHEN 2 THEN '容量与周期更长,适合家庭储备和周期补货' WHEN 3 THEN '重点场景更聚焦,适合恢复期或强化护理转化' WHEN 4 THEN '规格更轻便,适合外带、复诊包和临时使用' ELSE '陈列感更强,适合活动位、礼赠位与高客单展示' END, '支持医疗首页分类流与推荐流展示', scene_name || '场景匹配度高', merch_focus, CASE seq WHEN 1 THEN '价格带适合作为基础转化款' WHEN 2 THEN '价格带适合作为家庭囤货款' WHEN 3 THEN '价格带适合作为强化护理款' WHEN 4 THEN '价格带适合作为便携补充款' ELSE '价格带适合作为高价值展示款' END ), 'price_band', CASE seq WHEN 1 THEN '基础入门' WHEN 2 THEN '家庭常备' WHEN 3 THEN '加强护理' WHEN 4 THEN '便携补充' ELSE '礼盒升级' END, 'stock_strategy', CASE seq WHEN 1 THEN '稳定补货' WHEN 2 THEN '高库存常备' WHEN 3 THEN '中库存重点护理' WHEN 4 THEN '中高库存便携周转' ELSE '低库存陈列展示' END, 'care_focus', care_focus, 'usage_scene', usage_scene, 'merch_focus', merch_focus ) AS attributes, LOWER(REPLACE(product_prefix, ' ', '-')) AS slug_base FROM seed_templates INNER JOIN image_map ON image_map.template_index = seed_templates.template_index CROSS JOIN generate_series(1, 5) AS seq ) INSERT INTO public.ml_products ( id, merchant_id, category_id, brand_id, product_code, name, subtitle, description, main_image_url, image_urls, video_urls, base_price, market_price, cost_price, total_stock, available_stock, min_order_qty, max_order_qty, weight, dimensions, status, is_featured, is_new, is_hot, view_count, sale_count, favorite_count, rating_avg, rating_count, seo_title, seo_description, seo_keywords, slug, tags, attributes, created_at, updated_at, published_at ) SELECT id, merchant_id, category_id, brand_id, product_code, name, subtitle, description, main_image_url, image_urls, video_urls, base_price, market_price, cost_price, total_stock, available_stock, min_order_qty, max_order_qty, weight, dimensions, status, is_featured, is_new, is_hot, view_count, sale_count, favorite_count, rating_avg, rating_count, name AS seo_title, description AS seo_description, full_tags, slug_base || '-' || RIGHT(product_code, 3), full_tags, attributes, NOW(), NOW(), NOW() FROM seed_products ON CONFLICT (id) DO UPDATE SET merchant_id = EXCLUDED.merchant_id, category_id = EXCLUDED.category_id, brand_id = EXCLUDED.brand_id, product_code = EXCLUDED.product_code, name = EXCLUDED.name, subtitle = EXCLUDED.subtitle, description = EXCLUDED.description, main_image_url = EXCLUDED.main_image_url, image_urls = EXCLUDED.image_urls, video_urls = EXCLUDED.video_urls, base_price = EXCLUDED.base_price, market_price = EXCLUDED.market_price, cost_price = EXCLUDED.cost_price, total_stock = EXCLUDED.total_stock, available_stock = EXCLUDED.available_stock, min_order_qty = EXCLUDED.min_order_qty, max_order_qty = EXCLUDED.max_order_qty, weight = EXCLUDED.weight, dimensions = EXCLUDED.dimensions, status = EXCLUDED.status, is_featured = EXCLUDED.is_featured, is_new = EXCLUDED.is_new, is_hot = EXCLUDED.is_hot, view_count = EXCLUDED.view_count, sale_count = EXCLUDED.sale_count, favorite_count = EXCLUDED.favorite_count, rating_avg = EXCLUDED.rating_avg, rating_count = EXCLUDED.rating_count, seo_title = EXCLUDED.seo_title, seo_description = EXCLUDED.seo_description, seo_keywords = EXCLUDED.seo_keywords, slug = EXCLUDED.slug, tags = EXCLUDED.tags, attributes = EXCLUDED.attributes, updated_at = NOW(), published_at = EXCLUDED.published_at; COMMIT; -- 执行完成后可运行以下校验语句: -- SELECT id, name, level, parent_id FROM public.ml_categories WHERE slug LIKE 'medical-%' OR slug IN ('cold-fever','digestive-care','blood-pressure-monitoring','respiratory-care','bone-nutrition','immune-support','post-surgery-recovery','wound-care','moxa-therapy','herbal-patch','mobility-aid','home-safety') ORDER BY sort_order; -- SELECT product_code, name, base_price, sale_count, is_featured, is_new, is_hot FROM public.ml_products WHERE product_code LIKE 'MEDHOME-%' ORDER BY product_code; -- SELECT category_name, brand_name, shop_name, merchant_name, name FROM public.ml_products_detail_view WHERE product_code LIKE 'MEDHOME-%' ORDER BY product_code;