HarmonyOS 6 ArkTS工具函数封装与数据处理,实现数据转换、条件筛选、状态匹配、数值计算逻辑,简化页面复杂数据渲染流程
从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在美妆电商场景下的完整工程实践。
核心价值:
- 粉紫双主色品类区分:护肤粉红/彩妆紫色,用户一眼识别品类
- 多组件分离架构:5个独立@Component子组件,状态隔离、代码模块化
- AI肌肤测试问卷:5种肤质类型分步问卷,帮助用户判断肤质
- 色号精准匹配:十六进制颜色值渲染圆形色块,线上选色直观
- 消费占比可视化:圆形色块模拟饼图,消费结构一目了然
- 肌肤数据追踪:近7天水分/油分/平滑度三色进度条,肤质变化可追踪
未来可扩展:
- 接入真实AI肌肤检测SDK,通过拍照分析肤质,替代手动问卷
- 色号选择器接入AR试妆功能,用户实时预览上妆效果
- 肌肤档案接入护肤产品使用记录,形成"肤质-产品-效果"闭环推荐
- 消费占比接入真实订单数据,支持月/季/年维度切换和趋势分析
- 接入美妆品牌官方旗舰店,实现正品保障和品牌专属优惠
- 会员体系接入积分兑换、美妆豆抵扣、专属客服等增值服务
美妆护肤精选商城,让每一次购买都精准匹配你的肌肤。
更多推荐

所有评论(0)