从AI肌肤测试到色号精准匹配,从热销榜单到消费占比饼图,从肌肤档案到会员体系——本文以一套完整的ArkTS美妆护肤精选商城应用为例,深度解析HarmonyOS API 24在美妆电商场景下的多组件分离架构、肌肤类型测试问卷、色号选择器、消费占比可视化、肌肤数据追踪等核心技术实现。

一、引言

美妆护肤是电商领域中复购率最高、用户粘性最强的品类之一。与3C数码等标品不同,美妆消费高度依赖"肤质匹配"和"色号选择"——同样一款粉底液,干性肌肤和油性肌肤的使用效果天差地别;同一支口红,不同色号适合不同肤色和场合。传统美妆电商往往只提供商品列表和搜索,缺乏肤质诊断和色号辅助决策能力。

本应用(美妆护肤精选商城)以"粉紫渐变浅色"为视觉基调,打造集首页推荐、面部护肤、彩妆香水、美妆订单、个人中心五大模块于一体的美妆电商全链路平台。20款美妆产品覆盖护肤/彩妆/香水三大品类,8笔订单覆盖待付款/待发货/待收货/已完成四种状态,7天肌肤记录追踪水分/油分/平滑度/综合评分,5张优惠券覆盖不同品类和门槛,5种肌肤类型(干性/油性/混合/敏感/中性)。

本文将从架构设计、色彩系统、数据模型、五大Tab页面、弹框体系、核心技术特性等维度,完整解析这套应用的ArkTS实现。

二、整体架构

本应用采用多组件分离架构——@Entry @Component struct BeautyMallApp作为入口容器,通过@State activeTab控制五大Tab切换,每个Tab页面都是独立的@Component子组件(BeautyHomeContent/SkincareContent/MakeupContent/BeautyOrderContent/BeautyProfileContent),各自管理自己的状态和弹框。

架构层次:

  • 入口层:BeautyMallApp,负责Tab切换和底部导航
  • 页面层:5个独立@Component子组件,每个组件有自己的@State状态和弹框Builder
  • 数据层:5个全局const数组(20美妆产品+8订单+7肌肤记录+5优惠券+5肌肤类型)+3个常量数组(护肤分类/彩妆分类/订单状态)
  • 弹框层:每个页面组件内部定义自己的弹框,总计15+种弹框(肌肤测试问卷、领券中心、商品详情、删除确认、编辑添加、色号选择器、订单详情、编辑订单、删除订单、编辑资料、肌肤档案记录、注销账号等)

多组件架构的优势在于:每个页面状态隔离、代码模块化、便于团队协作开发。底部导航通过bottomTabItem Builder统一渲染,选中态有粉红#E91E63文字+底部指示条。

三、色彩系统:粉紫渐变浅色主题

美妆护肤的视觉语言应该是"柔美、精致、女性化、高级感"。本应用采用粉紫渐变浅色主题:

主色体系:

  • #E91E63 粉红:主色调,用于Tab选中态、价格、按钮、标签、会员标识——代表柔美与活力
  • #9C27B0 紫色:用于彩妆品牌色、彩妆分类标签、收藏统计——代表神秘与高级
  • #FF9800 橙色:用于星级评分、优惠券统计、油分指标——代表温暖与品质
  • #4CAF50 绿色:用于订单状态、肌肤评分、平滑度指标——代表健康与成功
  • #03A9F4 蓝色:用于水分指标、敏感肌肤类型——代表清爽与纯净
  • #F44336 红色:用于删除按钮、注销确认——代表危险操作

浅色背景层次:

  • #FFF5F8 浅粉:应用根背景
  • #FFFFFF 纯白:卡片背景、页面头部、弹框背景
  • #FCE4EC 极浅粉:按钮背景、头像背景、标签背景
  • #F3E5F5 极浅紫:彩妆分类标签背景
  • #F5F5F5 浅灰:取消按钮背景
  • #F0F0F0 灰:分割线、进度条背景
  • #E8F5E9 浅绿:订单状态标签背景

文字色:

  • #333333 深灰:主标题、商品名
  • #666666 中灰:订单号、日期
  • #999999 浅灰:辅助文字、未选中Tab、说明文字
  • #BBBBBB 极浅灰:输入框占位符

浅色主题通过浅粉#FFF5F8根背景+纯白卡片+极浅粉/紫按钮背景营造柔美空间感,粉红#E91E63作为唯一主高亮色贯穿全应用,紫色#9C27B0作为彩妆辅助色,确保视觉一致性和品类区分度。

四、数据模型

应用定义了5个接口,覆盖美妆电商全链路:

  • BeautyProduct美妆产品(id/name/brand/price/originalPrice/sales/emoji/tag/rating/shade/category)——20款产品,含护肤/彩妆/香水,shade字段存储色号(十六进制颜色值或"通用")
  • BeautyOrder订单(id/orderNo/productName/amount/status/date/emoji)——8笔订单
  • SkinRecord肌肤记录(id/date/moisture/oil/smoothness/score)——7天肌肤数据,含水分/油分/平滑度/综合评分四项指标
  • BeautyCoupon优惠券(id/value/threshold/scope/expire)——5张优惠券
  • SkinTypeOption肌肤类型(label/desc/color)——5种肌肤类型,含描述和专属颜色

shade字段是美妆产品的特色设计——护肤产品为"通用",彩妆产品存储十六进制颜色值(如#DC143C正红、#FF69B4粉红),在色号选择器中直接渲染为圆形色块,用户一眼看到颜色效果。

五、Tab0 首页推荐

首页是美妆商城的"门面",由四个层次构成:

1. 顶部Banner:💕美妆护肤精选标题+🔍搜索按钮(触发肌肤测试弹框)+🎫领券按钮。

2. 三宫格功能入口:🔬AI肌肤测试(智能推荐护肤方案)+🎫领券中心(满300减50)+📊肤质档案(查看肌肤变化),三列等宽排列。

3. 热销榜单:🏆热销榜单标题+更多入口+8款热销产品排行,每款含排名数字(前3名粉红#E91E63,其他灰色#CCCCCC)+50×50产品图标块+产品名+品牌+⭐评分+价格+已售数量。点击产品弹出商品详情弹框。

4. 今日推荐:✨今日推荐标题+2款推荐产品双列卡片,每卡含emoji图标+产品名(maxLines 1)+价格,浅粉背景#FFF5F8。

首页通过热销榜单营造"大家都在买"的社交氛围,通过AI肌肤测试入口引导用户进行肤质诊断,通过领券中心刺激消费转化。

六、Tab1 面部护肤

护肤页采用分类筛选+横卡列表布局,由三个层次构成:

1. 顶部标题栏:💧面部护肤+右侧+新增按钮(粉红圆形,触发新增护肤产品弹框)。

2. 分类筛选横滑:7个护肤分类chip(全部/洁面/爽肤水/精华/面霜/面膜/防晒),选中态粉红背景白字,未选中粉红文字浅粉背景,横滑滚动。

3. 护肤产品横卡列表:20款护肤产品横卡排列,每卡含64×64浅粉图标块+产品名(maxLines 2)+品牌(粉红文字)+⭐评分+已售+价格行(粉红价格+灰色划线原价+右侧标签)。点击卡片弹出商品详情弹框。

护肤页的编辑弹框支持功效分类选择(保湿/美白/抗老/祛痘)和适用肤质选择(所有肤质/干性/油性),这是美妆电商的特色功能——用户可以按肤质筛选适合自己的护肤产品。新增弹框支持产品名称/品牌/价格/分类输入。

七、Tab2 彩妆香水

彩妆页的核心特色是瀑布双列+色号选择器,由三个层次构成:

1. 顶部标题栏:💄彩妆香水+右侧🎨色号按钮(触发色号选择器弹框)。

2. 彩妆分类横滑:7个彩妆分类chip(全部/口红/粉底/眼影/腮红/香水/卸妆),紫色文字#9C27B0+浅紫背景#F3E5F5,横滑滚动。

3. 彩妆产品瀑布双列:20款彩妆产品按双列网格排列,每卡含64高图标区(顶部圆角,浅粉背景)+产品名(maxLines 1)+品牌(紫色文字#9C27B0)+价格行(粉红价格+灰色划线原价)+标签行(粉红标签+⭐评分)。点击卡片弹出商品详情弹框。

色号选择器弹框是彩妆页的亮点:展示6个色号圆形色块(#DC143C正红/#FF0000大红/#8B0000暗红/#FF69B4粉红/#FFC0CB浅粉/#800020酒红),每个色块下方有色号名称(#1966/#400/#16/高潮/浅粉/酒红),用户点击选择后确认。这解决了美妆电商中"线上选色难"的痛点——用户可以直观看到色号颜色,而不是只看文字描述。

彩妆详情弹框的按钮布局也与护肤页不同——选色号(粉红浅底)+编辑(紫色底)+删除(红色底),突出彩妆的色号选择功能。

八、Tab3 美妆订单

订单页的核心特色是状态Tab+消费占比饼图,由四个层次构成:

1. 顶部标题栏:📋美妆订单+共8单统计。

2. 状态Tab:5个状态选项(全部/待付款/待发货/待收货/已完成),选中态粉红加粗,固定在标题下方。

3. 消费分类占比饼图:💰消费分类占比标题+4个圆形色块模拟饼图(护肤45%粉红大圆80px/彩妆30%紫色中圆60px/香水15%橙色小圆45px/其他10%绿色最小圆35px),每个圆下方有分类名和百分比。通过不同大小的圆形模拟饼图占比,视觉直观。

4. 订单列表:8笔订单横卡,每卡含52×52浅粉图标块+商品名(maxLines 1)+订单号+价格行(粉红金额+日期+右侧状态标签绿色底)。点击卡片弹出订单详情弹框。

订单详情弹框展示订单号/商品/金额/状态/日期五项信息,底部有编辑和删除按钮。编辑订单弹框支持收件人/电话/地址/备注修改。

九、Tab4 个人中心

个人中心的核心特色是肌肤档案+会员体系,由五个层次构成:

1. 会员信息卡:60×60圆形头像(浅粉背景#FCE4EC)+昵称"美妆小达人"+手机号+钻石会员标签(粉红底)+积分8650+美妆豆320+右侧✏️编辑按钮。

2. 数据统计条:四格统计(8全部订单粉红/15收藏产品紫色/5优惠券橙色/85肌肤评分绿色),每格含数字+标签。

3. 肌肤档案入口:📊图标+我的肌肤档案标题+查看近7天肌肤数据变化+查看>入口,点击弹出肌肤档案记录弹框。

4. 肌肤档案记录弹框:展示近7天肌肤数据,每天含日期+综合评分(粉红加粗)+水分进度条(蓝色#03A9F4百分比)+油分进度条(橙色#FF9800百分比)+平滑度进度条(绿色#4CAF50百分比),三项指标用不同颜色区分,用户直观看到肌肤状态变化。

5. 设置列表:9个设置项(收货地址管理/我的优惠券/我的钱包/我的收藏/浏览历史/消息通知/主题设置/联系客服/退出登录),每项含图标+标签+右侧>箭头,纯白卡片背景圆角12。退出登录触发注销账号确认弹框(红色警示)。

肌肤档案是美妆电商个人中心的差异化功能——用户可以追踪自己的肌肤数据变化,结合护肤产品使用记录,形成"肤质-产品-效果"的闭环,提升用户粘性。

十、弹框体系

本应用弹框数量多达15+种,按页面分布:

首页5种:skinTestModal肌肤类型测试(分步问卷样式,5种肌肤类型选项,每项含标签+描述+右侧颜色条,选中显示✅,底部查看推荐方案按钮)、couponModal领券中心(5张优惠券卡片堆叠样式,含金额/门槛/范围/有效期+领取按钮)、detailModal商品详情(大卡片样式,120高图标区+商品名+价格行+评分/已售/色号+编辑/删除/加入购物车三按钮)、deleteModal删除确认(💔图标+确认移出购物车+取消/确认移出双按钮)、addModal编辑商品信息(商品名称/价格/色号规格/库存数量stepper输入+取消/保存修改双按钮)。

护肤页4种:detailModal商品详情(小号居中,编辑/删除/购买三按钮)、editModal编辑护肤产品(产品名称/价格/功效分类选择/适用肤质选择)、deleteModal删除确认、addModal新增护肤产品(名称/品牌/价格/分类输入)。

彩妆页4种:shadeModal色号选择器(6个色号圆形色块+色号名称+确认选择按钮)、detailModal商品详情(选色号/编辑/删除三按钮)、editModal编辑彩妆信息(名称/品牌/色号/价格输入)、deleteModal删除确认。

订单页3种:orderDetailModal订单详情(订单号/商品/金额/状态/日期+编辑/删除按钮)、editModal编辑订单(收件人/电话/地址/备注输入)、deleteModal删除订单(⚠️图标+确认删除+删除后不可恢复+取消/确认删除双按钮)。

我的页3种:editModal编辑个人资料(昵称/手机号/邮箱/肌肤类型选择)、skinRecordModal肌肤档案记录(近7天肌肤数据+水分/油分/平滑度三色进度条)、deleteModal注销账号(⚠️图标+确认注销+所有美妆档案将永久删除+取消/确认注销双按钮)。

所有弹框均采用统一的modalOverlay半透明遮罩(rgba(0,0,0,0.4))+居中卡片形态,zIndex 999确保在最上层。

十一、核心技术特性

1. 多组件分离架构:5个独立@Component子组件,每个组件管理自己的状态和弹框,入口组件只负责Tab切换,代码模块化程度高。

2. 肌肤类型测试问卷:首页skinTestModal采用分步问卷样式,5种肌肤类型(干性/油性/混合/敏感/中性)每项含标签+描述+右侧专属颜色条,选中显示✅,用户选择后查看推荐方案。这是美妆电商的差异化功能——通过简单问卷帮助用户判断自己的肤质类型。

3. 色号选择器:彩妆页shadeModal展示6个色号圆形色块,每个色块直接渲染为十六进制颜色值(#DC143C/#FF0000/#8B0000/#FF69B4/#FFC0CB/#800020),用户直观看到色号颜色,解决"线上选色难"痛点。

4. 消费占比可视化:订单页通过4个不同大小的圆形色块(80px/60px/45px/35px)模拟饼图占比(护肤45%/彩妆30%/香水15%/其他10%),无需复杂图表组件,视觉直观。

5. 肌肤数据追踪:个人中心skinRecordModal展示近7天肌肤数据,每天含水分(蓝色#03A9F4)/油分(橙色#FF9800)/平滑度(绿色#4CAF50)三色进度条+综合评分,三项指标用不同颜色区分,用户直观看到肌肤状态变化趋势。

6. 产品shade字段设计:BeautyProduct接口的shade字段存储十六进制颜色值(如#DC143C)或"通用",在色号选择器中直接渲染为圆形色块,在商品详情中显示色号信息,数据驱动UI。

7. 粉紫双主色品类区分:护肤品类用粉红#E91E63,彩妆品类用紫色#9C27B0,通过颜色区分两大品类,用户一眼识别当前浏览的品类。

8. 统一弹框遮罩:所有弹框共用modalOverlay Builder(rgba(0,0,0,0.4)半透明+点击关闭),zIndex 999,确保弹框在最上层且交互一致。

9. 状态隔离:每个页面组件的@State状态独立,弹框显隐互不干扰,避免单组件架构中状态过多导致的维护困难。

10. 底部导航指示条:选中Tab除了粉红文字加粗外,底部还有18×3粉红圆角指示条,视觉反馈明确。

十二、同类对比

维度通用美妆电商App本应用(美妆护肤精选商城)
主题浅色/粉色为主粉紫渐变浅色+双主色品类区分
架构单组件5个独立@Component多组件分离
肤质诊断无或简单AI肌肤测试问卷+5种肤质类型
色号选择文字描述十六进制颜色值渲染圆形色块
消费分析无或简单列表圆形色块模拟饼图占比可视化
肌肤追踪近7天水分/油分/平滑度三色进度条
弹框数量5-8种15+种覆盖全流程
品类区分统一颜色护肤粉红/彩妆紫色双主色

十三、完整代码结构总览

1174.ets
├── 数据结构(5个interface)
├── 静态配置(SKIN_TYPES 5种肌肤类型 + 3个常量数组)
├── 静态数据(5个数组:20美妆产品+8订单+7肌肤记录+5优惠券)
├── BeautyTab枚举(5个Tab)
├── BeautyMallApp入口组件(@Entry @Component)
│   ├── contentArea() Tab内容分发
│   ├── bottomTabItem() 底部导航项
│   └── build() 入口布局
├── BeautyHomeContent首页组件(5种弹框+hotRankItem+热销榜单+今日推荐)
├── SkincareContent护肤组件(4种弹框+skincareCard+分类筛选+横卡列表)
├── MakeupContent彩妆组件(4种弹框+makeupCard+色号选择器+瀑布双列)
├── BeautyOrderContent订单组件(3种弹框+orderItemBuilder+状态Tab+消费占比饼图)
└── BeautyProfileContent我的组件(3种弹框+settingItem+会员信息+肌肤档案+设置列表)

十四、开发环境搭建

14.1 环境要求

DevEco Studio 5.0+(支持ArkTS API 24)、HarmonyOS SDK API 24、Node.js 18+、至少8GB内存。

14.2 安装DevEco Studio

从华为开发者官网下载最新版本,运行安装包,选择安装路径,勾选创建桌面快捷方式,点击安装。

14.3 配置SDK

首次启动后进入File > Settings > HarmonyOS SDK,勾选API 24及以上版本,点击Apply等待下载完成。

14.4 创建项目

选择Create Project > Empty Ability,配置项目名称、包名、保存路径,选择Compile SDK为API 24,点击Finish。

14.5 运行应用

将1174.ets代码替换到entry/src/main/ets/pages/Index.ets,连接HarmonyOS设备或启动模拟器,点击运行按钮预览。

14.6 预览调试

DevEco Studio提供实时预览功能,编辑器右侧打开Previewer面板,支持多设备尺寸预览、深色模式切换、组件树inspect等调试能力。

附录:完整源码

// ============ 1174.ets 美妆护肤精选商城(拼多多风格) ============
// 场景:美妆护肤 / 彩妆香水 / 肌肤管理 · 粉紫渐变浅色主题
// 布局差异:首页Banner+榜单 / 护肤卡片列表+筛选 / 彩妆瀑布双列+色号 / 订单列表+饼图 / 肌肤档案个人中心

// ============ 类型定义 ============
interface BeautyProduct {
  id: number
  name: string
  brand: string
  price: number
  originalPrice: number
  sales: number
  emoji: string
  tag: string
  rating: number
  shade: string
  category: string
}

interface BeautyOrder {
  id: number
  orderNo: string
  productName: string
  amount: number
  status: string
  date: string
  emoji: string
}

interface SkinRecord {
  id: number
  date: string
  moisture: number
  oil: number
  smoothness: number
  score: number
}

interface BeautyCoupon {
  id: number
  value: number
  threshold: number
  scope: string
  expire: string
}

interface SkinTypeOption {
  label: string
  desc: string
  color: string
}

// ============ 静态配置 ============
const SKIN_TYPES: SkinTypeOption[] = [
  { label: '干性肌肤', desc: '需要深度滋润补水', color: '#E91E63' },
  { label: '油性肌肤', desc: '需要控油清爽型', color: '#FF9800' },
  { label: '混合肌肤', desc: 'T区油两颊偏干', color: '#9C27B0' },
  { label: '敏感肌肤', desc: '需要温和无刺激', color: '#03A9F4' },
  { label: '中性肌肤', desc: '水油平衡状态佳', color: '#4CAF50' }
]

const SKINCARE_CATS: string[] = ['全部', '洁面', '爽肤水', '精华', '面霜', '面膜', '防晒']
const MAKEUP_CATS: string[] = ['全部', '口红', '粉底', '眼影', '腮红', '香水', '卸妆']
const ORDER_STATUS: string[] = ['全部', '待付款', '待发货', '待收货', '已完成']

// ============ 美妆产品数据 ============
const mockBeautyProducts: BeautyProduct[] = [
  { id: 1, name: '兰蔻小黑瓶精华肌底液50ml', brand: '兰蔻', price: 1280, originalPrice: 1580, sales: 32456, emoji: '💧', tag: '畅销爆款', rating: 4.9, shade: '通用', category: '精华' },
  { id: 2, name: '雅诗兰黛沁水粉底液30ml', brand: '雅诗兰黛', price: 520, originalPrice: 650, sales: 21345, emoji: '💄', tag: '百亿补贴', rating: 4.8, shade: '#F5DEB3', category: '粉底' },
  { id: 3, name: 'SK-II神仙水护肤精华230ml', brand: 'SK-II', price: 1590, originalPrice: 1990, sales: 18567, emoji: '✨', tag: '限时秒杀', rating: 4.9, shade: '通用', category: '爽肤水' },
  { id: 4, name: '海蓝之谜经典面霜60ml', brand: '海蓝之谜', price: 2680, originalPrice: 2980, sales: 9876, emoji: '🌟', tag: '新品首发', rating: 5.0, shade: '通用', category: '面霜' },
  { id: 5, name: 'YSL小金条口红#1966', brand: 'YSL', price: 380, originalPrice: 420, sales: 45678, emoji: '💋', tag: '热卖色号', rating: 4.8, shade: '#DC143C', category: '口红' },
  { id: 6, name: '阿玛尼红管唇釉#400', brand: '阿玛尼', price: 320, originalPrice: 360, sales: 38923, emoji: '💋', tag: '经典正红', rating: 4.7, shade: '#FF0000', category: '口红' },
  { id: 7, name: '资生堂红腰子精华50ml', brand: '资生堂', price: 780, originalPrice: 980, sales: 25634, emoji: '🌸', tag: '百亿补贴', rating: 4.8, shade: '通用', category: '精华' },
  { id: 8, name: '雪花秀滋阴生人参面霜', brand: '雪花秀', price: 890, originalPrice: 1100, sales: 12345, emoji: '🌿', tag: '韩方护肤', rating: 4.6, shade: '通用', category: '面霜' },
  { id: 9, name: 'NARS高潮腮红', brand: 'NARS', price: 290, originalPrice: 350, sales: 34567, emoji: '🌹', tag: '热门色号', rating: 4.7, shade: '#FF69B4', category: '腮红' },
  { id: 10, name: '香奈儿五号香水50ml', brand: '香奈儿', price: 980, originalPrice: 1150, sales: 15432, emoji: '🧴', tag: '经典香氛', rating: 4.9, shade: '通用', category: '香水' },
  { id: 11, name: '兰蔻菁纯洁面乳125ml', brand: '兰蔻', price: 380, originalPrice: 450, sales: 22345, emoji: '🧴', tag: '温和洁面', rating: 4.6, shade: '通用', category: '洁面' },
  { id: 12, name: '佑天兰黄金果冻面膜', brand: '佑天兰', price: 128, originalPrice: 198, sales: 41234, emoji: '🎭', tag: '限时秒杀', rating: 4.5, shade: '通用', category: '面膜' },
  { id: 13, name: '安耐晒金瓶防晒60ml', brand: '安耐晒', price: 228, originalPrice: 288, sales: 56789, emoji: '☀️', tag: '防晒必备', rating: 4.8, shade: '通用', category: '防晒' },
  { id: 14, name: '纪梵希高定香榭散粉', brand: '纪梵希', price: 520, originalPrice: 620, sales: 18234, emoji: '✨', tag: '百亿补贴', rating: 4.7, shade: '通用', category: '粉底' },
  { id: 15, name: 'TF黑管唇釉#16', brand: 'Tom Ford', price: 480, originalPrice: 560, sales: 28923, emoji: '💋', tag: '热卖色号', rating: 4.9, shade: '#8B0000', category: '口红' },
  { id: 16, name: '美宝莲眼影盘12色', brand: '美宝莲', price: 159, originalPrice: 219, sales: 33456, emoji: '🎨', tag: '新手友好', rating: 4.5, shade: '通用', category: '眼影' },
  { id: 17, name: '欧莱雅紫熨斗眼霜', brand: '欧莱雅', price: 269, originalPrice: 329, sales: 29876, emoji: '👁️', tag: '新品首发', rating: 4.6, shade: '通用', category: '精华' },
  { id: 18, name: '城野医生收敛水100ml', brand: '城野医生', price: 199, originalPrice: 259, sales: 25678, emoji: '🌿', tag: '毛孔护理', rating: 4.5, shade: '通用', category: '爽肤水' },
  { id: 19, name: '娇兰帝皇蜂姿黑蜂蜜面霜', brand: '娇兰', price: 1980, originalPrice: 2280, sales: 8765, emoji: '🍯', tag: '高端抗老', rating: 4.9, shade: '通用', category: '面霜' },
  { id: 20, name: '贝德玛粉蓝舒缓卸妆水', brand: '贝德玛', price: 168, originalPrice: 228, sales: 45678, emoji: '💧', tag: '限时秒杀', rating: 4.7, shade: '通用', category: '卸妆' }
]

// ============ 美妆订单数据 ============
const mockBeautyOrders: BeautyOrder[] = [
  { id: 1, orderNo: 'PDD20260825001', productName: '兰蔻小黑瓶精华肌底液50ml', amount: 1280, status: '待收货', date: '2026-08-22', emoji: '💧' },
  { id: 2, orderNo: 'PDD20260824002', productName: 'YSL小金条口红#1966', amount: 380, status: '已完成', date: '2026-08-20', emoji: '💋' },
  { id: 3, orderNo: 'PDD20260823003', productName: '安耐晒金瓶防晒60ml', amount: 228, status: '待发货', date: '2026-08-23', emoji: '☀️' },
  { id: 4, orderNo: 'PDD20260822004', productName: 'SK-II神仙水230ml', amount: 1590, status: '待付款', date: '2026-08-24', emoji: '✨' },
  { id: 5, orderNo: 'PDD20260821005', productName: 'NARS高潮腮红', amount: 290, status: '已完成', date: '2026-08-18', emoji: '🌹' },
  { id: 6, orderNo: 'PDD20260820006', productName: '海蓝之谜经典面霜60ml', amount: 2680, status: '待收货', date: '2026-08-21', emoji: '🌟' },
  { id: 7, orderNo: 'PDD20260819007', productName: '香奈儿五号香水50ml', amount: 980, status: '已完成', date: '2026-08-15', emoji: '🧴' },
  { id: 8, orderNo: 'PDD20260818008', productName: '贝德玛舒缓卸妆水', amount: 168, status: '待发货', date: '2026-08-22', emoji: '💧' }
]

// ============ 肌肤记录数据 ============
const mockSkinRecords: SkinRecord[] = [
  { id: 1, date: '08月25日', moisture: 68, oil: 35, smoothness: 82, score: 85 },
  { id: 2, date: '08月24日', moisture: 65, oil: 40, smoothness: 78, score: 80 },
  { id: 3, date: '08月23日', moisture: 72, oil: 30, smoothness: 85, score: 88 },
  { id: 4, date: '08月22日', moisture: 60, oil: 45, smoothness: 75, score: 76 },
  { id: 5, date: '08月21日', moisture: 70, oil: 32, smoothness: 80, score: 83 },
  { id: 6, date: '08月20日', moisture: 58, oil: 50, smoothness: 70, score: 72 },
  { id: 7, date: '08月19日', moisture: 75, oil: 28, smoothness: 88, score: 90 }
]

// ============ 优惠券数据 ============
const mockBeautyCoupons: BeautyCoupon[] = [
  { id: 1, value: 50, threshold: 300, scope: '美妆全场', expire: '2026-08-31' },
  { id: 2, value: 200, threshold: 1000, scope: '高端护肤', expire: '2026-09-15' },
  { id: 3, value: 30, threshold: 200, scope: '彩妆专区', expire: '2026-08-28' },
  { id: 4, value: 100, threshold: 500, scope: '香水专区', expire: '2026-09-10' },
  { id: 5, value: 20, threshold: 100, scope: '面膜专区', expire: '2026-08-30' }
]

// ============ 底部 Tab 枚举 ============
enum BeautyTab {
  HOME = 0,
  SKINCARE = 1,
  MAKEUP = 2,
  ORDER = 3,
  PROFILE = 4
}

// ============ 入口页面 ============
@Entry
@Component
struct BeautyMallApp {
  @State activeTab: BeautyTab = BeautyTab.HOME

  @Builder contentArea() {
    Column() {
      if (this.activeTab === BeautyTab.HOME) {
        BeautyHomeContent()
      } else if (this.activeTab === BeautyTab.SKINCARE) {
        SkincareContent()
      } else if (this.activeTab === BeautyTab.MAKEUP) {
        MakeupContent()
      } else if (this.activeTab === BeautyTab.ORDER) {
        BeautyOrderContent()
      } else {
        BeautyProfileContent()
      }
    }
    .layoutWeight(1)
  }

  @Builder bottomTabItem(icon: string, label: string, tab: BeautyTab) {
    Column() {
      Text(icon).fontSize(20).opacity(this.activeTab === tab ? 1.0 : 0.45)
      Text(label).fontSize(9)
        .fontColor(this.activeTab === tab ? '#E91E63' : '#999999')
        .fontWeight(this.activeTab === tab ? FontWeight.Bold : FontWeight.Normal)
        .margin({ top: 1 })
      if (this.activeTab === tab) {
        Column().width(18).height(3)
          .backgroundColor('#E91E63').borderRadius(2).margin({ top: 2 })
      }
    }
    .layoutWeight(1)
    .alignItems(HorizontalAlign.Center)
    .padding({ top: 5, bottom: 5 })
    .onClick(() => { this.activeTab = tab })
  }

  build() {
    Column() {
      this.contentArea()
      Row() {
        this.bottomTabItem('🏠', '首页', BeautyTab.HOME)
        this.bottomTabItem('💧', '护肤', BeautyTab.SKINCARE)
        this.bottomTabItem('💄', '彩妆', BeautyTab.MAKEUP)
        this.bottomTabItem('📋', '订单', BeautyTab.ORDER)
        this.bottomTabItem('👤', '我的', BeautyTab.PROFILE)
      }
      .width('100%')
      .backgroundColor('#FFFFFF')
      .padding({ top: 4, bottom: 6 })
      .shadow({ radius: 8, color: '#1AF06292', offsetY: -2 })
    }
    .width('100%').height('100%')
    .backgroundColor('#FFF5F8')
  }
}

// ============ 首页推荐 ============
@Component
struct BeautyHomeContent {
  @State showSkinTestModal: boolean = false
  @State showCouponModal: boolean = false
  @State showDetailModal: boolean = false
  @State showDeleteModal: boolean = false
  @State showAddModal: boolean = false
  @State selectedProduct: BeautyProduct | null = null
  @State selectedSkinType: string = ''

  @Builder modalOverlay(onClose?: () => void) {
    Column()
      .width('100%').height('100%')
      .backgroundColor('rgba(0,0,0,0.4)')
      .onClick(() => { if (onClose) { onClose() } })
  }

  // ========== 弹框1:肌肤测试(分步问卷样式) ==========
  @Builder skinTestModal() {
    Column() {
      this.modalOverlay(() => { this.showSkinTestModal = false })
      Column() {
        Text('🔍 肌肤类型测试').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#E91E63')
          .padding({ top: 22, bottom: 4 })
        Text('选择最符合你肌肤状态的描述').fontSize(11).fontColor('#999999').padding({ bottom: 14 })
        Scroll() {
          Column() {
            ForEach(SKIN_TYPES, (s: SkinTypeOption) => {
              Row() {
                Column() {
                  Row() {
                    Text(s.label).fontSize(14).fontColor('#333333').fontWeight(FontWeight.Medium)
                    Column().layoutWeight(1)
                    if (this.selectedSkinType === s.label) {
                      Text('✅').fontSize(16)
                    } else {
                      Text('○').fontSize(16).fontColor('#CCCCCC')
                    }
                  }
                  .width('100%')
                  Text(s.desc).fontSize(11).fontColor('#999999').margin({ top: 4 })
                }
                .layoutWeight(1).alignItems(HorizontalAlign.Start)
                Column() {
                  Column().width(4).height(40).backgroundColor(s.color).borderRadius(2)
                }
              }
              .width('100%').backgroundColor('#FFF5F8')
              .borderRadius(10).padding({ left: 14, right: 14, top: 12, bottom: 12 })
              .margin({ left: 16, right: 16, top: 6 })
              .onClick(() => { this.selectedSkinType = s.label })
            })
          }
        }
        .layoutWeight(1).constraintSize({ maxHeight: '45%' })
        Text('查看推荐方案').fontSize(14).fontColor('#FFFFFF')
          .backgroundColor('#E91E63').borderRadius(22)
          .padding({ left: 36, right: 36, top: 12, bottom: 12 })
          .margin({ top: 14, bottom: 22 })
          .onClick(() => { this.showSkinTestModal = false })
      }
      .width('88%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  // ========== 弹框2:领券(卡片堆叠样式) ==========
  @Builder couponModal() {
    Column() {
      this.modalOverlay(() => { this.showCouponModal = false })
      Column() {
        Text('🎫 美妆优惠券').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#E91E63')
          .padding({ top: 22, bottom: 4 })
        Text('精选美妆好券 · 限时领取').fontSize(11).fontColor('#999999').padding({ bottom: 14 })
        Scroll() {
          Column() {
            ForEach(mockBeautyCoupons, (c: BeautyCoupon) => {
              Row() {
                Column() {
                  Text('¥' + c.value).fontSize(26).fontWeight(FontWeight.Bold).fontColor('#E91E63')
                  Text('满' + c.threshold + '可用').fontSize(10).fontColor('#999999')
                }.width(100).alignItems(HorizontalAlign.Center)
                Column() {
                  Text(c.scope).fontSize(13).fontColor('#333333').fontWeight(FontWeight.Medium)
                  Text('有效期至 ' + c.expire).fontSize(10).fontColor('#999999').margin({ top: 2 })
                }.layoutWeight(1).alignItems(HorizontalAlign.Start)
                Text('领取').fontSize(12).fontColor('#FFFFFF')
                  .backgroundColor('#E91E63').borderRadius(14)
                  .padding({ left: 14, right: 14, top: 6, bottom: 6 })
                  .onClick(() => { this.showCouponModal = false })
              }
              .width('100%').backgroundColor('#FFF5F8')
              .borderRadius(12).padding({ top: 14, bottom: 14, left: 14, right: 14 })
              .margin({ left: 16, right: 16, top: 6 })
            })
          }
        }
        .layoutWeight(1).constraintSize({ maxHeight: '45%' })
        Text('✕').fontSize(16).fontColor('#999999')
          .margin({ top: 12, bottom: 18 })
          .onClick(() => { this.showCouponModal = false })
      }
      .width('88%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  // ========== 弹框3:商品详情(大卡片样式) ==========
  @Builder detailModal() {
    Column() {
      this.modalOverlay(() => { this.showDetailModal = false })
      Column() {
        Column() {
          Text(this.selectedProduct?.emoji ?? '💄').fontSize(56)
        }.width('100%').height(120).justifyContent(FlexAlign.Center)
        .backgroundColor('#FFF5F8').borderRadius({ topLeft: 16, topRight: 16 })
        Text(this.selectedProduct?.name ?? '').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#333333')
          .padding({ left: 20, right: 20, top: 14 })
        Row() {
          Text('¥' + (this.selectedProduct?.price ?? 0)).fontSize(26).fontWeight(FontWeight.Bold).fontColor('#E91E63')
          Text('¥' + (this.selectedProduct?.originalPrice ?? 0)).fontSize(13).fontColor('#999999')
            .decoration({ type: TextDecorationType.LineThrough }).margin({ left: 8, top: 6 })
          Text(this.selectedProduct?.tag ?? '').fontSize(10).fontColor('#FFFFFF')
            .backgroundColor('#E91E63').borderRadius(4)
            .padding({ left: 6, right: 6, top: 2, bottom: 2 }).margin({ left: 8, top: 5 })
        }
        .width('100%').padding({ left: 20, top: 6 })
        Row() {
          Text('⭐' + (this.selectedProduct?.rating ?? 0)).fontSize(12).fontColor('#FF9800')
          Text('已售' + (this.selectedProduct?.sales ?? 0)).fontSize(11).fontColor('#999999').margin({ left: 12 })
          Text('色号:' + (this.selectedProduct?.shade ?? '')).fontSize(11).fontColor('#999999').margin({ left: 12 })
        }
        .width('100%').padding({ left: 20, top: 6 })
        Row() {
          Text('编辑').fontSize(13).fontColor('#E91E63')
            .backgroundColor('#FCE4EC').borderRadius(20)
            .padding({ left: 22, right: 22, top: 10, bottom: 10 })
            .onClick(() => { this.showDetailModal = false; this.showAddModal = true })
          Text('删除').fontSize(13).fontColor('#FFFFFF')
            .backgroundColor('#F44336').borderRadius(20)
            .padding({ left: 22, right: 22, top: 10, bottom: 10 }).margin({ left: 10 })
            .onClick(() => { this.showDetailModal = false; this.showDeleteModal = true })
          Text('加入购物车').fontSize(13).fontColor('#FFFFFF')
            .backgroundColor('#E91E63').borderRadius(20)
            .padding({ left: 22, right: 22, top: 10, bottom: 10 }).margin({ left: 10 })
            .onClick(() => { this.showDetailModal = false })
        }
        .width('100%').justifyContent(FlexAlign.Center)
        .padding({ top: 16, bottom: 20 })
      }
      .width('90%').backgroundColor('#FFFFFF').borderRadius(16)
      .alignItems(HorizontalAlign.Center)
      .position({ x: '5%', y: '6%' })
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
  }

  // ========== 弹框4:删除确认 ==========
  @Builder deleteModal() {
    Column() {
      this.modalOverlay(() => { this.showDeleteModal = false })
      Column() {
        Text('💔').fontSize(40).margin({ top: 4 })
        Text('确认移出购物车?').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#333333')
        Text('移出后可重新添加').fontSize(12).fontColor('#F44336').margin({ top: 4 })
        Row() {
          Text('取消').fontSize(14).fontColor('#999999')
            .backgroundColor('#F5F5F5').borderRadius(20)
            .padding({ left: 28, right: 28, top: 10, bottom: 10 })
            .onClick(() => { this.showDeleteModal = false })
          Text('确认移出').fontSize(14).fontColor('#FFFFFF')
            .backgroundColor('#F44336').borderRadius(20)
            .padding({ left: 28, right: 28, top: 10, bottom: 10 }).margin({ left: 12 })
            .onClick(() => { this.showDeleteModal = false })
        }
        .padding({ top: 20, bottom: 22 })
      }
      .width('78%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  // ========== 弹框5:编辑/添加 ==========
  @Builder addModal() {
    Column() {
      this.modalOverlay(() => { this.showAddModal = false })
      Column() {
        Text('✏️ 编辑商品信息').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
          .padding({ top: 22, bottom: 10 })
        Divider().color('#F0F0F0')
        Text('商品名称').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: this.selectedProduct?.name ?? '' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('价格').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: '¥' + (this.selectedProduct?.price ?? 0) })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('色号/规格').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: this.selectedProduct?.shade ?? '通用' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('库存数量').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        Row() {
          Text('−').fontSize(18).fontColor('#E91E63').width(36).height(36).textAlign(TextAlign.Center)
            .backgroundColor('#FFF5F8').borderRadius(8)
          Text('100').fontSize(14).fontColor('#333333').width(50).height(36).textAlign(TextAlign.Center)
            .backgroundColor('#FFF5F8').borderRadius(8).margin({ left: 8 })
          Text('+').fontSize(18).fontColor('#E91E63').width(36).height(36).textAlign(TextAlign.Center)
            .backgroundColor('#FFF5F8').borderRadius(8).margin({ left: 8 })
        }
        .margin({ top: 4 })
        Row() {
          Text('取消').fontSize(14).fontColor('#999999')
            .backgroundColor('#F5F5F5').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 })
            .onClick(() => { this.showAddModal = false })
          Text('保存修改').fontSize(14).fontColor('#FFFFFF')
            .backgroundColor('#E91E63').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 }).margin({ left: 12 })
            .onClick(() => { this.showAddModal = false })
        }
        .padding({ top: 18, bottom: 22 })
      }
      .width('88%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder hotRankItem(rank: number, p: BeautyProduct) {
    Row() {
      Text(rank.toString()).fontSize(20).fontWeight(FontWeight.Bold)
        .fontColor(rank <= 3 ? '#E91E63' : '#CCCCCC').width(30).textAlign(TextAlign.Center)
      Column() {
        Text(p.emoji).fontSize(24)
      }.width(50).height(50).backgroundColor('#FFF5F8').borderRadius(8)
      .justifyContent(FlexAlign.Center)
      Column() {
        Text(p.name).fontSize(12).fontColor('#333333').fontWeight(FontWeight.Medium).maxLines(1)
        Text(p.brand + ' · ⭐' + p.rating).fontSize(10).fontColor('#999999').margin({ top: 2 })
        Row() {
          Text('¥' + p.price).fontSize(14).fontColor('#E91E63').fontWeight(FontWeight.Bold)
          Text('已售' + p.sales).fontSize(9).fontColor('#999999').margin({ left: 8 })
        }
        .margin({ top: 2 })
      }.layoutWeight(1).alignItems(HorizontalAlign.Start).padding({ left: 10 })
    }
    .width('100%').backgroundColor('#FFFFFF').borderRadius(10)
    .padding({ left: 12, right: 12, top: 8, bottom: 8 })
    .margin({ left: 12, right: 12, top: 4 })
    .onClick(() => { this.selectedProduct = p; this.showDetailModal = true })
  }

  build() {
    Stack() {
      Column() {
        // 顶部Banner
        Row() {
          Text('💕').fontSize(16)
          Text('美妆护肤精选').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#E91E63').margin({ left: 4 })
          Column().layoutWeight(1)
          Text('🔍').fontSize(16).margin({ right: 10 }).onClick(() => { this.showSkinTestModal = true })
          Text('🎫').fontSize(16).margin({ right: 12 }).onClick(() => { this.showCouponModal = true })
        }
        .width('100%').padding({ top: 14, bottom: 10 })
        .backgroundColor('#FFFFFF')

        Scroll() {
          Column() {
            // 肌肤测试入口
            Row() {
              Column() {
                Text('🔬').fontSize(28)
                Text('AI肌肤测试').fontSize(14).fontColor('#E91E63').fontWeight(FontWeight.Bold).margin({ top: 4 })
                Text('智能推荐护肤方案').fontSize(10).fontColor('#999999').margin({ top: 2 })
              }.layoutWeight(1).alignItems(HorizontalAlign.Center)
              Column() {
                Text('🎫').fontSize(28)
                Text('领券中心').fontSize(14).fontColor('#E91E63').fontWeight(FontWeight.Bold).margin({ top: 4 })
                Text('满300减50').fontSize(10).fontColor('#999999').margin({ top: 2 })
              }.layoutWeight(1).alignItems(HorizontalAlign.Center)
              Column() {
                Text('📊').fontSize(28)
                Text('肤质档案').fontSize(14).fontColor('#E91E63').fontWeight(FontWeight.Bold).margin({ top: 4 })
                Text('查看肌肤变化').fontSize(10).fontColor('#999999').margin({ top: 2 })
              }.layoutWeight(1).alignItems(HorizontalAlign.Center)
            }
            .width('100%').padding({ top: 16, bottom: 16 })
            .backgroundColor('#FFFFFF').margin({ top: 6 })

            // 热销榜单
            Column() {
              Row() {
                Text('🏆 热销榜单').fontSize(15).fontWeight(FontWeight.Bold).fontColor('#333333')
                Column().layoutWeight(1)
                Text('更多 >').fontSize(11).fontColor('#999999')
              }
              .width('100%').padding({ left: 16, top: 14, bottom: 8 })
              this.hotRankItem(1, mockBeautyProducts[4])
              this.hotRankItem(2, mockBeautyProducts[0])
              this.hotRankItem(3, mockBeautyProducts[5])
              this.hotRankItem(4, mockBeautyProducts[2])
              this.hotRankItem(5, mockBeautyProducts[3])
              this.hotRankItem(6, mockBeautyProducts[8])
              this.hotRankItem(7, mockBeautyProducts[12])
              this.hotRankItem(8, mockBeautyProducts[9])
            }
            .width('100%').backgroundColor('#FFFFFF').margin({ top: 6, bottom: 6 })

            // 今日推荐
            Column() {
              Text('✨ 今日推荐').fontSize(15).fontWeight(FontWeight.Bold).fontColor('#333333')
                .width('100%').padding({ left: 16, top: 14, bottom: 8 })
              Row() {
                Column() {
                  Text(mockBeautyProducts[6].emoji).fontSize(36)
                  Text(mockBeautyProducts[6].name).fontSize(10).fontColor('#333333').maxLines(1)
                  Text('¥' + mockBeautyProducts[6].price).fontSize(13).fontColor('#E91E63').fontWeight(FontWeight.Bold)
                }.layoutWeight(1).backgroundColor('#FFF5F8').borderRadius(10).padding({ top: 10, bottom: 10 })
                .margin({ left: 6, right: 3 }).alignItems(HorizontalAlign.Center)
                .onClick(() => { this.selectedProduct = mockBeautyProducts[6]; this.showDetailModal = true })
                Column() {
                  Text(mockBeautyProducts[10].emoji).fontSize(36)
                  Text(mockBeautyProducts[10].name).fontSize(10).fontColor('#333333').maxLines(1)
                  Text('¥' + mockBeautyProducts[10].price).fontSize(13).fontColor('#E91E63').fontWeight(FontWeight.Bold)
                }.layoutWeight(1).backgroundColor('#FFF5F8').borderRadius(10).padding({ top: 10, bottom: 10 })
                .margin({ left: 3, right: 6 }).alignItems(HorizontalAlign.Center)
                .onClick(() => { this.selectedProduct = mockBeautyProducts[10]; this.showDetailModal = true })
              }
              .width('100%').padding({ bottom: 14 })
            }
            .width('100%').backgroundColor('#FFFFFF')
          }
          .padding({ bottom: 20 })
        }
        .layoutWeight(1).scrollBar(BarState.Off)
      }
      .width('100%').height('100%')

      if (this.showSkinTestModal) { this.skinTestModal() }
      if (this.showCouponModal) { this.couponModal() }
      if (this.showDetailModal) { this.detailModal() }
      if (this.showDeleteModal) { this.deleteModal() }
      if (this.showAddModal) { this.addModal() }
    }
    .width('100%').height('100%')
  }
}

// ============ 面部护肤页(分类筛选+列表) ============
@Component
struct SkincareContent {
  @State selectedCat: string = '全部'
  @State showDetailModal: boolean = false
  @State showEditModal: boolean = false
  @State showDeleteModal: boolean = false
  @State showAddModal: boolean = false
  @State selectedProduct: BeautyProduct | null = null

  @Builder modalOverlay(onClose?: () => void) {
    Column()
      .width('100%').height('100%')
      .backgroundColor('rgba(0,0,0,0.4)')
      .onClick(() => { if (onClose) { onClose() } })
  }

  @Builder detailModal() {
    Column() {
      this.modalOverlay(() => { this.showDetailModal = false })
      Column() {
        Text(this.selectedProduct?.emoji ?? '💧').fontSize(48).margin({ top: 20 })
        Text(this.selectedProduct?.name ?? '').fontSize(15).fontColor('#333333').fontWeight(FontWeight.Bold)
          .padding({ left: 16, right: 16, top: 10 })
        Text('¥' + (this.selectedProduct?.price ?? 0)).fontSize(22).fontColor('#E91E63').fontWeight(FontWeight.Bold)
        Row() {
          Text('编辑').fontSize(13).fontColor('#E91E63')
            .backgroundColor('#FCE4EC').borderRadius(18)
            .padding({ left: 22, right: 22, top: 10, bottom: 10 })
            .onClick(() => { this.showDetailModal = false; this.showEditModal = true })
          Text('删除').fontSize(13).fontColor('#FFFFFF')
            .backgroundColor('#F44336').borderRadius(18)
            .padding({ left: 22, right: 22, top: 10, bottom: 10 }).margin({ left: 10 })
            .onClick(() => { this.showDetailModal = false; this.showDeleteModal = true })
          Text('购买').fontSize(13).fontColor('#FFFFFF')
            .backgroundColor('#E91E63').borderRadius(18)
            .padding({ left: 22, right: 22, top: 10, bottom: 10 }).margin({ left: 10 })
            .onClick(() => { this.showDetailModal = false })
        }
        .padding({ top: 14, bottom: 20 })
      }
      .width('75%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder editModal() {
    Column() {
      this.modalOverlay(() => { this.showEditModal = false })
      Column() {
        Text('✏️ 编辑护肤产品').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
          .padding({ top: 22, bottom: 10 })
        Divider().color('#F0F0F0')
        Text('产品名称').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: this.selectedProduct?.name ?? '' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('价格').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: '¥' + (this.selectedProduct?.price ?? 0) })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('功效分类').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        Row() {
          Text('保湿').fontSize(11).fontColor('#FFFFFF').backgroundColor('#E91E63').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
          Text('美白').fontSize(11).fontColor('#E91E63').backgroundColor('#FCE4EC').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
          Text('抗老').fontSize(11).fontColor('#E91E63').backgroundColor('#FCE4EC').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
          Text('祛痘').fontSize(11).fontColor('#E91E63').backgroundColor('#FCE4EC').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
        }
        .padding({ left: 16, top: 6 })
        Text('适用肤质').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        Row() {
          Text('所有肤质').fontSize(11).fontColor('#FFFFFF').backgroundColor('#E91E63').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
          Text('干性').fontSize(11).fontColor('#E91E63').backgroundColor('#FCE4EC').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
          Text('油性').fontSize(11).fontColor('#E91E63').backgroundColor('#FCE4EC').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
        }
        .padding({ left: 16, top: 6 })
        Row() {
          Text('取消').fontSize(14).fontColor('#999999')
            .backgroundColor('#F5F5F5').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 })
            .onClick(() => { this.showEditModal = false })
          Text('保存').fontSize(14).fontColor('#FFFFFF')
            .backgroundColor('#E91E63').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 }).margin({ left: 12 })
            .onClick(() => { this.showEditModal = false })
        }
        .padding({ top: 18, bottom: 22 })
      }
      .width('88%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder deleteModal() {
    Column() {
      this.modalOverlay(() => { this.showDeleteModal = false })
      Column() {
        Text('🗑️').fontSize(36).margin({ top: 20 })
        Text('确认删除此产品?').fontSize(15).fontColor('#333333').fontWeight(FontWeight.Bold).margin({ top: 6 })
        Row() {
          Text('取消').fontSize(13).fontColor('#999999')
            .backgroundColor('#F5F5F5').borderRadius(16)
            .padding({ left: 24, right: 24, top: 8, bottom: 8 })
            .onClick(() => { this.showDeleteModal = false })
          Text('删除').fontSize(13).fontColor('#FFFFFF')
            .backgroundColor('#F44336').borderRadius(16)
            .padding({ left: 24, right: 24, top: 8, bottom: 8 }).margin({ left: 10 })
            .onClick(() => { this.showDeleteModal = false })
        }
        .padding({ top: 14, bottom: 18 })
      }
      .width('72%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder addModal() {
    Column() {
      this.modalOverlay(() => { this.showAddModal = false })
      Column() {
        Text('➕ 新增护肤产品').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
          .padding({ top: 22, bottom: 10 })
        Divider().color('#F0F0F0')
        Text('产品名称').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: '输入产品名称...' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('品牌').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: '如:兰蔻、雅诗兰黛...' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('价格').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: '¥ 0.00' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('分类').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        Row() {
          Text('洁面').fontSize(11).fontColor('#E91E63').backgroundColor('#FCE4EC').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
          Text('精华').fontSize(11).fontColor('#FFFFFF').backgroundColor('#E91E63').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
          Text('面霜').fontSize(11).fontColor('#E91E63').backgroundColor('#FCE4EC').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
          Text('面膜').fontSize(11).fontColor('#E91E63').backgroundColor('#FCE4EC').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
        }
        .padding({ left: 16, top: 6 })
        Row() {
          Text('取消').fontSize(14).fontColor('#999999')
            .backgroundColor('#F5F5F5').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 })
            .onClick(() => { this.showAddModal = false })
          Text('添加').fontSize(14).fontColor('#FFFFFF')
            .backgroundColor('#E91E63').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 }).margin({ left: 12 })
            .onClick(() => { this.showAddModal = false })
        }
        .padding({ top: 18, bottom: 22 })
      }
      .width('88%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder skincareCard(p: BeautyProduct) {
    Row() {
      Column() {
        Text(p.emoji).fontSize(32)
      }.width(64).height(64).backgroundColor('#FFF5F8').borderRadius(10)
      .justifyContent(FlexAlign.Center)
      Column() {
        Text(p.name).fontSize(13).fontColor('#333333').fontWeight(FontWeight.Medium).maxLines(2)
        Row() {
          Text(p.brand).fontSize(10).fontColor('#E91E63')
          Text('⭐' + p.rating).fontSize(10).fontColor('#FF9800').margin({ left: 6 })
          Text('已售' + p.sales).fontSize(9).fontColor('#999999').margin({ left: 6 })
        }
        .margin({ top: 4 })
        Row() {
          Text('¥' + p.price).fontSize(16).fontColor('#E91E63').fontWeight(FontWeight.Bold)
          Text('¥' + p.originalPrice).fontSize(10).fontColor('#999999')
            .decoration({ type: TextDecorationType.LineThrough }).margin({ left: 4, top: 4 })
          Column().layoutWeight(1)
          Text(p.tag).fontSize(9).fontColor('#FFFFFF').backgroundColor('#E91E63')
            .borderRadius(4).padding({ left: 4, right: 4, top: 1, bottom: 1 })
        }
        .margin({ top: 4 })
      }.layoutWeight(1).alignItems(HorizontalAlign.Start).padding({ left: 10 })
    }
    .width('100%').backgroundColor('#FFFFFF').borderRadius(12)
    .padding({ left: 12, right: 12, top: 10, bottom: 10 })
    .margin({ left: 12, right: 12, top: 5 })
    .onClick(() => { this.selectedProduct = p; this.showDetailModal = true })
  }

  build() {
    Stack() {
      Column() {
        Row() {
          Text('💧 面部护肤').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
          Column().layoutWeight(1)
          Text('+').fontSize(20).fontColor('#FFFFFF')
            .backgroundColor('#E91E63').width(28).height(28).borderRadius(14).textAlign(TextAlign.Center)
            .margin({ right: 14 })
            .onClick(() => { this.showAddModal = true })
        }
        .width('100%').padding({ top: 14, bottom: 10 })
        .backgroundColor('#FFFFFF')

        Scroll() {
          Row() {
            ForEach(SKINCARE_CATS, (c: string) => {
              if (this.selectedCat === c) {
                Text(c).fontSize(11).fontColor('#FFFFFF').backgroundColor('#E91E63')
                  .borderRadius(14).padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4, right: 4 })
              } else {
                Text(c).fontSize(11).fontColor('#E91E63').backgroundColor('#FCE4EC')
                  .borderRadius(14).padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4, right: 4 })
                  .onClick(() => { this.selectedCat = c })
              }
            })
          }
          .padding({ left: 8, right: 8 })
        }
        .scrollable(ScrollDirection.Horizontal).scrollBar(BarState.Off).height(36)
        .backgroundColor('#FFFFFF')

        Scroll() {
          Column() {
            this.skincareCard(mockBeautyProducts[0])
            this.skincareCard(mockBeautyProducts[2])
            this.skincareCard(mockBeautyProducts[6])
            this.skincareCard(mockBeautyProducts[3])
            this.skincareCard(mockBeautyProducts[7])
            this.skincareCard(mockBeautyProducts[10])
            this.skincareCard(mockBeautyProducts[16])
            this.skincareCard(mockBeautyProducts[18])
            this.skincareCard(mockBeautyProducts[17])
            this.skincareCard(mockBeautyProducts[11])
            this.skincareCard(mockBeautyProducts[12])
            this.skincareCard(mockBeautyProducts[13])
            this.skincareCard(mockBeautyProducts[1])
            this.skincareCard(mockBeautyProducts[14])
            this.skincareCard(mockBeautyProducts[8])
            this.skincareCard(mockBeautyProducts[9])
            this.skincareCard(mockBeautyProducts[5])
            this.skincareCard(mockBeautyProducts[4])
            this.skincareCard(mockBeautyProducts[15])
            this.skincareCard(mockBeautyProducts[19])
          }
          .padding({ bottom: 20 })
        }
        .layoutWeight(1).scrollBar(BarState.Off)
      }
      .width('100%').height('100%')

      if (this.showDetailModal) { this.detailModal() }
      if (this.showEditModal) { this.editModal() }
      if (this.showDeleteModal) { this.deleteModal() }
      if (this.showAddModal) { this.addModal() }
    }
    .width('100%').height('100%')
  }
}

// ============ 彩妆香水页(瀑布双列+色号选择) ============
@Component
struct MakeupContent {
  @State showShadeModal: boolean = false
  @State showDetailModal: boolean = false
  @State showEditModal: boolean = false
  @State showDeleteModal: boolean = false
  @State selectedProduct: BeautyProduct | null = null

  @Builder modalOverlay(onClose?: () => void) {
    Column()
      .width('100%').height('100%')
      .backgroundColor('rgba(0,0,0,0.4)')
      .onClick(() => { if (onClose) { onClose() } })
  }

  @Builder shadeModal() {
    Column() {
      this.modalOverlay(() => { this.showShadeModal = false })
      Column() {
        Text('🎨 选择色号').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
          .padding({ top: 22, bottom: 4 })
        Text(this.selectedProduct?.name ?? '').fontSize(12).fontColor('#999999').padding({ bottom: 12 })
        Column() {
          Row() {
            Column() {
              Column().width(40).height(40).backgroundColor('#DC143C').borderRadius(20)
              Text('#1966').fontSize(10).fontColor('#333333').margin({ top: 4 })
            }.layoutWeight(1).alignItems(HorizontalAlign.Center)
            Column() {
              Column().width(40).height(40).backgroundColor('#FF0000').borderRadius(20)
              Text('#400').fontSize(10).fontColor('#333333').margin({ top: 4 })
            }.layoutWeight(1).alignItems(HorizontalAlign.Center)
            Column() {
              Column().width(40).height(40).backgroundColor('#8B0000').borderRadius(20)
              Text('#16').fontSize(10).fontColor('#333333').margin({ top: 4 })
            }.layoutWeight(1).alignItems(HorizontalAlign.Center)
          }
          .padding({ top: 8, bottom: 8 })
          Row() {
            Column() {
              Column().width(40).height(40).backgroundColor('#FF69B4').borderRadius(20)
              Text('高潮').fontSize(10).fontColor('#333333').margin({ top: 4 })
            }.layoutWeight(1).alignItems(HorizontalAlign.Center)
            Column() {
              Column().width(40).height(40).backgroundColor('#FFC0CB').borderRadius(20)
              Text('浅粉').fontSize(10).fontColor('#333333').margin({ top: 4 })
            }.layoutWeight(1).alignItems(HorizontalAlign.Center)
            Column() {
              Column().width(40).height(40).backgroundColor('#800020').borderRadius(20)
              Text('酒红').fontSize(10).fontColor('#333333').margin({ top: 4 })
            }.layoutWeight(1).alignItems(HorizontalAlign.Center)
          }
          .padding({ top: 8, bottom: 8 })
        }
        .width('100%').padding({ left: 16, right: 16 })
        Text('确认选择').fontSize(14).fontColor('#FFFFFF')
          .backgroundColor('#E91E63').borderRadius(20)
          .padding({ left: 36, right: 36, top: 12, bottom: 12 })
          .margin({ top: 14, bottom: 22 })
          .onClick(() => { this.showShadeModal = false })
      }
      .width('80%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder detailModal() {
    Column() {
      this.modalOverlay(() => { this.showDetailModal = false })
      Column() {
        Text(this.selectedProduct?.emoji ?? '💄').fontSize(48).margin({ top: 20 })
        Text(this.selectedProduct?.name ?? '').fontSize(15).fontColor('#333333').fontWeight(FontWeight.Bold)
          .padding({ left: 16, right: 16, top: 8 })
        Text('¥' + (this.selectedProduct?.price ?? 0)).fontSize(22).fontColor('#E91E63').fontWeight(FontWeight.Bold)
        Row() {
          Text('选色号').fontSize(13).fontColor('#E91E63')
            .backgroundColor('#FCE4EC').borderRadius(18)
            .padding({ left: 22, right: 22, top: 10, bottom: 10 })
            .onClick(() => { this.showDetailModal = false; this.showShadeModal = true })
          Text('编辑').fontSize(13).fontColor('#FFFFFF')
            .backgroundColor('#9C27B0').borderRadius(18)
            .padding({ left: 22, right: 22, top: 10, bottom: 10 }).margin({ left: 10 })
            .onClick(() => { this.showDetailModal = false; this.showEditModal = true })
          Text('删除').fontSize(13).fontColor('#FFFFFF')
            .backgroundColor('#F44336').borderRadius(18)
            .padding({ left: 22, right: 22, top: 10, bottom: 10 }).margin({ left: 10 })
            .onClick(() => { this.showDetailModal = false; this.showDeleteModal = true })
        }
        .padding({ top: 14, bottom: 20 })
      }
      .width('75%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder editModal() {
    Column() {
      this.modalOverlay(() => { this.showEditModal = false })
      Column() {
        Text('✏️ 编辑彩妆信息').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
          .padding({ top: 22, bottom: 10 })
        Divider().color('#F0F0F0')
        Text('产品名称').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: this.selectedProduct?.name ?? '' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('品牌').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: this.selectedProduct?.brand ?? '' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('色号').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: this.selectedProduct?.shade ?? '' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('价格').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: '¥' + (this.selectedProduct?.price ?? 0) })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Row() {
          Text('取消').fontSize(14).fontColor('#999999')
            .backgroundColor('#F5F5F5').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 })
            .onClick(() => { this.showEditModal = false })
          Text('保存').fontSize(14).fontColor('#FFFFFF')
            .backgroundColor('#E91E63').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 }).margin({ left: 12 })
            .onClick(() => { this.showEditModal = false })
        }
        .padding({ top: 18, bottom: 22 })
      }
      .width('88%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder deleteModal() {
    Column() {
      this.modalOverlay(() => { this.showDeleteModal = false })
      Column() {
        Text('💔').fontSize(36).margin({ top: 20 })
        Text('确认删除彩妆产品?').fontSize(15).fontColor('#333333').fontWeight(FontWeight.Bold).margin({ top: 6 })
        Row() {
          Text('取消').fontSize(13).fontColor('#999999')
            .backgroundColor('#F5F5F5').borderRadius(16)
            .padding({ left: 24, right: 24, top: 8, bottom: 8 })
            .onClick(() => { this.showDeleteModal = false })
          Text('删除').fontSize(13).fontColor('#FFFFFF')
            .backgroundColor('#F44336').borderRadius(16)
            .padding({ left: 24, right: 24, top: 8, bottom: 8 }).margin({ left: 10 })
            .onClick(() => { this.showDeleteModal = false })
        }
        .padding({ top: 14, bottom: 18 })
      }
      .width('72%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder makeupCard(p: BeautyProduct) {
    Column() {
      Column() {
        Text(p.emoji).fontSize(36)
      }.width('100%').height(64).justifyContent(FlexAlign.Center)
      .backgroundColor('#FFF5F8').borderRadius({ topLeft: 10, topRight: 10 })
      Text(p.name).fontSize(10).fontColor('#333333').maxLines(1).padding({ left: 6, right: 6, top: 4 })
      Text(p.brand).fontSize(9).fontColor('#9C27B0')
      Row() {
        Text('¥' + p.price).fontSize(13).fontColor('#E91E63').fontWeight(FontWeight.Bold)
        Text('¥' + p.originalPrice).fontSize(9).fontColor('#999999')
          .decoration({ type: TextDecorationType.LineThrough }).margin({ left: 4, top: 2 })
      }
      .padding({ left: 6, bottom: 4 })
      Row() {
        Text(p.tag).fontSize(8).fontColor('#FFFFFF').backgroundColor('#E91E63')
          .borderRadius(4).padding({ left: 4, right: 4, top: 1, bottom: 1 })
        Text('⭐' + p.rating).fontSize(8).fontColor('#FF9800').margin({ left: 4 })
      }
      .padding({ left: 6, bottom: 6 })
    }
    .width('100%').backgroundColor('#FFFFFF').borderRadius(10)
    .onClick(() => { this.selectedProduct = p; this.showDetailModal = true })
  }

  build() {
    Stack() {
      Column() {
        Row() {
          Text('💄 彩妆香水').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
          Column().layoutWeight(1)
          Text('🎨').fontSize(18).margin({ right: 14 })
            .onClick(() => { this.showShadeModal = true })
        }
        .width('100%').padding({ top: 14, bottom: 10 })
        .backgroundColor('#FFFFFF')

        Scroll() {
          Row() {
            ForEach(MAKEUP_CATS, (c: string) => {
              Text(c).fontSize(11).fontColor('#9C27B0').backgroundColor('#F3E5F5')
                .borderRadius(14).padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4, right: 4 })
            })
          }
          .padding({ left: 8, right: 8 })
        }
        .scrollable(ScrollDirection.Horizontal).scrollBar(BarState.Off).height(36)
        .backgroundColor('#FFFFFF')

        Scroll() {
          Column() {
            Row() {
              this.makeupCard(mockBeautyProducts[4])
              this.makeupCard(mockBeautyProducts[5])
            }
            .padding({ left: 6, right: 6 })
            Row() {
              this.makeupCard(mockBeautyProducts[1])
              this.makeupCard(mockBeautyProducts[13])
            }
            .padding({ left: 6, right: 6, top: 6 })
            Row() {
              this.makeupCard(mockBeautyProducts[8])
              this.makeupCard(mockBeautyProducts[15])
            }
            .padding({ left: 6, right: 6, top: 6 })
            Row() {
              this.makeupCard(mockBeautyProducts[9])
              this.makeupCard(mockBeautyProducts[14])
            }
            .padding({ left: 6, right: 6, top: 6 })
            Row() {
              this.makeupCard(mockBeautyProducts[19])
              this.makeupCard(mockBeautyProducts[16])
            }
            .padding({ left: 6, right: 6, top: 6 })
            Row() {
              this.makeupCard(mockBeautyProducts[3])
              this.makeupCard(mockBeautyProducts[7])
            }
            .padding({ left: 6, right: 6, top: 6 })
            Row() {
              this.makeupCard(mockBeautyProducts[0])
              this.makeupCard(mockBeautyProducts[2])
            }
            .padding({ left: 6, right: 6, top: 6 })
            Row() {
              this.makeupCard(mockBeautyProducts[6])
              this.makeupCard(mockBeautyProducts[10])
            }
            .padding({ left: 6, right: 6, top: 6 })
            Row() {
              this.makeupCard(mockBeautyProducts[11])
              this.makeupCard(mockBeautyProducts[12])
            }
            .padding({ left: 6, right: 6, top: 6 })
            Row() {
              this.makeupCard(mockBeautyProducts[17])
              this.makeupCard(mockBeautyProducts[18])
            }
            .padding({ left: 6, right: 6, top: 6, bottom: 20 })
          }
        }
        .layoutWeight(1).scrollBar(BarState.Off)
      }
      .width('100%').height('100%')

      if (this.showShadeModal) { this.shadeModal() }
      if (this.showDetailModal) { this.detailModal() }
      if (this.showEditModal) { this.editModal() }
      if (this.showDeleteModal) { this.deleteModal() }
    }
    .width('100%').height('100%')
  }
}

// ============ 订单页(状态Tab+饼图) ============
@Component
struct BeautyOrderContent {
  @State selectedStatus: string = '全部'
  @State showDetailModal: boolean = false
  @State showEditModal: boolean = false
  @State showDeleteModal: boolean = false
  @State selectedOrder: BeautyOrder | null = null

  @Builder modalOverlay(onClose?: () => void) {
    Column()
      .width('100%').height('100%')
      .backgroundColor('rgba(0,0,0,0.4)')
      .onClick(() => { if (onClose) { onClose() } })
  }

  @Builder orderDetailModal() {
    Column() {
      this.modalOverlay(() => { this.showDetailModal = false })
      Column() {
        Text(this.selectedOrder?.emoji ?? '📦').fontSize(40).margin({ top: 20 })
        Text('订单详情').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#333333').margin({ top: 8 })
        Divider().color('#F0F0F0').margin({ top: 10 })
        Column() {
          Row() {
            Text('订单号').fontSize(11).fontColor('#999999')
            Text(this.selectedOrder?.orderNo ?? '').fontSize(11).fontColor('#666666').margin({ left: 8 })
          }.width('100%').padding({ top: 8, bottom: 4 })
          Row() {
            Text('商品').fontSize(11).fontColor('#999999')
            Text(this.selectedOrder?.productName ?? '').fontSize(11).fontColor('#333333').margin({ left: 8 })
          }.width('100%').padding({ top: 4, bottom: 4 })
          Row() {
            Text('金额').fontSize(11).fontColor('#999999')
            Text('¥' + (this.selectedOrder?.amount ?? 0)).fontSize(13).fontColor('#E91E63').fontWeight(FontWeight.Bold).margin({ left: 8 })
          }.width('100%').padding({ top: 4, bottom: 4 })
          Row() {
            Text('状态').fontSize(11).fontColor('#999999')
            Text(this.selectedOrder?.status ?? '').fontSize(11).fontColor('#4CAF50').margin({ left: 8 })
          }.width('100%').padding({ top: 4, bottom: 8 })
        }
        .width('100%').padding({ left: 20, right: 20 })
        Row() {
          Text('编辑').fontSize(13).fontColor('#E91E63')
            .backgroundColor('#FCE4EC').borderRadius(18)
            .padding({ left: 22, right: 22, top: 10, bottom: 10 })
            .onClick(() => { this.showDetailModal = false; this.showEditModal = true })
          Text('删除').fontSize(13).fontColor('#FFFFFF')
            .backgroundColor('#F44336').borderRadius(18)
            .padding({ left: 22, right: 22, top: 10, bottom: 10 }).margin({ left: 10 })
            .onClick(() => { this.showDetailModal = false; this.showDeleteModal = true })
        }
        .padding({ top: 8, bottom: 20 })
      }
      .width('82%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder editModal() {
    Column() {
      this.modalOverlay(() => { this.showEditModal = false })
      Column() {
        Text('✏️ 编辑订单').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
          .padding({ top: 22, bottom: 10 })
        Divider().color('#F0F0F0')
        Text('收件人').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: '李娜' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('联系电话').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: '139****6666' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('收货地址').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextArea({ placeholder: '北京市海淀区...' })
          .placeholderColor('#BBBBBB').fontSize(12).width('90%').height(50)
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('备注留言').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: '选填...' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Row() {
          Text('取消').fontSize(14).fontColor('#999999')
            .backgroundColor('#F5F5F5').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 })
            .onClick(() => { this.showEditModal = false })
          Text('保存').fontSize(14).fontColor('#FFFFFF')
            .backgroundColor('#E91E63').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 }).margin({ left: 12 })
            .onClick(() => { this.showEditModal = false })
        }
        .padding({ top: 18, bottom: 22 })
      }
      .width('88%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder deleteModal() {
    Column() {
      this.modalOverlay(() => { this.showDeleteModal = false })
      Column() {
        Text('⚠️').fontSize(36).margin({ top: 20 })
        Text('确认删除此订单?').fontSize(15).fontColor('#333333').fontWeight(FontWeight.Bold).margin({ top: 6 })
        Text('删除后不可恢复').fontSize(11).fontColor('#F44336').margin({ top: 4 })
        Row() {
          Text('取消').fontSize(13).fontColor('#999999')
            .backgroundColor('#F5F5F5').borderRadius(16)
            .padding({ left: 24, right: 24, top: 8, bottom: 8 })
            .onClick(() => { this.showDeleteModal = false })
          Text('确认删除').fontSize(13).fontColor('#FFFFFF')
            .backgroundColor('#F44336').borderRadius(16)
            .padding({ left: 24, right: 24, top: 8, bottom: 8 }).margin({ left: 10 })
            .onClick(() => { this.showDeleteModal = false })
        }
        .padding({ top: 14, bottom: 18 })
      }
      .width('74%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder orderItemBuilder(o: BeautyOrder) {
    Row() {
      Column() {
        Text(o.emoji).fontSize(28)
      }.width(52).height(52).backgroundColor('#FFF5F8').borderRadius(8)
      .justifyContent(FlexAlign.Center)
      Column() {
        Text(o.productName).fontSize(12).fontColor('#333333').fontWeight(FontWeight.Medium).maxLines(1)
        Text(o.orderNo).fontSize(10).fontColor('#999999').margin({ top: 2 })
        Row() {
          Text('¥' + o.amount).fontSize(14).fontColor('#E91E63').fontWeight(FontWeight.Bold)
          Text(o.date).fontSize(10).fontColor('#999999').margin({ left: 8 })
          Column().layoutWeight(1)
          Text(o.status).fontSize(10).fontColor('#4CAF50')
            .backgroundColor('#E8F5E9').borderRadius(6)
            .padding({ left: 6, right: 6, top: 2, bottom: 2 })
        }
        .margin({ top: 4 })
      }.layoutWeight(1).alignItems(HorizontalAlign.Start).padding({ left: 10 })
    }
    .width('100%').backgroundColor('#FFFFFF').borderRadius(12)
    .padding({ left: 12, right: 12, top: 10, bottom: 10 })
    .margin({ left: 12, right: 12, top: 5 })
    .onClick(() => { this.selectedOrder = o; this.showDetailModal = true })
  }

  build() {
    Stack() {
      Column() {
        Row() {
          Text('📋 美妆订单').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
          Column().layoutWeight(1)
          Text('共' + mockBeautyOrders.length + '单').fontSize(11).fontColor('#999999').margin({ right: 14 })
        }
        .width('100%').padding({ top: 14, bottom: 10 })
        .backgroundColor('#FFFFFF')

        Row() {
          ForEach(ORDER_STATUS, (s: string) => {
            if (this.selectedStatus === s) {
              Text(s).fontSize(11).fontColor('#E91E63').fontWeight(FontWeight.Bold)
                .padding({ left: 6, right: 6 }).layoutWeight(1).textAlign(TextAlign.Center)
            } else {
              Text(s).fontSize(11).fontColor('#999999')
                .padding({ left: 6, right: 6 }).layoutWeight(1).textAlign(TextAlign.Center)
                .onClick(() => { this.selectedStatus = s })
            }
          })
        }
        .width('100%').padding({ top: 8, bottom: 8 })
        .backgroundColor('#FFFFFF').border({ width: { bottom: 1 }, color: '#F0F0F0' })

        // 消费占比饼图(CSS模拟)
        Column() {
          Text('💰 消费分类占比').fontSize(13).fontWeight(FontWeight.Bold).fontColor('#333333')
            .width('100%').padding({ left: 16, top: 12, bottom: 8 })
          Row() {
            Column() {
              Column().width(80).height(80).borderRadius(40)
                .backgroundColor('#E91E63')
                .border({ width: 3, color: '#FCE4EC' })
              Text('护肤 45%').fontSize(10).fontColor('#E91E63').margin({ top: 4 })
            }.layoutWeight(1).alignItems(HorizontalAlign.Center)
            Column() {
              Column().width(60).height(60).borderRadius(30)
                .backgroundColor('#9C27B0')
                .border({ width: 3, color: '#F3E5F5' })
              Text('彩妆 30%').fontSize(10).fontColor('#9C27B0').margin({ top: 4 })
            }.layoutWeight(1).alignItems(HorizontalAlign.Center)
            Column() {
              Column().width(45).height(45).borderRadius(22)
                .backgroundColor('#FF9800')
                .border({ width: 3, color: '#FFF3E0' })
              Text('香水 15%').fontSize(10).fontColor('#FF9800').margin({ top: 4 })
            }.layoutWeight(1).alignItems(HorizontalAlign.Center)
            Column() {
              Column().width(35).height(35).borderRadius(17)
                .backgroundColor('#4CAF50')
                .border({ width: 3, color: '#E8F5E9' })
              Text('其他 10%').fontSize(10).fontColor('#4CAF50').margin({ top: 4 })
            }.layoutWeight(1).alignItems(HorizontalAlign.Center)
          }
          .padding({ bottom: 12 })
        }
        .width('100%').backgroundColor('#FFFFFF').borderRadius(12)
        .margin({ left: 12, right: 12, top: 6 })

        Scroll() {
          Column() {
            this.orderItemBuilder(mockBeautyOrders[0])
            this.orderItemBuilder(mockBeautyOrders[1])
            this.orderItemBuilder(mockBeautyOrders[2])
            this.orderItemBuilder(mockBeautyOrders[3])
            this.orderItemBuilder(mockBeautyOrders[4])
            this.orderItemBuilder(mockBeautyOrders[5])
            this.orderItemBuilder(mockBeautyOrders[6])
            this.orderItemBuilder(mockBeautyOrders[7])
          }
          .padding({ bottom: 20 })
        }
        .layoutWeight(1).scrollBar(BarState.Off)
      }
      .width('100%').height('100%')

      if (this.showDetailModal) { this.orderDetailModal() }
      if (this.showEditModal) { this.editModal() }
      if (this.showDeleteModal) { this.deleteModal() }
    }
    .width('100%').height('100%')
  }
}

// ============ 个人中心页(肌肤档案) ============
@Component
struct BeautyProfileContent {
  @State showEditModal: boolean = false
  @State showSkinModal: boolean = false
  @State showDeleteModal: boolean = false

  @Builder modalOverlay(onClose?: () => void) {
    Column()
      .width('100%').height('100%')
      .backgroundColor('rgba(0,0,0,0.4)')
      .onClick(() => { if (onClose) { onClose() } })
  }

  @Builder editModal() {
    Column() {
      this.modalOverlay(() => { this.showEditModal = false })
      Column() {
        Text('✏️ 编辑个人资料').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
          .padding({ top: 22, bottom: 10 })
        Divider().color('#F0F0F0')
        Text('昵称').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: '美妆小达人' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('手机号').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: '139****6666' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('邮箱').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        TextInput({ placeholder: 'beauty@example.com' })
          .placeholderColor('#BBBBBB').fontSize(13).width('90%')
          .backgroundColor('#FFF5F8').borderRadius(8).margin({ top: 4 })
        Text('肌肤类型').fontSize(12).fontColor('#999999').width('100%').padding({ left: 20, top: 14 })
        Row() {
          Text('混合肌肤').fontSize(11).fontColor('#FFFFFF').backgroundColor('#E91E63').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
          Text('干性').fontSize(11).fontColor('#E91E63').backgroundColor('#FCE4EC').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
          Text('油性').fontSize(11).fontColor('#E91E63').backgroundColor('#FCE4EC').borderRadius(10)
            .padding({ left: 12, right: 12, top: 5, bottom: 5 }).margin({ left: 4 })
        }
        .padding({ left: 16, top: 6 })
        Row() {
          Text('取消').fontSize(14).fontColor('#999999')
            .backgroundColor('#F5F5F5').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 })
            .onClick(() => { this.showEditModal = false })
          Text('保存').fontSize(14).fontColor('#FFFFFF')
            .backgroundColor('#E91E63').borderRadius(20)
            .padding({ left: 28, right: 28, top: 12, bottom: 12 }).margin({ left: 12 })
            .onClick(() => { this.showEditModal = false })
        }
        .padding({ top: 18, bottom: 22 })
      }
      .width('88%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder skinRecordModal() {
    Column() {
      this.modalOverlay(() => { this.showSkinModal = false })
      Column() {
        Text('📊 肌肤档案记录').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
          .padding({ top: 22, bottom: 4 })
        Text('近7天肌肤数据变化').fontSize(11).fontColor('#999999').padding({ bottom: 12 })
        Divider().color('#F0F0F0')
        Scroll() {
          Column() {
            ForEach(mockSkinRecords, (r: SkinRecord) => {
              Column() {
                Row() {
                  Text(r.date).fontSize(13).fontColor('#333333').fontWeight(FontWeight.Bold)
                  Column().layoutWeight(1)
                  Text('综合评分 ' + r.score).fontSize(12).fontColor('#E91E63').fontWeight(FontWeight.Bold)
                }
                .width('100%')
                Row() {
                  Text('水分').fontSize(11).fontColor('#999999')
                  Column().layoutWeight(1).height(4).backgroundColor('#F0F0F0').borderRadius(2)
                  Text(r.moisture + '%').fontSize(11).fontColor('#03A9F4').margin({ left: 4 })
                }
                .width('100%').margin({ top: 6 })
                Row() {
                  Text('油分').fontSize(11).fontColor('#999999')
                  Column().layoutWeight(1).height(4).backgroundColor('#F0F0F0').borderRadius(2)
                  Text(r.oil + '%').fontSize(11).fontColor('#FF9800').margin({ left: 4 })
                }
                .width('100%').margin({ top: 4 })
                Row() {
                  Text('平滑度').fontSize(11).fontColor('#999999')
                  Column().layoutWeight(1).height(4).backgroundColor('#F0F0F0').borderRadius(2)
                  Text(r.smoothness + '%').fontSize(11).fontColor('#4CAF50').margin({ left: 4 })
                }
                .width('100%').margin({ top: 4 })
              }
              .width('100%').padding({ left: 16, right: 16, top: 10, bottom: 10 })
              .border({ width: { bottom: 1 }, color: '#F0F0F0' })
            })
          }
        }
        .layoutWeight(1).constraintSize({ maxHeight: '40%' })
        Text('✕ 关闭').fontSize(13).fontColor('#999999')
          .margin({ top: 12, bottom: 18 })
          .onClick(() => { this.showSkinModal = false })
      }
      .width('88%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder deleteModal() {
    Column() {
      this.modalOverlay(() => { this.showDeleteModal = false })
      Column() {
        Text('⚠️').fontSize(40).margin({ top: 22 })
        Text('确认注销账号?').fontSize(16).fontColor('#333333').fontWeight(FontWeight.Bold).margin({ top: 8 })
        Text('所有美妆档案将永久删除').fontSize(11).fontColor('#F44336').margin({ top: 4 })
        Row() {
          Text('取消').fontSize(14).fontColor('#999999')
            .backgroundColor('#F5F5F5').borderRadius(20)
            .padding({ left: 28, right: 28, top: 10, bottom: 10 })
            .onClick(() => { this.showDeleteModal = false })
          Text('确认注销').fontSize(14).fontColor('#FFFFFF')
            .backgroundColor('#F44336').borderRadius(20)
            .padding({ left: 28, right: 28, top: 10, bottom: 10 }).margin({ left: 12 })
            .onClick(() => { this.showDeleteModal = false })
        }
        .padding({ top: 20, bottom: 22 })
      }
      .width('76%').backgroundColor('#FFFFFF').borderRadius(20)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%').height('100%').position({ x: 0, y: 0 }).zIndex(999)
    .justifyContent(FlexAlign.Center)
  }

  @Builder settingItem(icon: string, label: string, action?: () => void) {
    Row() {
      Text(icon).fontSize(18)
      Text(label).fontSize(13).fontColor('#333333').layoutWeight(1).margin({ left: 12 })
      Text('>').fontSize(14).fontColor('#CCCCCC')
    }
    .width('100%').padding({ top: 14, bottom: 14, left: 16 })
    .border({ width: { bottom: 1 }, color: '#F5F5F5' })
    .onClick(() => { if (action) { action() } })
  }

  build() {
    Stack() {
      Column() {
        // 会员卡
        Column() {
          Row() {
            Column() {
              Text('💁‍♀️').fontSize(40)
            }.width(60).height(60).backgroundColor('#FCE4EC').borderRadius(30)
            .justifyContent(FlexAlign.Center)
            Column() {
              Text('美妆小达人').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#333333')
              Text('139****6666').fontSize(11).fontColor('#999999').margin({ top: 2 })
              Row() {
                Text('钻石会员').fontSize(9).fontColor('#FFFFFF').backgroundColor('#E91E63')
                  .borderRadius(4).padding({ left: 5, right: 5, top: 1, bottom: 1 })
                Text('积分 8650').fontSize(10).fontColor('#999999').margin({ left: 8 })
                Text('美妆豆 320').fontSize(10).fontColor('#999999').margin({ left: 8 })
              }
              .margin({ top: 4 })
            }.layoutWeight(1).alignItems(HorizontalAlign.Start).padding({ left: 14 })
            Text('✏️').fontSize(18).margin({ right: 14 })
              .onClick(() => { this.showEditModal = true })
          }
          .width('100%').padding({ left: 16, right: 16, top: 16, bottom: 16 })
        }
        .width('100%').backgroundColor('#FFFFFF')

        // 数据统计
        Row() {
          Column() {
            Text('8').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#E91E63')
            Text('全部订单').fontSize(9).fontColor('#999999')
          }.layoutWeight(1).alignItems(HorizontalAlign.Center)
          Column() {
            Text('15').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#9C27B0')
            Text('收藏产品').fontSize(9).fontColor('#999999')
          }.layoutWeight(1).alignItems(HorizontalAlign.Center)
          Column() {
            Text('5').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#FF9800')
            Text('优惠券').fontSize(9).fontColor('#999999')
          }.layoutWeight(1).alignItems(HorizontalAlign.Center)
          Column() {
            Text('85').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#4CAF50')
            Text('肌肤评分').fontSize(9).fontColor('#999999')
          }.layoutWeight(1).alignItems(HorizontalAlign.Center)
        }
        .width('100%').padding({ top: 12, bottom: 12 })
        .backgroundColor('#FFFFFF').margin({ top: 6 })

        // 肌肤档案入口
        Row() {
          Text('📊').fontSize(28)
          Column() {
            Text('我的肌肤档案').fontSize(14).fontColor('#333333').fontWeight(FontWeight.Bold)
            Text('查看近7天肌肤数据变化').fontSize(10).fontColor('#999999').margin({ top: 2 })
          }.layoutWeight(1).alignItems(HorizontalAlign.Start).padding({ left: 12 })
          Text('查看 >').fontSize(12).fontColor('#E91E63')
        }
        .width('100%').padding({ left: 16, right: 16, top: 14, bottom: 14 })
        .backgroundColor('#FFFFFF').borderRadius(12)
        .margin({ left: 12, right: 12, top: 8 })
        .onClick(() => { this.showSkinModal = true })

        // 设置列表
        Scroll() {
          Column() {
            this.settingItem('📍', '收货地址管理', () => {})
            this.settingItem('🎫', '我的优惠券', () => {})
            this.settingItem('💰', '我的钱包', () => {})
            this.settingItem('⭐', '我的收藏', () => {})
            this.settingItem('📦', '浏览历史', () => {})
            this.settingItem('🔔', '消息通知', () => {})
            this.settingItem('🎨', '主题设置', () => {})
            this.settingItem('📞', '联系客服', () => {})
            this.settingItem('🚪', '退出登录', () => { this.showDeleteModal = true })
          }
          .backgroundColor('#FFFFFF').borderRadius(12)
          .margin({ left: 12, right: 12, top: 8, bottom: 20 })
        }
        .layoutWeight(1).scrollBar(BarState.Off)
      }
      .width('100%').height('100%')

      if (this.showEditModal) { this.editModal() }
      if (this.showSkinModal) { this.skinRecordModal() }
      if (this.showDeleteModal) { this.deleteModal() }
    }
    .width('100%').height('100%')
  }
}

十五、总结展望

本文完整解析了基于HarmonyOS API 24的美妆护肤精选商城应用,从粉紫渐变浅色主题色彩系统、多组件分离架构、美妆产品数据模型(含shade色号字段)、首页热销榜单+AI肌肤测试入口、护肤分类筛选+功效/肤质选择、彩妆瀑布双列+色号选择器、订单状态Tab+消费占比饼图、个人中心肌肤档案+会员体系,到15+种弹框体系、肌肤类型测试问卷、十六进制色号渲染、三色肌肤进度条、粉紫双主色品类区分,展现了ArkTS在美妆电商场景下的完整工程实践。

核心价值:

  1. 粉紫双主色品类区分:护肤粉红/彩妆紫色,用户一眼识别品类
  2. 多组件分离架构:5个独立@Component子组件,状态隔离、代码模块化
  3. AI肌肤测试问卷:5种肤质类型分步问卷,帮助用户判断肤质
  4. 色号精准匹配:十六进制颜色值渲染圆形色块,线上选色直观
  5. 消费占比可视化:圆形色块模拟饼图,消费结构一目了然
  6. 肌肤数据追踪:近7天水分/油分/平滑度三色进度条,肤质变化可追踪

未来可扩展:

  • 接入真实AI肌肤检测SDK,通过拍照分析肤质,替代手动问卷
  • 色号选择器接入AR试妆功能,用户实时预览上妆效果
  • 肌肤档案接入护肤产品使用记录,形成"肤质-产品-效果"闭环推荐
  • 消费占比接入真实订单数据,支持月/季/年维度切换和趋势分析
  • 接入美妆品牌官方旗舰店,实现正品保障和品牌专属优惠
  • 会员体系接入积分兑换、美妆豆抵扣、专属客服等增值服务

美妆护肤精选商城,让每一次购买都精准匹配你的肌肤。


Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐