本文基于 HarmonyOS ArkTS 声明式 UI(ArkUI)开发的美发沙龙发型设计一站式平台源码,从色彩系统、架构设计、数据模型、八大 Tab、首页设计、预约系统、服务生态、设计师产品、社区优惠、美发文化、平台趋势、深色时尚感等多个维度进行深度解析,并在文末附录提供完整可运行的 ArkTS 源码。


引言:从"头"开始的美丽经济

美发,是人们日常生活中最频繁的美容消费之一。从男士的经典短发、复古油头,到女士的长发波浪、空气刘海,再到儿童的可爱造型,发型不仅是个人形象的重要组成部分,更是时尚态度和个性表达的载体。然而,传统美发行业长期存在着信息不透明、预约不方便、设计师水平参差不齐、产品质量难以保证等痛点。用户往往需要通过电话或到店预约,不知道哪位设计师擅长自己想要的风格,也不清楚店里有哪些洗护造型产品可供选择。

"美发沙龙"发型设计一站式平台,正是为解决这些痛点而生的概念应用。它将美发服务的全流程整合在一个平台中,通过 8 个 Tab(首页/发型/预约/设计师/产品/社区/优惠/我的)构建了完整的美发服务生态。用户可以在一个 App 中浏览发型图库、在线预约时间、选择心仪的设计师、购买洗护造型产品、在社区分享发型经验、领取优惠券享受优惠,实现了从发现到预约到消费到分享的全链路闭环。

这款应用的视觉设计独具匠心。以深黑 #121212 为底色,营造高级而时尚的氛围;以优雅紫 #9B59B6 为主强调色,传递创意与个性;以明亮金 #F1C40F 为辅助强调色,增添品质与活力。紫金配色在深色背景上的碰撞,既符合美发行业的时尚创意属性,又具有现代设计的高级感和品质感。紫色象征创意与个性,金色象征品质与尊贵,二者协同构建了一个既时尚又专业的美发服务视觉体验。

与功能完整的真实美业平台不同,这款概念应用聚焦于前端 UI 层的设计与实现,所有数据为静态 mock 数据,在线支付、实时预约同步、用户登录等后端功能未实现。这种"UI 优先"的定位使得应用代码简洁清晰,适合作为 ArkUI 开发的学习案例和美业平台的设计参考。应用采用纯 ArkTS 单文件开发,约 750 行代码,无第三方依赖,复制即可在 DevEco Studio 中运行,严格遵循 ArkTS 严格模式规范。

本文将带你深入这款美发沙龙平台的设计与实现,理解美发服务的全流程设计和紫金时尚美学,以及 ArkTS 声明式 UI 如何高效构建服务类应用。

美发沙龙主界面

色彩风格:优雅紫与明亮金的时尚碰撞

这款应用的色彩系统是美发行业时尚属性与现代深色模式设计的完美融合。深黑 #121212 作为背景色,是流媒体和生活服务类应用的经典深色背景,既降低了视觉疲劳,又让彩色内容更加突出。卡片色 #1E1E1E 和浅卡片色 #2C2C2C 构建了清晰的三级灰度层级,让内容卡片在深色背景上自然浮现。

主强调色 #9B59B6 是优雅的紫罗兰色,这是一种饱和度适中(约 65%)、明度中等(约 55%)的紫色。紫色在色彩心理学中象征创意、个性、神秘与高贵,与美发行业的创意属性高度契合——发型设计本身就是一种创意表达,每位设计师都有自己的风格和个性。紫色在深色背景上具有良好的视觉穿透力,被用于 Tab 选中态、分类筛选选中态、设计师评分、预约确认按钮、社区发帖按钮、优惠券领取等关键交互元素,成为整个 App 的视觉锚点。深紫 #8E44AD 作为紫色的暗色变体,用于需要降低视觉强度的场景。

辅助强调色 #F1C40F 是明亮的金黄色,这是一种高饱和(约 85%)、高明度(约 60%)的暖黄色。金色象征品质、活力、尊贵与阳光,在美发行业中代表着高品质的服务和产品。金色在应用中被用于价格显示、设计师职称、产品品牌、预约已选提示、登录提示等信息元素,既提升了视觉品质感,又与紫色主色形成了冷暖对比的和谐搭配。

文字色采用纯白 #FFFFFF 作为主文字色,确保在深色背景上的最大可读性;中灰 #B0B0B0 作为次级文字色,用于描述、时间、分类等次要信息。chip 背景色 #3A3A3A 和边框色 #444444 构建了标签和分割线的视觉语言。

这套色彩系统的核心设计哲学是:深色背景营造高级时尚氛围,优雅紫传递创意与个性,明亮金增添品质与活力。三者协同,构建了一个既符合美发行业时尚创意属性、又具有现代设计高级感和品质感的视觉体验。紫金配色在美发场景中传递时尚与专业,在预约场景中传递可信赖感,在产品场景中传递品质感,同一套色彩系统适配了美发服务的多个场景。

美发沙龙色彩风格


第一章 项目概述

1.1 项目定位

美发沙龙发型设计一站式平台是一款基于 HarmonyOS ArkTS 声明式 UI(ArkUI)开发的生活服务类概念应用,API 9+,Stage 模型,单文件 .ets,约 750 行代码,严格遵循 ArkTS 严格模式规范(无展开,无 Object.assign,无计算属性名)。应用聚焦美发服务领域,通过 8 个 Tab 构建从发型浏览、在线预约、设计师选择、产品购买、社区分享到优惠领取的完整美发服务生态。

与美团、大众点评等综合生活服务平台不同,这款应用垂直聚焦于美发服务领域,将发型设计、预约管理、设计师资源、洗护产品、社区交流、优惠营销等美发相关服务整合在一个平台中,提供更专业、更聚焦的美发服务体验。

1.2 核心功能

应用的核心功能围绕美发服务全流程展开:

  1. 首页聚合:8 个分类快捷入口、热门发型横向滚动、热门设计师四列宫格、社区热帖预览,一站式聚合平台核心内容
  2. 发型大全:8 款发型(男士/女士/儿童),分类筛选 chips(全部/男士/女士/儿童),双列宫格展示
  3. 在线预约:选择设计师(4位)、选择时间段(6个时段,含不可约状态)、确认预约,完整预约流程
  4. 设计师:4 位发型师列表,展示职称、经验、擅长风格、评分
  5. 产品商城:4 款洗护造型产品,展示品牌、类型、价格,双列宫格
  6. 社区交流:3 条美发经验帖子,展示点赞、评论,发帖入口
  7. 优惠券:3 张优惠券,展示折扣、有效期,立即领取按钮
  8. 个人中心:未登录状态、我的预约、收藏发型、我的评论、优惠券、设置等菜单

1.3 技术栈

  • 开发框架:HarmonyOS ArkTS 声明式 UI(ArkUI)
  • API 版本:API 9+(Stage 模型)
  • 开发语言:ArkTS(TypeScript 超集,严格模式)
  • 开发工具:DevEco Studio
  • 代码规模:约 750 行,单文件 .ets
  • 第三方依赖:无

1.4 设计亮点

  1. 紫金时尚配色:优雅紫 #9B59B6 + 明亮金 #F1C40F + 纯白 #FFFFFF,在 #121212 深黑背景上构建高级时尚的视觉体验,符合美发行业的创意属性
  2. 8 Tab 全流程覆盖:首页/发型/预约/设计师/产品/社区/优惠/我的,8 个 Tab 覆盖美发服务从发现到消费到分享的全流程
  3. 双头部设计:首页使用 HomeHeader(品牌标识+副标题+通知+用户),其他 Tab 使用 CommonHeader(标题+通知),通过条件渲染切换
  4. 完整预约流程:预约 Tab 实现了设计师选择→时间段选择→确认预约的完整流程,包含状态管理(selectedDesigner/selectedSlot)和不可约时段处理
  5. 发型分类筛选:发型 Tab 实现了全部/男士/女士/儿童四分类筛选,通过 @Builder categoryChip 封装可复用的筛选标签
  6. getTabTitle 严格模式合规:使用 if-else 链替代对象字面量,避免计算属性名,是 ArkTS 严格模式的典型实践
  7. 四列设计师宫格:首页热门设计师使用 23% 宽度的四列宫格,在有限空间内展示多位设计师
  8. 优惠券营销设计:优惠 Tab 实现了优惠券列表+立即领取按钮的营销设计,折扣信息金色高亮突出
  9. 1 组交互动画:Tab 图标缩放(scale 1.2,200ms EaseOut),提升交互反馈感
  10. 单文件零依赖:约 750 行代码在一个 .ets 文件中,复制即运行,无第三方依赖

第二章 色彩系统

2.1 调色板接口与常量

应用的色彩系统通过 AppPalette 接口定义,包含 12 个色彩字段,然后通过 SP 常量实例化。

interface AppPalette {
  bg: string;
  primary: string;
  primaryDark: string;
  accent: string;
  card: string;
  cardLight: string;
  text: string;
  textSub: string;
  chip: string;
  border: string;
  white: string;
}

const SP: AppPalette = {
  bg: '#121212',
  primary: '#9B59B6',
  primaryDark: '#8E44AD',
  accent: '#F1C40F',
  card: '#1E1E1E',
  cardLight: '#2C2C2C',
  text: '#FFFFFF',
  textSub: '#B0B0B0',
  chip: '#3A3A3A',
  border: '#444444',
  white: '#FFFFFF'
};

2.2 背景色层级

应用的背景色采用三级深灰层级:

  • SP.bg #121212:页面最底层背景色,深灰近黑,是流媒体和生活服务类应用的经典深色背景
  • SP.card #1E1E1E:卡片背景色,比背景色亮约 7%,让内容卡片在背景上自然浮现
  • SP.cardLight #2C2C2C:浅卡片背景色,比卡片色再亮约 7%,用于横向推荐卡片、社区帖子、设计师列表、产品卡片等需要更高对比度的区域

2.3 主强调色系统

主强调色采用紫色双色调:

  • SP.primary #9B59B6:优雅紫,主强调色。这是一种饱和度适中(约 65%)、明度中等(约 55%)的紫罗兰色。紫色象征创意、个性、神秘与高贵,与美发行业的创意属性高度契合。用于 Tab 选中态文字和指示器、分类筛选选中态背景、设计师评分、预约确认按钮、社区发帖按钮、优惠券领取按钮等关键交互元素
  • SP.primaryDark #8E44AD:深紫,主色的暗色变体(亮度降低约 8%),用于需要降低视觉强度的场景

紫色在美发服务平台中的设计意义深远:紫色是创意和个性的象征,而发型设计本身就是一种创意表达。每位设计师都有自己的风格和个性,每位用户也都有自己的发型偏好和时尚态度。紫色的创意属性与美发行业的创意本质高度契合,让用户在使用 App 时就能感受到平台的创意和时尚氛围。

2.4 辅助强调色

  • SP.accent #F1C40F:明亮金,辅助强调色。这是一种高饱和(约 85%)、高明度(约 60%)的暖黄色。金色象征品质、活力、尊贵与阳光,在美发行业中代表着高品质的服务和产品。用于价格显示、设计师职称、产品品牌、预约已选提示、登录提示等信息元素

金色与紫色是经典的互补色搭配。紫色偏冷,金色偏暖,二者在色轮上相对,形成了强烈而和谐的对比。紫金搭配常见于高端品牌、皇家徽章、时尚设计中,传递着尊贵、创意与品质的复合感受。在美发平台中,紫色用于交互元素(引导操作),金色用于信息元素(展示价值),二者功能分工明确,不会产生视觉冲突。

2.5 文字色系统

  • SP.text #FFFFFF:纯白主文字色,用于标题、服务名称、设计师姓名等核心信息
  • SP.textSub #B0B0B0:中灰次级文字色,约 69% 亮度的灰色,用于描述、时间、分类、地址等次要信息

2.6 功能色

  • SP.chip #3A3A3A:标签背景色,深灰色,用于未选中的分类筛选标签
  • SP.border #444444:边框色,比 chip 色稍亮,用于 Tab 栏顶部分割线、头部底部分割线、菜单项底部分割线等
  • SP.white #FFFFFF:纯白,与 SP.text 相同

2.7 半透明叠加技巧

应用中使用半透明叠加层创建热门标签背景:

  • SP.primary + '33':20% 不透明度的紫色,用于发型卡片的"🔥 热"热门标签背景

半透明紫色标签在深色背景上效果自然柔和,保留了紫色的品牌识别,同时降低了视觉强度,适合用于热门标签等辅助元素。


第三章 架构设计

3.1 整体架构

应用采用经典的 ArkUI 声明式组件化架构,整体结构为"根入口组件 + 头部(条件渲染)+ 内容区 + 底部 Tab 栏"的四层结构。

HairApp(根入口,@Entry)
├── 头部(条件渲染)
│   ├── HomeHeader(首页头部:品牌标识+副标题)
│   └── CommonHeader(通用头部:标题+通知,@Prop title)
├── Stack(内容区,条件渲染,8个内容组件)
│   ├── HomeContent(首页)
│   ├── StylesContent(发型,含分类筛选)
│   ├── BookingContent(预约,含状态管理)
│   ├── DesignerContent(设计师)
│   ├── ProductContent(产品)
│   ├── CommunityContent(社区)
│   ├── CouponContent(优惠)
│   └── MineContent(我的)
└── Row(底部 Tab 栏,8 个 tabItem)

3.2 根入口组件 HairApp

HairApp 是应用的根入口组件,使用 @Entry@Component 装饰器标记。它管理一个全局状态:

  • @State activeTab: number:当前选中的 Tab,使用 MainTab 枚举值,默认为 MainTab.HOME

根组件的 build() 方法构建了 Column 垂直布局,包含三个部分:

  1. 头部(条件渲染):如果当前是首页,渲染 HomeHeader;否则渲染 CommonHeader,通过 getTabTitle(this.activeTab) 获取标题
  2. Stack 内容区:通过 if/else if 条件渲染根据 activeTab 切换 8 个内容组件
  3. Row 底部 Tab 栏:包含 8 个 Tab 项,通过 @Builder tabItem 生成

3.3 双头部设计

应用采用双头部设计:

HomeHeader(首页头部):用于首页 Tab,展示品牌标识。包含品牌 emoji 💇、应用名称"美发沙龙"(紫色加粗 18px)、副标题"剪发 · 烫染 · 护发"(金色 9px)、通知图标 🔔、用户图标 👤。

CommonHeader(通用头部):用于其他 7 个 Tab,展示当前页面标题。通过 @Prop title: string 接收标题参数,左侧显示标题(白色加粗 18px),右侧显示通知图标 🔔。

双头部通过根组件的条件渲染切换,兼顾了首页的品牌展示需求和内页的简洁导航需求。

3.4 getTabTitle 方法与严格模式

getTabTitle(tab: number): string 方法根据 Tab 枚举值返回中文标题,使用 if-else 链实现,避免计算属性名:

getTabTitle(tab: number): string {
  if (tab === MainTab.STYLES) {
    return '发型';
  } else if (tab === MainTab.BOOKING) {
    return '预约';
  }
  // ... 更多 else if
  return '页面';
}

注释中明确提到"无计算属性名",这是 ArkTS 严格模式的核心约束之一。使用 if-else 链替代对象字面量映射,确保代码在严格模式下可正常编译。

3.5 内容区组件

内容区包含 8 个独立组件:

  1. HomeContent(首页):8 快捷入口 + 横向热门发型 + 四列热门设计师 + 社区热帖
  2. StylesContent(发型):分类筛选 chips(全部/男士/女士/儿童)+ 双列发型宫格,管理 selectedCategory 和 styles 两个状态
  3. BookingContent(预约):设计师选择 + 时间段选择 + 确认预约,管理 selectedDesigner 和 selectedSlot 两个状态
  4. DesignerContent(设计师):4 位设计师单列列表
  5. ProductContent(产品):4 款产品双列宫格
  6. CommunityContent(社区):3 条帖子单列列表 + 发帖按钮
  7. CouponContent(优惠):3 张优惠券单列列表 + 立即领取按钮
  8. MineContent(我的):未登录状态 + 5 项菜单

3.6 底部 8 Tab 栏

底部 Tab 栏包含 8 个 Tab:首页 🏠、发型 💇、预约 📅、设计师 👨、产品 🧴、社区 💬、优惠 🎫、我的 👤。

每个 Tab 项通过 @Builder tabItem(icon, label, tab) 生成,包含:

  • 图标 Text(emoji,选中时 scale 1.2 缩放动画,200ms EaseOut)
  • 标签 Text(9px,选中时紫色,未选中时灰色)
  • 底部指示器 Divider(选中时紫色 2px,未选中时透明)

8 个 Tab 在 58px 高的 Tab 栏中平均分配宽度,标签使用 9px 较小字号,确保 8 个 Tab 在手机屏幕宽度内清晰可读。

3.7 组件通信机制

应用的组件通信采用多种机制:

  1. @State(组件内状态):HairApp 的 activeTab,StylesContent 的 selectedCategory 和 styles,BookingContent 的 selectedDesigner 和 selectedSlot 等
  2. @Prop(父子单向传参):CommonHeader 的 title,从父组件接收标题参数
  3. @Builder 自定义构建函数:tabItem、quickItem、categoryChip、menuItem 等封装可复用 UI 片段
  4. 组件方法:getTabTitle 方法在根组件内部调用

应用中没有使用 @Link 双向绑定,因为搜索框等需要双向绑定的组件在这个应用中不存在。预约和发型筛选的状态都在各自组件内部管理,不需要与父组件通信。


第四章 数据模型

4.1 接口定义

应用定义了 7 个核心接口:

interface HairStyle {
  id: number;
  name: string;
  icon: string;
  category: string;      // '男士' | '女士' | '儿童'
  length: string;
  price: number;
  hot: boolean;
}

interface Designer {
  id: number;
  name: string;
  avatar: string;
  title: string;
  rating: number;
  experience: string;
  style: string;
}

interface AppointmentSlot {
  id: number;
  date: string;
  time: string;
  available: boolean;
}

interface Product {
  id: number;
  name: string;
  brand: string;
  icon: string;
  price: number;
  type: string;
}

interface Post {
  id: number;
  user: string;
  avatar: string;
  title: string;
  content: string;
  time: string;
  likes: number;
  comments: number;
}

interface Coupon {
  id: number;
  name: string;
  discount: string;
  validUntil: string;
}

HairStyle(发型):描述一款发型,包含 7 个字段。category 字段使用’男士’/‘女士’/'儿童’三分类,length 字段描述发长(短发/中发/长发),price 字段使用数字类型(因为发型价格都是整数元),hot 字段标记是否热门。

Designer(设计师):描述一位发型师,包含 7 个字段。title 字段描述职称(首席发型师/高级发型师/烫染专家/男士理发师),rating 字段使用数字类型(0-5 分制),experience 字段描述经验年限,style 字段描述擅长风格。

AppointmentSlot(预约时段):描述一个可预约的时间段,包含 4 个字段。date 和 time 字段描述日期和时间,available 字段标记是否可预约(false 表示已被预约)。这个接口是预约系统的核心数据结构。

Product(产品):描述一款洗护造型产品,包含 6 个字段。brand 字段描述品牌(Kérastase/Moroccanoil/Schwarzkopf/Wella),type 字段描述产品类型(洗护/造型/烫染),price 字段使用数字类型。

Post(帖子):描述一条社区帖子,包含 8 个字段。user 和 avatar 字段描述发帖用户,title 和 content 字段描述帖子内容,time 字段描述发帖时间,likes 和 comments 字段描述互动数据。

Coupon(优惠券):描述一张优惠券,包含 4 个字段。name 字段描述优惠券名称,discount 字段描述折扣信息(满100减20/第二件半价/8折优惠),validUntil 字段描述有效期。

4.2 静态数据

应用定义了 6 组静态数据常量:

HAIR_STYLES(发型列表):8 款发型:

  • 男士:经典短发(¥68,热门)、韩式纹理烫(¥188)、寸头(¥58)
  • 女士:长发波浪(¥268,热门)、齐耳短发(¥88)、日系空气刘海(¥128,热门)
  • 儿童:儿童丸子头(¥68)、儿童平头(¥48)

8 款发型中 3 款标记为热门(经典短发、长发波浪、日系空气刘海),覆盖男士、女士、儿童三个分类。

DESIGNERS(设计师列表):4 位设计师:

  • Tony 老师(首席发型师,4.9分,10年经验,韩式剪发)
  • Allen(高级发型师,4.7分,7年经验,日系造型)
  • Lisa(烫染专家,4.8分,8年经验,烫染设计)
  • Kevin(男士理发师,4.6分,5年经验,复古油头)

4 位设计师各有专长,覆盖韩式、日系、烫染、男士等不同风格。

APPOINTMENT_SLOTS(预约时段列表):6 个时段:

  • 2026-08-28:10:00(可约)、11:00(可约)、14:00(不可约)、15:00(可约)
  • 2026-08-29:09:30(可约)、13:00(不可约)

6 个时段中 4 个可约、2 个不可约,模拟了真实预约场景中的时段可用性。

PRODUCTS(产品列表):4 款产品:

  • 滋润洗发水(Kérastase,¥128,洗护)
  • 护发精油(Moroccanoil,¥188,洗护)
  • 定型喷雾(Schwarzkopf,¥68,造型)
  • 烫发修复霜(Wella,¥158,烫染)

4 款产品都是国际知名美发品牌,覆盖洗护、造型、烫染三种类型。

POSTS(帖子列表):3 条帖子:

  • 时尚达人《推荐这款空气刘海,超减龄!》(56赞12评)
  • 发型控《男士短发打理技巧》(34赞8评)
  • 宝妈小惠《儿童第一次理发体验》(27赞5评)

3 条帖子覆盖女士发型、男士造型、儿童理发三个主题,内容实用有趣。

COUPONS(优惠券列表):3 张优惠券:

  • 新客专享(满100减20,有效期至2026-09-30)
  • 烫染特惠(第二件半价,有效期至2026-10-15)
  • 生日礼券(8折优惠,有效期至2026-12-31)

3 张优惠券覆盖新客引流、烫染促销、生日营销三种营销场景。

4.3 数据设计特点

  1. 三分类发型体系:HairStyle 的 category 字段使用’男士’/‘女士’/'儿童’三分类,覆盖了美发服务的主要客群
  2. 价格数字类型:发型和产品的 price 字段使用数字类型(而非字符串),因为价格都是整数元,便于后续计算和排序
  3. 预约时段状态:AppointmentSlot 的 available 字段标记时段是否可约,不可约时段在 UI 中显示为灰色且不可点击
  4. 设计师专长差异化:4 位设计师各有不同的职称、经验和擅长风格,用户可以根据自己的需求选择合适的设计师
  5. 国际品牌产品:4 款产品都是 Kérastase、Moroccanoil、Schwarzkopf、Wella 等国际知名美发品牌,提升了平台的专业感和品质感
  6. 优惠券营销场景:3 张优惠券覆盖新客引流、烫染促销、生日营销三种典型营销场景
  7. 热门标记驱动推荐:通过 hot 布尔字段标记热门发型,首页横向推荐和发型卡片的热门标签都基于此字段

4.4 纯函数工具

应用定义了 1 个纯函数工具:

function genId(): number {
  return Math.floor(Math.random() * 1000000);
}

genId() 生成 0-999999 之间的随机整数,用于新增数据时生成唯一标识。虽然当前应用的静态数据已预定义 ID,但此函数为后续扩展(如用户发帖、添加预约等)提供了基础工具。


第五章 八大 Tab 详解

应用的底部导航包含 8 个 Tab:首页、发型、预约、设计师、产品、社区、优惠、我的。这是目前解析的应用中 Tab 数量最多的之一,覆盖了美发服务的全流程。

5.1 首页:全场景聚合

首页是应用的默认 Tab,包含四个核心模块:

8 个分类快捷入口:Row + @Builder quickItem 生成 8 个快捷入口:发型 💇、预约 📅、设计师 👨、产品 🧴、社区 💬、优惠 🎫、资讯 📖、客服 📞。前 6 个对应底部 Tab 的核心分类,资讯和客服是额外功能入口。

热门发型横向滚动:Scroll 横向滚动展示 HAIR_STYLES.filter(s => s.hot) 的 3 款热门发型(经典短发、长发波浪、日系空气刘海)。每个卡片宽度 110px,包含图标(44px)、名称(12px)、价格(10px 金色)。

热门设计师四列宫格:Flex wrap + SpaceBetween 实现四列宫格,每个卡片宽度 23%,展示 4 位设计师。每个卡片包含头像(32px)、姓名(12px)、职称(9px 金色)、评分(10px 紫色)。四列宫格在有限空间内展示多位设计师,是首页的特色布局。

社区热帖预览:展示 POSTS.slice(0, 2) 的前 2 条帖子。每个帖子卡片包含用户头像、用户名、时间、帖子标题、内容摘要(单行省略)、点赞数和评论数。

首页底部有"— 美丽从头开始 —"的品牌标语。

5.2 发型:分类筛选与双列宫格

发型 Tab 使用独立的 StylesContent 组件,管理两个状态:selectedCategory(当前选中分类,默认’全部’)和 styles(当前显示的发型列表)。

页面顶部显示"💇 发型大全"标题,下方是分类筛选 chips(全部/男士/女士/儿童),通过 @Builder categoryChip(label) 生成。选中的 chip 显示紫色背景+白色文字,未选中的显示 chip 色背景+灰色文字。点击 chip 时更新 selectedCategory 并过滤 styles 数组。

下方是双列宫格(Flex wrap + SpaceBetween,每个卡片宽度 47%),展示当前分类下的发型列表。每个发型卡片包含:图标(40px)、名称(13px)、分类·发长(9px 灰色)、价格(12px 金色)、热门标签(如果 hot 为 true,显示"🔥 热"紫色半透明标签)。

发型 Tab 的分类筛选功能是这个 Tab 的核心亮点,用户可以快速筛选出自己感兴趣的客群分类,浏览对应的发型款式。

美发沙龙发型

5.3 预约:完整预约流程

预约 Tab 使用独立的 BookingContent 组件,管理三个状态:slots(预约时段列表)、selectedDesigner(当前选中设计师 ID,默认 1)、selectedSlot(当前选中时段 ID,默认 -1 表示未选)。

预约流程分为三步:

第一步:选择设计师:页面显示"选择设计师"提示,下方是横向排列的设计师卡片(Row + ForEach)。每个设计师卡片包含头像(28px)和姓名(11px),选中的设计师卡片显示紫色背景,未选中的显示 chip 色背景。点击设计师卡片更新 selectedDesigner。

第二步:选择时间段:页面显示"可选时间段"提示,下方是 Flex wrap 布局的时段标签(左对齐 Start)。每个时段标签显示日期+时间(11px),有三种状态:

  • 已选中:紫色背景+白色文字
  • 可约未选中:浅卡片色背景+白色文字
  • 不可约:chip 色背景+灰色文字,不可点击

点击可约时段更新 selectedSlot,不可约时段点击无响应。

第三步:确认预约:如果 selectedSlot 不为 -1(已选时段),显示已选时段提示(金色文字)和"确认预约"按钮(紫色背景+白色文字,圆角 16)。如果未选时段,显示"请选择时间段"提示(灰色文字)。

预约 Tab 是整个应用中状态管理最复杂的 Tab,实现了设计师选择→时段选择→确认预约的完整流程,包含状态联动和不可约时段处理,是服务类应用预约功能的典型实现。

美发沙龙预约

5.4 设计师:专业团队展示

设计师 Tab 使用独立的 DesignerContent 组件,展示 4 位设计师的单列列表。

每个设计师卡片背景色 SP.cardLight,圆角 10px,包含:

  • 左侧头像(32px,margin right 12px)
  • 中间信息区(layoutWeight 1):
    • 姓名(14px 白色)
    • 职称·经验(10px 灰色)
    • 擅长风格(10px 金色,margin top 2px)
  • 右侧评分(12px 紫色,"⭐ 4.9"格式,通过 d.rating.toFixed(1) 格式化)

单列列表布局适合展示信息较多的设计师条目,用户可以在列表页快速了解每位设计师的职称、经验、擅长风格和评分,做出选择决策。

4 位设计师各有专长:Tony 老师擅长韩式剪发,Allen 擅长日系造型,Lisa 是烫染专家,Kevin 擅长复古油头。用户可以根据自己想要的发型风格选择合适的设计师。

美发沙龙设计师

5.5 产品:洗护造型商城

产品 Tab 使用独立的 ProductContent 组件,展示 4 款洗护造型产品的双列宫格。

每个产品卡片宽度 47%,背景色 SP.card,圆角 10px,包含:

  • 产品图标(36px,居中)
  • 产品名称(13px 白色)
  • 品牌·类型(9px 灰色)
  • 价格(12px 金色,"¥128"格式)

4 款产品都是国际知名美发品牌:Kérastase(卡诗)滋润洗发水、Moroccanoil(摩洛哥油)护发精油、Schwarzkopf(施华蔻)定型喷雾、Wella(威娜)烫发修复霜。覆盖洗护、造型、烫染三种产品类型,价格从 ¥68 到 ¥188 不等。

双列宫格布局适合展示产品,用户可以快速浏览多款产品的外观、品牌和价格,做出购买决策。金色价格在深色背景上醒目突出,引导用户关注产品价值。

美发沙龙产品

5.6 社区:发型经验分享

社区 Tab 使用独立的 CommunityContent 组件,展示 3 条美发经验帖子的单列列表。

每个帖子卡片背景色 SP.cardLight,圆角 10px,包含:

  • 顶部用户信息行:头像(16px)+ 用户名(12px 白色)+ 时间(9px 灰色)
  • 帖子标题(13px 加粗白色)
  • 帖子内容(11px 灰色,maxLines 2 双行省略)
  • 底部互动行:❤️ 点赞数(10px 灰色)+ 💬 评论数(10px 灰色)+ 右侧"发帖"按钮(10px 紫色)

3 条帖子覆盖不同主题:时尚达人分享空气刘海减龄经验、发型控分享男士短发打理技巧、宝妈小惠分享儿童第一次理发体验。内容实用有趣,覆盖了女士、男士、儿童三个客群的发型需求。

社区的"发帖"按钮位于每个帖子卡片的右下角,方便用户随时发布新帖子。紫色的发帖按钮在深色背景上醒目突出,引导用户参与社区互动。

美发沙龙社区

5.7 优惠:优惠券营销

优惠 Tab 使用独立的 CouponContent 组件,展示 3 张优惠券的单列列表。

每张优惠券卡片背景色 SP.cardLight,圆角 10px,包含:

  • 左侧信息区(layoutWeight 1):
    • 优惠券名称(14px 加粗白色)
    • 折扣信息(12px 金色,margin top 2px)
    • 有效期(9px 灰色,margin top 2px)
  • 右侧"立即领取"按钮(11px 白色,紫色背景,圆角 12,padding 左右 12 上下 4)

3 张优惠券覆盖三种营销场景:

  1. 新客专享(满100减20,有效期至2026-09-30):新客引流,吸引首次到店用户
  2. 烫染特惠(第二件半价,有效期至2026-10-15):烫染促销,提升高客单价服务的销量
  3. 生日礼券(8折优惠,有效期至2026-12-31):生日营销,提升用户忠诚度和复购率

优惠券的折扣信息使用金色高亮突出,"立即领取"按钮使用紫色背景,二者形成紫金搭配,既醒目又符合品牌视觉。优惠券营销是美业平台提升用户转化和复购的重要手段。

美发沙龙优惠

5.8 我的:个人中心

我的 Tab 使用独立的 MineContent 组件,展示个人中心页面。

用户信息卡:展示未登录状态。包含圆形头像占位(80px,emoji 👤)、"未登录"文字(16px 加粗白色)、"登录查看我的预约"提示(11px 金色)。金色的登录提示引导用户登录。

菜单列表:包含 5 个菜单项,通过 @Builder menuItem 生成:

  • 📋 我的预约
  • ❤️ 收藏发型
  • 📝 我的评论
  • 🎫 优惠券
  • ⚙️ 设置

每个菜单项包含图标、标签、右箭头,底部有 0.5px 分割线。

底部标语:“— 美丽人生,从’头’开始 —”(10px 灰色),使用双关语"从头开始",既指美发从头发开始,又指美丽人生从现在开始,巧妙传递品牌理念。

我的页面是用户系统的入口,5 个菜单项覆盖了预约管理、收藏、评论、优惠券、设置等个人中心核心功能。虽然当前仅展示未登录状态,但为后续扩展用户登录、预约管理、收藏同步等功能提供了基础框架。


第六章 首页设计:多模块聚合的信息架构

6.1 首页的信息架构

首页是应用的门面,采用多模块聚合的信息架构,从上到下依次包含四个模块:

  1. 8 个分类快捷入口(导航层):一键跳转到核心服务分类
  2. 热门发型横向滚动(推荐层):展示编辑精选的热门发型
  3. 热门设计师四列宫格(内容层):展示平台核心设计师资源
  4. 社区热帖预览(社交层):展示用户分享的发型经验

这种四层信息架构遵循了"导航→推荐→内容→社交"的逻辑顺序,用户从上到下浏览时,先通过快捷入口明确导航方向,再通过热门发型发现精选款式,然后通过设计师了解专业团队,最后通过社区热帖获得社交价值和实用经验。

6.2 8 个分类快捷入口

快捷入口位于首页最顶部,8 个图标通过 Row 水平排列,每个入口通过 .layoutWeight(1) 平均分配宽度。

每个快捷入口通过 @Builder quickItem(icon, label) 生成,包含 emoji 图标(24px)和文字标签(10px 灰色,margin top 2px)。

8 个快捷入口分别是:发型 💇、预约 📅、设计师 👨、产品 🧴、社区 💬、优惠 🎫、资讯 📖、客服 📞。其中前 6 个对应底部 Tab 的核心分类,资讯和客服是额外的功能入口,为后续功能扩展预留了导航位置。

快捷入口的设计价值在于:用户可以在首页一键跳转到任何核心服务分类,不需要先切换到底部 Tab 再寻找入口,提升了导航效率。

6.3 热门发型横向滚动

横向滚动推荐区位于快捷入口下方,使用 Scroll 组件的 ScrollDirection.Horizontal 实现横向滚动。展示 HAIR_STYLES.filter(s => s.hot) 过滤出的 3 款热门发型:经典短发、长发波浪、日系空气刘海。

每个推荐卡片宽度 110px,背景色 SP.cardLight,圆角 12px,内边距 8px,左右 margin 10px。卡片包含:

  • 发型图标(44px,居中,占据卡片主要视觉空间)
  • 发型名称(12px 白色,margin top 4px)
  • 价格(10px 金色)

横向滚动的设计优势:在有限的纵向空间内展示多款发型,用户可以左右滑动浏览;大尺寸图标让发型款式一目了然,金色价格在深色背景上醒目突出。

6.4 热门设计师四列宫格

热门设计师四列宫格是首页的特色布局。使用 Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) 实现四列响应式宫格,每个卡片宽度 23%,展示 4 位设计师。

每个卡片背景色 SP.card,圆角 8px,内边距 6px,margin top 8px。卡片包含:

  • 设计师头像(32px,居中)
  • 设计师姓名(12px 白色,margin top 4px)
  • 职称(9px 金色)
  • 评分(10px 紫色,"⭐ 4.9"格式,margin top 2px)

四列宫格在有限的纵向空间内展示了 4 位设计师,是首页信息密度最高的模块。用户可以快速浏览平台的核心设计师团队,了解每位设计师的姓名、职称和评分。四列布局比双列或单列更节省纵向空间,适合展示头像+姓名+评分这种信息简洁的条目。

6.5 社区热帖预览

社区热帖预览位于设计师宫格下方,展示 POSTS.slice(0, 2) 的前 2 条帖子。

每个帖子卡片背景色 SP.cardLight,圆角 10px,内边距 10px,margin top 8px。卡片结构与社区 Tab 的帖子卡片类似,但内容摘要使用 maxLines 1 单行省略(社区 Tab 使用 maxLines 2 双行省略),因为首页空间有限,需要更紧凑的展示。

社区热帖预览的设计价值:让首页不仅是服务浏览的平台,还具有社交属性,用户可以看到其他用户的发型经验分享,增加了页面的内容丰富度和用户粘性。

6.6 首页设计的平衡之道

首页设计的核心挑战是在有限的屏幕空间内平衡信息密度和可读性。这款应用的首页通过以下方式实现了平衡:

  1. 模块分隔:四个模块之间通过 margin top 自然分隔,每个模块有明确的标题(如"👨 热门设计师"、“💬 社区热帖”),用户可以快速识别模块边界
  2. 布局变化:快捷入口(单行图标)、横向推荐(横向滚动卡片)、设计师(四列宫格)、社区(单列列表)四种布局交替出现,避免了页面单调
  3. 色彩节奏:紫色(标题、评分、按钮)、金色(价格、职称、提示)、白色(标题文字)、灰色(描述文字)在深色背景上形成了有节奏的色彩变化
  4. 留白控制:模块之间、卡片之间、元素之间的 margin 和 padding 控制得当,既保证了信息密度,又不会显得拥挤

首页是用户对应用的第一印象,这款应用的首页通过精心设计的信息架构和布局变化,在一个页面内完整展示了平台的核心功能和内容,为用户提供了清晰的导航和丰富的内容选择。


第七章 预约系统与状态管理

7.1 预约系统的重要性

在线预约是美发服务平台的核心功能之一。传统美发店的预约方式主要是电话预约或到店预约,存在着不方便、不直观、容易出错等问题。用户不知道哪些时段可约、哪些设计师有空,往往需要打电话反复确认。在线预约系统让用户可以在 App 中直观地查看可约时段、选择心仪的设计师、一键确认预约,大幅提升了预约效率和用户体验。

这款应用的预约 Tab 实现了一个完整的在线预约流程,虽然是概念原型(没有真实的后端预约同步),但 UI 层的预约流程已经完整实现,包含了设计师选择、时段选择、确认预约三个核心步骤,以及状态管理、不可约时段处理、已选提示等细节。

7.2 预约流程的三步设计

预约 Tab 的预约流程分为三步:

第一步:选择设计师

用户进入预约 Tab 后,首先看到"选择设计师"提示和横向排列的 4 位设计师卡片。每位设计师卡片包含头像(28px)和姓名(11px),默认选中第一位设计师(Tony 老师,selectedDesigner 默认值为 1)。

设计师卡片的选中态使用紫色背景,未选中态使用 chip 色背景。点击设计师卡片时更新 selectedDesigner 状态,选中态随之切换。

设计师选择是预约流程的第一步,因为不同设计师的可约时段可能不同。在真实应用中,选择设计师后应该加载该设计师的可约时段,但在这个概念原型中,时段列表是固定的 6 个时段,不随设计师变化。

第二步:选择时间段

选择设计师后,用户向下滚动看到"可选时间段"提示和 Flex wrap 布局的时段标签。6 个时段标签左对齐排列(FlexAlign.Start),每个标签显示日期+时间(如"2026-08-28 10:00")。

时段标签有三种视觉状态:

  • 已选中(selectedSlot === s.id):紫色背景 + 白色文字,清晰标示用户当前选择
  • 可约未选中(s.available === true 且未选中):浅卡片色背景 + 白色文字,表示可预约
  • 不可约(s.available === false):chip 色背景 + 灰色文字,表示已被预约,不可点击

点击可约时段时更新 selectedSlot 状态,选中态切换到新时段。不可约时段点击无响应(onClick 中有 if (s.available) 判断)。

这种三态设计让用户可以直观地了解每个时段的状态,避免选择不可约的时段,是预约系统的核心交互设计。

第三步:确认预约

选择时段后,页面底部显示已选时段提示和确认预约按钮:

如果 selectedSlot !== -1(已选时段):

  • 显示"已选:2026-08-28 10:00"提示(12px 金色文字)
  • 显示"确认预约"按钮(14px 白色文字,紫色背景,圆角 16,padding 左右 30 上下 8)

如果 selectedSlot === -1(未选时段):

  • 显示"请选择时间段"提示(12px 灰色文字)
  • 不显示确认按钮

点击"确认预约"按钮时,onClick 回调中有注释"// 模拟预约成功",表示在真实应用中这里会调用后端 API 提交预约请求。

确认预约按钮使用紫色背景,与应用的主强调色一致,在深色背景上醒目突出,引导用户完成预约的最后一步。

7.3 状态管理设计

预约 Tab 管理三个状态:

@State slots: AppointmentSlot[] = APPOINTMENT_SLOTS;
@State selectedDesigner: number = 1;
@State selectedSlot: number = -1;
  • slots:预约时段列表,初始化为 APPOINTMENT_SLOTS 静态数据。在真实应用中,这个列表应该从后端 API 动态获取,根据选中的设计师加载对应的可约时段
  • selectedDesigner:当前选中的设计师 ID,默认值为 1(Tony 老师)。用户点击设计师卡片时更新此状态
  • selectedSlot:当前选中的时段 ID,默认值为 -1(表示未选时段)。用户点击可约时段时更新此状态

三个状态的联动关系:

  1. selectedDesigner 变化 → 设计师卡片选中态切换 →(真实应用中)重新加载 slots
  2. selectedSlot 变化 → 时段标签选中态切换 → 底部显示已选提示和确认按钮(或显示"请选择时间段")
  3. slots 变化 → 时段标签列表重新渲染

这种状态管理设计简洁清晰,每个状态都有明确的职责,状态之间的联动关系明确。在真实应用中,还需要增加预约提交状态(如 loading、success、error)和预约结果展示,但在概念原型中,核心的选择流程已经完整实现。

7.4 已选时段的查找方式

预约 Tab 中显示已选时段时,使用了 filter + 索引访问的方式查找已选时段:

this.slots.filter(s => s.id === this.selectedSlot)[0]?.date

这种方式通过 filter 过滤出 id 等于 selectedSlot 的时段,然后取第一个元素([0]),使用可选链(?.)访问 date 和 time 属性,避免 selectedSlot 为 -1 时出现 undefined 访问错误。

虽然在概念原型中这种方式可以工作,但在真实应用中,更高效的方式是使用 find 方法:this.slots.find(s => s.id === this.selectedSlot),或者将已选时段存储为一个单独的状态变量,避免每次渲染时都进行 filter 查找。

7.5 预约系统的设计价值

预约系统是美发服务平台的核心功能,其设计价值体现在:

  1. 提升预约效率:用户可以在 App 中直观地查看可约时段、选择设计师、一键确认预约,不需要打电话反复确认
  2. 减少到店等待:提前预约让用户可以在约定时间到店直接服务,减少到店等待时间
  3. 优化门店排期:在线预约让门店可以提前了解预约情况,合理安排设计师和工位,提升门店运营效率
  4. 用户体验提升:完整的预约流程(选择设计师→选择时段→确认预约)让用户有掌控感,金色的已选提示和紫色的确认按钮提供了清晰的视觉反馈
  5. 数据收集:在线预约系统可以收集用户的预约偏好、到店时间、消费习惯等数据,为个性化推荐和精准营销提供基础

这款应用的预约 Tab 虽然是概念原型,但完整实现了预约流程的 UI 层和状态管理,为真实美业平台的预约功能开发提供了有价值的参考。


第八章 美发服务生态

8.1 服务分类体系

应用的美发服务分类体系通过 HairStyle 接口的 category 字段和 length 字段构建,形成了二维分类体系:

按客群分类(category)

  • 男士:3 款发型——经典短发、韩式纹理烫、寸头。男士发型以简洁、利落、有型为主,价格从 ¥58 到 ¥188 不等。经典短发和寸头是基础剪发,韩式纹理烫是烫发服务,价格较高。
  • 女士:3 款发型——长发波浪、齐耳短发、日系空气刘海。女士发型以变化丰富、时尚个性为主,价格从 ¥88 到 ¥268 不等。长发波浪是烫卷服务,价格最高;齐耳短发是基础剪发;日系空气刘海是刘海造型。
  • 儿童:2 款发型——儿童丸子头、儿童平头。儿童发型以可爱、易打理为主,价格从 ¥48 到 ¥68 不等,是所有分类中价格最低的。

按发长分类(length)

  • 短发:经典短发、寸头、齐耳短发、儿童平头,共 4 款
  • 中发:韩式纹理烫、日系空气刘海,共 2 款
  • 长发:长发波浪、儿童丸子头,共 2 款

这种二维分类体系让用户可以从客群和发长两个维度筛选发型,快速找到适合自己的款式。在发型 Tab 中,目前实现了按客群分类的筛选(全部/男士/女士/儿童),按发长分类可以作为后续扩展功能。

8.2 美发服务的价格体系

应用的美发服务价格从 ¥48 到 ¥268 不等,形成了清晰的价格梯队:

基础剪发(¥48-¥88)

  • 儿童平头 ¥48(最低价)
  • 寸头 ¥58
  • 经典短发 ¥68
  • 儿童丸子头 ¥68
  • 齐耳短发 ¥88

基础剪发是美发店的核心基础服务,价格亲民,覆盖男士、女士、儿童三个客群,是客流量最大的服务项目。

造型烫染(¥128-¥268)

  • 日系空气刘海 ¥128
  • 韩式纹理烫 ¥188
  • 长发波浪 ¥268(最高价)

造型烫染是美发店的高客单价服务,技术含量高,耗时较长,是美发店的主要利润来源。价格从 ¥128 到 ¥268,根据发型复杂度和用发量不同而差异较大。

这种价格体系设计符合真实美发店的定价逻辑:基础剪发价格亲民、客流量大,起到引流作用;造型烫染价格较高、利润空间大,是主要盈利来源。用户可以根据自己的预算和需求选择合适的服务。

8.3 热门发型的推荐逻辑

应用通过 hot: boolean 字段标记热门发型,共有 3 款热门发型:经典短发(男士)、长发波浪(女士)、日系空气刘海(女士)。

热门发型在两个位置展示:

  1. 首页横向滚动推荐HAIR_STYLES.filter(s => s.hot) 过滤出热门发型,横向滚动展示
  2. 发型卡片热门标签:在发型 Tab 的双列宫格中,热门发型卡片显示"🔥 热"紫色半透明标签

热门发型的筛选逻辑简单清晰:通过手动标记 hot 字段,由内容运营人员根据发型的受欢迎程度和时效性动态调整。新发型上线时可以标记为热门,过时发型可以取消热门标记。

3 款热门发型覆盖了男士和女士两个客群,其中女士有 2 款(长发波浪、日系空气刘海),男士有 1 款(经典短发)。这种分布反映了美发市场中女士发型变化更丰富、热门款式更多的实际情况。

在真实美发平台中,热门推荐的逻辑会更复杂,通常综合考虑以下因素:

  • 预约量/选择次数
  • 用户评分/好评率
  • 设计师推荐
  • 上新时间/时效性
  • 编辑推荐/运营加权
  • 用户个性化偏好

概念应用简化为手动 hot 标记,为理解推荐系统的基本原理提供了清晰的入口。

8.4 美发服务的完整生态

这款应用的美发服务生态虽然只有 8 款发型,但已经覆盖了美发服务的核心环节:

  • 剪发:经典短发、寸头、齐耳短发、儿童平头——基础剪发服务
  • 烫发:韩式纹理烫、长发波浪——烫发造型服务
  • 刘海造型:日系空气刘海——局部造型服务
  • 儿童造型:儿童丸子头、儿童平头——儿童美发服务
  • 洗护产品:滋润洗发水、护发精油、定型喷雾、烫发修复霜——居家洗护产品
  • 设计师服务:Tony 老师、Allen、Lisa、Kevin——专业设计师团队
  • 预约服务:在线预约系统——便捷预约通道
  • 社区交流:发型经验分享——用户互助社区
  • 优惠营销:优惠券——促销引流手段

这 9 个环节构成了从发现发型→选择设计师→在线预约→到店服务→购买产品→社区分享→优惠复购的完整美发服务闭环。用户可以在一个平台上完成美发服务的全流程,不需要在多个平台之间切换。

在真实的美发服务平台中,服务生态会更加丰富,包括但不限于:染发、护发、头皮护理、接发、编发、化妆、美甲、SPA 等更多服务项目,以及会员体系、积分商城、储值卡、次卡等更多营销手段。这款应用的服务分类体系为后续扩展更多服务提供了清晰的骨架。


第九章 设计师与产品资源

9.1 设计师团队建设

设计师是美发店的核心资产,设计师的技术水平和服务态度直接影响用户的满意度和复购率。应用的设计师列表包含 4 位发型师,各有不同的专长和定位:

Tony 老师(首席发型师,4.9分,10年经验,韩式剪发):

  • 职称最高(首席发型师),经验最丰富(10年),评分最高(4.9分)
  • 擅长韩式剪发,适合喜欢韩式风格的用户
  • 是平台的招牌设计师,预约价格可能最高

Allen(高级发型师,4.7分,7年经验,日系造型):

  • 职称高级,经验 7 年,评分 4.7 分
  • 擅长日系造型,适合喜欢日系清新风格的用户
  • 是平台的中坚力量设计师

Lisa(烫染专家,4.8分,8年经验,烫染设计):

  • 职称烫染专家,经验 8 年,评分 4.8 分
  • 专注烫染领域,适合需要烫发染发服务的用户
  • 是平台的专项技术专家

Kevin(男士理发师,4.6分,5年经验,复古油头):

  • 职称男士理发师,经验 5 年(最少),评分 4.6 分(最低)
  • 专注男士理发,擅长复古油头,适合男士用户
  • 是平台的新锐设计师

4 位设计师形成了清晰的梯队:首席(Tony)→ 高级(Allen)→ 专家(Lisa)→ 新锐(Kevin),覆盖了不同职称、不同经验、不同擅长风格的设计师。用户可以根据自己的预算、发型需求和风格偏好选择合适的设计师。

9.2 设计师信息展示

设计师列表采用单列卡片布局,每个卡片展示以下信息:

  • 头像(32px emoji):设计师的视觉标识,使用 emoji 占位
  • 姓名(14px 白色加粗):设计师姓名,是卡片中最醒目的信息
  • 职称·经验(10px 灰色):如"首席发型师 · 10年经验",让用户快速了解设计师的资历
  • 擅长风格(10px 金色,margin top 2px):如"擅长: 韩式剪发",金色文字在深色背景上醒目突出,让用户快速了解设计师的专长
  • 评分(12px 紫色,右侧):如"⭐ 4.9",通过 d.rating.toFixed(1) 格式化为一位小数,紫色评分与品牌主色一致

这种信息展示方式让用户在列表页就能获取设计师的核心信息(姓名、职称、经验、擅长、评分),不需要点击进入详情页,提升了决策效率。

在真实美发平台中,设计师信息还会包括:设计师照片、作品集、用户评价、可约时段、服务价格、个人简介等更详细的信息。概念应用简化为核心信息展示,为设计师详情页的设计提供了基础。

9.3 洗护造型产品

应用的产品商城包含 4 款洗护造型产品,都是国际知名美发品牌:

Kérastase(卡诗)滋润洗发水(¥128,洗护):

  • 卡诗是欧莱雅集团旗下的高端美发品牌,以专业护发著称
  • 滋润洗发水适合干枯发质,是基础洗护产品

Moroccanoil(摩洛哥油)护发精油(¥188,洗护):

  • 摩洛哥油是以摩洛哥坚果油为核心成分的知名护发品牌
  • 护发精油是热销产品,适合所有发质,价格最高(¥188)

Schwarzkopf(施华蔻)定型喷雾(¥68,造型):

  • 施华蔻是汉高集团旗下的专业美发品牌
  • 定型喷雾是造型产品,适合需要持久定型的用户,价格最低(¥68)

Wella(威娜)烫发修复霜(¥158,烫染):

  • 威娜是宝洁旗下的专业美发品牌
  • 烫发修复霜是烫染后护理产品,适合刚烫完头发需要修复的用户

4 款产品覆盖洗护(2款)、造型(1款)、烫染(1款)三种类型,价格从 ¥68 到 ¥188 不等,都是国际知名品牌。这种产品选择体现了平台的专业性和品质感——只推荐经过市场验证的知名品牌产品,让用户放心购买。

9.4 产品信息展示

产品列表采用双列宫格布局,每个卡片展示以下信息:

  • 产品图标(36px emoji,居中):产品的视觉标识
  • 产品名称(13px 白色):如"滋润洗发水"
  • 品牌·类型(9px 灰色):如"Kérastase · 洗护",让用户快速了解产品品牌和类型
  • 价格(12px 金色):如"¥128",金色价格在深色背景上醒目突出

双列宫格布局适合展示产品,用户可以快速浏览多款产品的外观、品牌和价格。国际品牌名称(Kérastase、Moroccanoil 等)提升了产品的专业感和可信度,金色价格引导用户关注产品价值。

在真实美发平台中,产品信息还会包括:产品图片、详细描述、成分说明、适用发质、使用方法、用户评价、库存状态、相关推荐等更详细的信息。概念应用简化为核心信息展示,为产品详情页的设计提供了基础。

9.5 设计师与产品的协同价值

设计师和产品是美发服务平台的两大核心资源,二者的协同价值体现在:

  1. 设计师推荐产品:设计师在服务过程中可以根据用户的发质和需求推荐合适的洗护造型产品,提升产品销量
  2. 产品提升服务效果:用户购买合适的洗护产品在家使用,可以延长美发服务的效果,提升用户满意度
  3. 设计师作品展示:设计师可以使用平台产品打造作品,展示在设计师作品集中,提升设计师的专业形象
  4. 套餐组合销售:平台可以推出"剪发+洗护产品"、"烫染+修复产品"等套餐,将设计师服务和产品组合销售,提升客单价
  5. 数据协同:用户的发型选择、设计师偏好、产品购买等数据可以协同分析,为个性化推荐提供更精准的依据

这款应用虽然没有实现设计师和产品的深度协同,但在同一个平台中展示了设计师和产品两大资源,为后续的协同功能开发提供了基础架构。


第十章 社区与优惠营销

10.1 社区的价值定位

社区是美发服务平台的重要组成部分。与电商平台的"商品+评价"模式不同,美发服务具有很强的经验属性和社交属性——用户在选择发型和设计师时,往往需要参考其他用户的真实经验和效果展示。社区正是为满足这一需求而存在的。

美发社区的价值体现在:

  1. 经验分享:用户可以分享自己的发型经验、打理技巧、踩坑教训,帮助其他用户少走弯路
  2. 效果展示:用户可以展示自己的发型效果,为其他用户提供真实的参考(比商家宣传图更有说服力)
  3. 问答互助:用户可以在社区提问,其他有经验的用户和设计师可以回答,形成互助社区
  4. 潮流趋势:社区中流行的发型和话题可以反映当前的美发潮流趋势,为用户提供时尚参考
  5. 用户粘性:社区互动(发帖、评论、点赞、关注)增加了用户的使用频率和停留时间,提升了用户粘性
  6. 口碑传播:优质的社区内容和良好的用户体验会促使用户自发传播,带来新用户

10.2 社区帖子内容分析

应用的社区列表包含 3 条帖子,覆盖不同主题和客群:

《推荐这款空气刘海,超减龄!》 by 时尚达人(2026-08-25,56赞12评):

  • 内容摘要:“剪了Lisa同款,朋友都说像换了个人…”
  • 主题:女士发型推荐,具体是空气刘海造型
  • 特点:标题使用感叹号和"超减龄"等吸引眼球的词汇,内容提到"Lisa同款"(暗示是设计师 Lisa 的作品),具有很强的种草效果
  • 互动数据最高(56赞12评),反映了女士发型话题的高关注度

《男士短发打理技巧》 by 发型控(2026-08-22,34赞8评):

  • 内容摘要:“用发蜡和吹风机,三分钟搞定…”
  • 主题:男士造型教程,具体是短发打理技巧
  • 特点:内容实用,提供了具体的打理方法(发蜡+吹风机,三分钟),对男士用户有很强的参考价值
  • 互动数据中等(34赞8评)

《儿童第一次理发体验》 by 宝妈小惠(2026-08-18,27赞5评):

  • 内容摘要:“造型师很有耐心,宝宝没哭…”
  • 主题:儿童理发体验分享
  • 特点:内容温馨,提到"造型师很有耐心,宝宝没哭",对有孩子的宝妈用户有很强的参考价值和情感共鸣
  • 互动数据最低(27赞5评),反映了儿童理发话题的相对小众

3 条帖子覆盖女士、男士、儿童三个客群,内容类型包括发型推荐、造型教程、体验分享三种,形成了多样化的社区内容生态。每条帖子都有具体的内容和实用的信息,不是空洞的灌水帖,体现了社区内容的质量。

10.3 社区帖子的信息展示

社区帖子采用单列卡片布局,每个卡片展示以下信息:

  • 用户信息行:头像(16px emoji)+ 用户名(12px 白色)+ 发帖时间(9px 灰色)
  • 帖子标题(13px 加粗白色):帖子的核心信息,是卡片中最醒目的内容
  • 帖子内容(11px 灰色,maxLines 2 双行省略):帖子的详细内容,让用户快速了解帖子要点
  • 互动行:❤️ 点赞数(10px 灰色)+ 💬 评论数(10px 灰色)+ 右侧"发帖"按钮(10px 紫色)

社区 Tab 的帖子内容使用 maxLines 2 双行省略(首页预览使用 maxLines 1 单行省略),因为社区 Tab 是内容的主要展示页面,可以展示更多内容。"发帖"按钮位于每个帖子卡片的右下角,方便用户随时发布新帖子。

在真实美发社区中,帖子信息还会包括:帖子图片/视频、话题标签、位置信息、收藏数、转发数、评论列表等更丰富的信息。概念应用简化为核心信息展示,为社区功能的扩展提供了基础。

10.4 优惠券营销体系

优惠券是美发服务平台的重要营销工具,用于新客引流、促销转化、复购激励等场景。应用的优惠 Tab 包含 3 张优惠券,覆盖三种典型营销场景:

新客专享(满100减20,有效期至2026-09-30)

  • 营销目标:新客引流,吸引首次到店的用户
  • 优惠形式:满减(满100元减20元),门槛适中,大部分美发服务都能达到
  • 有效期:约 1 个月(到 2026-09-30),营造紧迫感,促使用户尽快使用
  • 设计要点:"新客专享"名称明确标识目标用户,金色的"满100减20"折扣信息醒目突出

烫染特惠(第二件半价,有效期至2026-10-15)

  • 营销目标:烫染促销,提升高客单价服务的销量
  • 优惠形式:第二件半价,鼓励用户同时购买两项烫染服务(如烫发+染发),提升客单价
  • 有效期:约 1.5 个月(到 2026-10-15)
  • 设计要点:"烫染特惠"名称明确标识促销品类,"第二件半价"是有吸引力的优惠形式

生日礼券(8折优惠,有效期至2026-12-31)

  • 营销目标:生日营销,提升用户忠诚度和复购率
  • 优惠形式:8折优惠,折扣力度大,让用户在生日月享受特别优惠
  • 有效期:较长(到 2026-12-31),给用户充足的使用时间
  • 设计要点:"生日礼券"名称传递专属感和关怀感,"8折优惠"是有吸引力的折扣

3 张优惠券形成了完整的营销体系:新客专享(引流)→ 烫染特惠(转化)→ 生日礼券(复购),覆盖了用户生命周期的不同阶段。这种优惠券设计体现了美业营销的核心逻辑:通过不同类型的优惠券,在用户生命周期的不同阶段施加影响,实现引流、转化、复购的营销目标。

10.5 优惠券的信息展示

优惠券采用单列卡片布局,每张卡片展示以下信息:

  • 左侧信息区(layoutWeight 1):
    • 优惠券名称(14px 加粗白色):如"新客专享"
    • 折扣信息(12px 金色,margin top 2px):如"满100减20",金色高亮突出
    • 有效期(9px 灰色,margin top 2px):如"有效期至 2026-09-30"
  • 右侧"立即领取"按钮(11px 白色,紫色背景,圆角 12,padding 左右 12 上下 4)

优惠券的信息展示简洁清晰,用户可以快速了解优惠券的名称、折扣、有效期,并通过"立即领取"按钮一键领取。金色的折扣信息和紫色的领取按钮形成紫金搭配,既醒目又符合品牌视觉。

在真实美发平台中,优惠券还会包括:使用条件(如限新用户、限指定服务)、使用说明、已领取状态、使用记录等更详细的信息。概念应用简化为核心信息展示,为优惠券功能的扩展提供了基础。

10.6 社区与优惠的协同营销

社区和优惠券是美发平台的两大营销工具,二者可以协同发挥更大的价值:

  1. 社区种草+优惠转化:用户在社区看到其他用户的发型经验分享(种草),产生到店消费的意愿,此时平台推送相关优惠券,促进用户转化
  2. 优惠活动+社区传播:平台推出优惠活动后,用户可以在社区分享优惠信息和使用体验,形成口碑传播,扩大优惠活动的影响力
  3. 社区内容+精准优惠:根据用户在社区的浏览和互动数据,分析用户的发型偏好和消费需求,精准推送相关的优惠券(如经常浏览烫发帖子的用户推送烫染特惠券)
  4. KOL 社区+专属优惠:邀请社区中的发型达人(KOL)发布专属优惠码,粉丝使用优惠码到店消费,KOL 获得佣金,形成社区 KOL 营销闭环
  5. 用户生成内容+优惠激励:通过优惠券激励用户在社区发布发型体验帖子(如"发布发型体验帖即可获得 20 元优惠券"),丰富社区内容的同时提升用户粘性

社区和优惠的协同营销是美业平台的高级运营手段,概念应用虽然没有实现这些协同功能,但在同一个平台中展示了社区和优惠两大模块,为后续的协同营销开发提供了基础架构。


第十一章 美发文化与时尚趋势

11.1 美发文化的历史演变

美发是人类最古老的美容行为之一,其历史可以追溯到数千年前。从古埃及人的假发和染发剂,到古希腊人的卷发造型,从中国古代的发髻和簪花,到欧洲中世纪的头饰文化,美发始终是人类表达身份、地位、审美和个性的重要方式。

进入现代社会后,美发行业经历了几次重大变革:

  1. 20 世纪初:理发店开始专业化,男士理发和女士美发逐渐分化,电烫技术的发明让普通女性也能拥有卷发造型
  2. 20 世纪中期:美发产品工业化,洗发水、护发素、发胶、染发剂等产品大规模生产,美发从专业沙龙走向家庭日常
  3. 20 世纪后期:发型潮流多元化,朋克、嬉皮、摇滚、嘻哈等亚文化催生了各种个性发型,美发成为年轻人表达自我的重要方式
  4. 21 世纪:互联网和社交媒体的兴起让发型潮流传播更快,日韩风格、欧美风格、复古风格等各种发型在社交媒体上快速流行,用户可以通过手机随时获取发型灵感

这款应用的美发服务生态反映了当代美发文化的特点:发型款式多元化(男士/女士/儿童,短发/中发/长发,剪发/烫发/造型)、设计师专业化(不同设计师有不同的擅长风格)、产品品牌化(国际知名品牌的洗护造型产品)、社区社交化(用户分享发型经验和效果)。

11.2 日韩风格的流行

应用的设计师团队中,Tony 老师擅长韩式剪发,Allen 擅长日系造型,反映了当前中国美发市场中日韩风格的流行趋势。

韩式风格的特点:

  • 男士:韩式纹理烫、韩式中分、韩式逗号刘海,自然蓬松,有层次感
  • 女士:韩式空气刘海、韩式大波浪、韩式低马尾,温柔甜美,有氛围感
  • 特点:自然、蓬松、有空气感,不刻意,适合日常

日系风格的特点:

  • 男士:日系短发、日系狼尾、日系蘑菇头,个性鲜明,有设计感
  • 女士:日系短发、日系丸子头、日系编发,清新可爱,有少女感
  • 特点:清新、个性、有设计感,适合追求独特风格的用户

日韩风格在中国的流行得益于韩剧、日剧、K-pop、J-pop 等日韩流行文化的广泛传播。年轻人通过韩剧和日剧看到主角的发型,产生模仿意愿,推动了日韩风格在美发市场的流行。应用中将韩式和日系作为设计师的主要擅长风格,正是对这一市场趋势的反映。

11.3 烫染服务的高价值

应用的发型列表中,烫染服务的价格明显高于基础剪发:长发波浪 ¥268(最高价)、韩式纹理烫 ¥188,而基础剪发价格在 ¥48-¥88 之间。这种价格差异反映了烫染服务在美发店中的高价值地位。

烫染服务高价值的原因:

  1. 技术含量高:烫发和染发需要专业的技术和经验,不同发质、不同目标效果需要不同的操作方案,技术门槛高
  2. 耗时长:一次烫发或染发通常需要 2-4 小时,远长于基础剪发的 30-60 分钟,占用设计师和工位的时间更长
  3. 产品成本高:烫发水、染发剂等专业产品成本较高,高端品牌的产品成本更高
  4. 效果持久:烫染效果可以维持 2-6 个月,用户愿意为持久的造型效果支付更高价格
  5. 体验感强:烫染过程中用户可以享受头部按摩、护理等附加服务,体验感更强

烫染服务是美发店的主要利润来源,也是设计师技术水平的核心体现。应用中 Lisa 作为"烫染专家",评分 4.8 分,经验 8 年,体现了烫染设计师在团队中的重要地位。产品列表中的"烫发修复霜"(Wella,¥158)则是烫染后的配套护理产品,形成了"烫染服务+修复产品"的完整服务链。

11.4 儿童美发的细分市场

应用的发型列表中有 2 款儿童发型(儿童丸子头 ¥68、儿童平头 ¥48),设计师团队中虽然没有专门的儿童理发师,但社区中有"儿童第一次理发体验"的帖子,反映了儿童美发这一细分市场的存在。

儿童美发市场的特点:

  1. 价格较低:儿童发型价格(¥48-¥68)低于成人发型,因为儿童发型相对简单,耗时较短
  2. 需要耐心:儿童(尤其是幼儿)理发时容易哭闹、不配合,需要设计师有足够的耐心和技巧
  3. 家长决策:儿童美发的决策者是家长,家长更关注安全性、卫生性和设计师的耐心程度
  4. 情感价值高:儿童第一次理发是重要的成长纪念,家长愿意记录和分享,社区中"儿童第一次理发体验"的帖子正是这种情感价值的体现
  5. 复购率高:儿童头发生长快,需要定期理发,复购率高于成人

儿童美发是美发市场中一个稳定且有潜力的细分市场。应用中虽然只有 2 款儿童发型和 1 条相关帖子,但已经覆盖了儿童美发的基本需求,为后续扩展儿童美发专区(如儿童专属设计师、儿童洗护产品、儿童理发纪念服务等)提供了基础。

11.5 美发产品的品牌化趋势

应用的产品列表中 4 款产品都是国际知名品牌:Kérastase(卡诗,法国)、Moroccanoil(摩洛哥油,以色列)、Schwarzkopf(施华蔻,德国)、Wella(威娜,德国)。这种全国际品牌的产品选择反映了当前美发产品市场的品牌化趋势。

美发产品品牌化的原因:

  1. 专业背书:国际专业美发品牌在美发行业中有长期的专业积累和良好的口碑,用户更信任专业品牌的产品
  2. 效果保障:知名品牌的产品经过严格的研发和测试,效果和安全性更有保障
  3. 体验感好:知名品牌的产品在香味、质地、使用感等方面更优秀,用户体验更好
  4. 社交属性:使用知名品牌的洗护产品具有一定的社交属性,用户愿意在社区分享
  5. 溢价能力:知名品牌的产品价格更高,利润空间更大,美发店更愿意推荐

应用中 4 款产品的价格从 ¥68 到 ¥188 不等,都是中高端价位,体现了平台的品质定位。在真实美发平台中,产品列表会更加丰富,包括不同价位、不同品牌、不同功效的更多产品选择,满足不同用户的需求。

11.6 美发行业的未来趋势

展望未来,美发行业的发展趋势包括:

  1. 数字化预约:在线预约系统将成为美发店的标配,用户可以随时查看可约时段、选择设计师、在线预约,减少到店等待
  2. AI 发型试戴:通过 AR/AI 技术,用户可以在手机上虚拟试戴不同发型,预览效果后再决定,降低试错成本
  3. 个性化推荐:基于用户的脸型、发质、风格偏好、历史消费等数据,AI 智能推荐适合的发型和设计师
  4. 居家美发产品升级:随着消费者对美发护理的重视,居家洗护造型产品市场将持续增长,产品更加细分和专业化
  5. 可持续美发:环保、无动物实验、天然成分的美发产品将受到更多关注,可持续美发成为新趋势
  6. 男性美发市场增长:男性对形象管理的重视程度提升,男士美发市场将持续增长,男士专属理发店和男士护理产品将更加丰富
  7. 社区化运营:美发店将更加重视社区运营,通过发型分享、用户评价、设计师 IP 等方式建立用户社区,提升用户粘性
  8. 健康美发理念:头皮护理、防脱生发、烫染修复等健康美发理念将受到更多关注,健康成为美发的新卖点

这款应用作为概念原型,已经涵盖了在线预约、发型浏览、设计师展示、产品商城、社区交流、优惠营销等核心功能,为美发行业的数字化转型提供了有价值的参考。


第十二章 美业服务平台趋势

12.1 美业服务平台化的行业趋势

近年来,美业服务的平台化已经成为不可逆转的趋势。从美团、大众点评的综合生活服务平台,到新氧、更美等医美垂直平台,到河狸家、美丽修行等美业服务平台,平台化正在重塑美业服务的各个细分领域。美发作为美业中最大的细分市场,也正在经历平台化的变革。

美业服务平台化的核心价值在于:

  1. 信息透明化:平台将分散的美发店信息、设计师信息、服务价格、用户评价等聚合在一起,用户可以在一个平台上透明地比较和选择,消除信息不对称
  2. 预约在线化:平台提供在线预约系统,用户可以随时查看可约时段、在线预约,不需要打电话或到店预约,提升了预约效率
  3. 服务标准化:平台通过服务标准、评价体系、质量监控等机制,推动美发店服务的标准化,降低用户的决策风险
  4. 营销数字化:平台提供优惠券、团购、会员、积分等数字化营销工具,帮助美发店精准获客和提升复购
  5. 数据资产化:平台积累的用户消费数据、偏好数据、评价数据等成为宝贵的数据资产,可以用于个性化推荐、精准营销、行业分析等

美发服务平台化的驱动力来自供需两端:供给端(美发店)需要获客渠道、预约管理、营销工具、数据洞察;需求端(用户)需要透明信息、便捷预约、品质保障、优惠价格。平台通过连接供需两端,创造了双向价值。

12.2 垂直平台与综合平台的竞争

在美业服务平台化的进程中,垂直平台和综合平台之间存在竞争:

综合平台(美团、大众点评等):

  • 优势:流量大、用户多、覆盖广、技术实力强、资金充足、支付和评价体系完善
  • 劣势:对美发垂直行业的理解不够深入,服务标准化程度低,用户体验不够专业,美发店的获客成本越来越高

垂直平台(美发专属 App 等):

  • 优势:对美发行业理解深入,服务标准化程度高,用户体验专业,可以提供发型试戴、设计师 IP、社区交流等综合平台没有的特色功能
  • 劣势:流量小、用户少、获客成本高、技术实力和资金相对较弱

这款美发沙龙应用属于垂直平台,聚焦美发服务领域。垂直平台的核心竞争力在于对行业的深度理解和专业化的用户体验。美发服务具有很强的专业性(发型设计、烫染技术、发质护理等),综合平台难以提供足够专业的服务体验,这为垂直平台留下了发展空间。

未来的趋势可能是综合平台与垂直平台的合作与融合:综合平台提供流量和支付基础设施,垂直平台提供专业的服务内容和用户体验,双方通过 API 对接、投资并购等方式合作共赢。

12.3 设计师 IP 化的趋势

设计师是美发店的核心资产,设计师 IP 化是美业平台的重要趋势。设计师 IP 化是指将设计师打造为具有个人品牌和粉丝基础的 IP,通过设计师的个人影响力吸引用户和提升复购。

设计师 IP 化的要素:

  1. 个人形象:设计师有独特的个人形象和风格标签(如"韩式剪发专家"、“复古油头匠人”),让用户容易记住和识别
  2. 作品展示:设计师有丰富的作品集,展示自己的技术水平和审美风格,让用户直观了解设计师的能力
  3. 粉丝积累:设计师通过社区、社交媒体等渠道积累粉丝,粉丝因为信任设计师而选择到店消费
  4. 内容输出:设计师定期输出发型教程、护理知识、趋势解读等专业内容,建立专业权威形象
  5. 用户评价:设计师有大量的真实用户评价和好评,建立口碑信任

应用的设计师列表中,每位设计师都有明确的职称(首席发型师/高级发型师/烫染专家/男士理发师)、经验年限、擅长风格和评分,这些都是设计师 IP 的基础要素。在真实平台中,设计师 IP 还会包括个人照片、作品集、粉丝数、内容输出、直播等更丰富的 IP 元素。

设计师 IP 化的价值在于:用户因为信任设计师而选择到店,设计师的粉丝成为稳定的客源,设计师的个人品牌提升了美发店的溢价能力。平台可以通过设计师 IP 化提升用户粘性和平台价值。

12.4 社区化运营的趋势

社区化运营是美业平台的另一个重要趋势。传统的美业平台主要是"信息展示+在线预约"的工具型平台,用户用完即走,粘性低。社区化运营通过用户生成内容(UGC)、互动交流、话题讨论等方式,将平台从工具升级为社区,提升用户粘性和使用时长。

美业社区的内容类型:

  1. 发型分享:用户分享自己的新发型、染发效果、烫发体验,附前后对比图,是最受欢迎的内容类型
  2. 经验教程:用户分享发型打理技巧、护发心得、产品使用体验,具有很强的实用价值
  3. 探店评价:用户分享美发店探店体验、设计师服务评价、价格对比,帮助其他用户选择
  4. 问答求助:用户提问关于发型选择、发质问题、产品推荐等,其他用户和设计师回答
  5. 潮流讨论:用户讨论当季流行发型、发色趋势、明星同款等时尚话题

应用的社区列表中有 3 条帖子,覆盖发型推荐(空气刘海)、经验教程(男士短发打理)、体验分享(儿童第一次理发)三种内容类型,已经具备了美业社区的基本内容生态。

社区化运营的价值在于:

  • 提升用户粘性:用户因为社区内容而频繁访问平台,使用时长增加
  • 降低获客成本:优质的社区内容可以通过社交分享带来自然流量,降低付费获客成本
  • 提升转化率:用户在社区被种草后更容易转化为到店消费,社区内容成为天然的营销素材
  • 数据资产:社区内容反映了用户的发型偏好、消费需求、痛点问题,是宝贵的数据资产

12.5 私域运营与会员体系

私域运营和会员体系是美业平台提升用户复购和 Lifetime Value(LTV)的重要手段。

私域运营

  • 美发店通过企业微信、微信群、小程序等渠道将用户沉淀到私域
  • 在私域中进行个性化服务、优惠推送、预约提醒、节日问候等
  • 私域用户的复购率和客单价通常高于公域用户

会员体系

  • 会员等级:普通会员、银卡会员、金卡会员、钻石会员等,不同等级享受不同权益
  • 积分系统:消费获得积分,积分可以兑换产品、服务、优惠券等
  • 储值卡:用户预存储值金额,享受折扣和专属服务
  • 次卡:用户购买多次服务卡(如 10 次剪发卡),享受优惠价格
  • 专属权益:会员专属发型师、会员专属产品、会员专属活动、生日礼遇等

应用的优惠 Tab 中有 3 张优惠券(新客专享、烫染特惠、生日礼券),我的页面中有"优惠券"菜单项,这些都是会员营销体系的基础元素。在真实平台中,会员体系会更加完善,包括会员等级、积分系统、储值卡、次卡、专属权益等完整的会员营销体系。

私域运营和会员体系的核心目标是提升用户复购率和 LTV。美发服务是高频消费(用户平均每 1-2 个月理发一次),通过私域运营和会员体系将用户沉淀为长期客户,可以大幅提升用户的 LTV 和平台的盈利能力。

12.6 技术驱动的美业升级

技术正在驱动美业行业的升级:

  1. AI 发型推荐:基于用户的脸型、发质、肤色、风格偏好等数据,AI 智能推荐适合的发型,降低用户的选择成本
  2. AR 虚拟试戴:通过 AR 技术,用户可以在手机上虚拟试戴不同发型和发色,预览效果后再决定,降低试错成本
  3. 智能预约系统:基于历史预约数据和实时客流,智能推荐最佳预约时段,减少用户等待时间,提升门店运营效率
  4. 数字化客户管理:通过 CRM 系统记录用户的发质、过敏史、消费记录、偏好等信息,设计师可以提供更个性化的服务
  5. 智能库存管理:通过销售数据预测产品需求,智能管理洗护产品库存,减少库存积压和缺货
  6. 线上教育平台:为美发师提供在线教育平台,包含技术教程、趋势解读、考试认证等,提升行业整体技术水平
  7. 供应链数字化:通过数字化供应链管理,优化美发产品的采购、仓储、配送流程,降低供应链成本

这些技术应用正在改变美发行业的传统模式,让服务更加透明、高效、个性化。这款应用虽然是一个概念原型,但其平台化的架构(在线预约、发型浏览、设计师展示、产品商城、社区交流、优惠营销)为技术驱动的美业升级提供了基础框架。


第十三章 深色模式与时尚感

13.1 深色模式在美业应用中的适用性

深色模式最初在内容消费类应用(视频、阅读、图片)中广泛应用,近年来逐渐扩展到生活服务类应用,包括美业服务平台。对于美发沙龙这类时尚属性强的应用来说,深色模式具有特殊的适用性。

深色模式在美业应用中的适用性体现在:

  1. 时尚高级感:深色背景天然具有高级、时尚、专业的视觉感受,与美发行业的时尚属性高度契合。高端美发沙龙通常采用深色装修风格,深色模式的 App 与高端美发店的视觉风格一致
  2. 内容突出:深色背景让彩色内容(发型图片、产品图片、设计师照片)更加突出,用户的视觉焦点自然集中在内容上,而不是界面元素上
  3. 品牌色表现力:紫色和金色在深色背景上的表现力远强于浅色背景。紫色在深色背景上更加神秘高贵,金色在深色背景上更加明亮尊贵,紫金配色在深色模式下达到最佳视觉效果
  4. 长时间使用舒适:用户在浏览发型、选择设计师、查看产品时可能需要较长时间,深色模式可以降低长时间使用的视觉疲劳
  5. OLED 省电:在 OLED 屏幕上,深色背景可以显著降低功耗,延长续航时间
  6. 行业趋势:越来越多的美业和时尚类应用采用深色模式作为默认主题,深色模式已经成为时尚类应用的行业标准

这款美发沙龙应用采用深色模式作为唯一主题(不提供浅色模式切换),正是基于对美发行业时尚属性的深刻理解。深色模式不仅是一种视觉风格选择,更是与美发行业高端时尚定位相匹配的设计决策。

13.2 三级灰度层级的视觉深度

应用的背景色采用三级灰度层级,构建了清晰的视觉深度:

  • SP.bg #121212:页面最底层背景,深灰近黑,是美业和流媒体应用的经典深色背景
  • SP.card #1E1E1E:卡片背景,比背景亮约 7%,让内容卡片在背景上自然浮现
  • SP.cardLight #2C2C2C:浅卡片背景,比卡片再亮约 7%,用于横向推荐卡片、社区帖子、设计师列表、预约时段等需要更高对比度的区域

三级灰度层级的设计价值:

  1. 视觉分层:通过微妙的亮度差异,在不使用边框的情况下清晰区分不同的视觉区域。背景层、卡片层、浅卡片层形成了自然的视觉深度
  2. 信息层级:不同层级的背景对应不同重要性的内容。浅卡片(#2C2C2C)用于需要更高对比度的内容区域(如社区帖子、设计师列表),普通卡片(#1E1E1E)用于常规内容区域(如发型宫格、产品宫格)
  3. 视觉节奏:三级灰度在页面中交替出现,形成了有节奏的视觉变化,避免了单一深色背景的单调感
  4. 沉浸感:整体偏暗的色调让用户的视觉焦点自然集中在内容上,而不是界面元素上,营造了沉浸式的使用体验

三级灰度层级是深色模式设计的核心技巧。很多初学者在设计深色模式时容易犯的错误是使用纯黑背景(#000000)和单一的卡片色,导致界面缺乏层次感和深度。这款应用的三级灰度设计是深色模式的最佳实践。

13.3 紫金配色在深色背景上的表现力

优雅紫 #9B59B6 和明亮金 #F1C40F 在深黑 #121212 背景上具有极强的视觉表现力,是这款应用视觉设计的核心亮点。

紫色的表现力

  • #9B59B6 是一种饱和度适中(约 65%)、明度中等(约 55%)的紫罗兰色
  • 在深黑背景上,紫色的对比度约为 4.5:1,满足 WCAG AA 级标准,既醒目又不刺眼
  • 紫色具有神秘、创意、个性、高贵的色彩心理感受,与美发行业的创意属性高度契合
  • 紫色用于 Tab 选中态、分类筛选选中态、设计师评分、预约确认按钮、社区发帖按钮、优惠券领取按钮等关键交互元素,成为整个界面的视觉锚点

金色的表现力

  • #F1C40F 是一种高饱和(约 85%)、高明度(约 60%)的暖黄色
  • 在深黑背景上,金色的对比度约为 10:1,远超 WCAG AAA 级标准,非常明亮醒目
  • 金色具有品质、活力、尊贵、阳光的色彩心理感受,在美发行业中代表高品质的服务和产品
  • 金色用于价格显示、设计师职称、产品品牌、预约已选提示、登录提示、优惠券折扣等信息元素,提升了界面的品质感和价值感

紫金搭配的协同效应

  • 紫色偏冷,金色偏暖,二者在色轮上相对,形成了强烈而和谐的冷暖对比
  • 紫金搭配常见于高端品牌、皇家徽章、时尚设计中,传递着尊贵、创意与品质的复合感受
  • 在美发平台中,紫色用于交互元素(引导操作),金色用于信息元素(展示价值),二者功能分工明确,不会产生视觉冲突
  • 紫色的神秘创意与金色的品质活力相互映衬,构建了一个既时尚创意又专业品质的美发服务视觉体验

紫金配色在深色背景上的出色表现力,是这款应用视觉设计的核心竞争力。它既符合美发行业的时尚创意属性,又具有专业品质感,让用户在使用 App 时就能感受到平台的高端定位和时尚氛围。

13.4 半透明叠加的标签设计

应用中使用半透明叠加层创建热门标签背景:

  • SP.primary + '33':20% 不透明度的紫色,用于发型卡片的"🔥 热"热门标签背景

半透明叠加标签的设计优势:

  1. 视觉柔和:半透明紫色标签在深色背景上效果自然柔和,不会产生实色标签的生硬色块感
  2. 层次丰富:半透明标签与深色背景形成了微妙的视觉层次,标签的边界自然过渡,不会过于突兀
  3. 品牌一致:半透明紫色保留了紫色的品牌识别,同时降低了视觉强度,适合用于热门标签等辅助元素
  4. 文字可读:半透明紫色背景上的紫色文字(或白色文字)仍然具有足够的对比度,确保可读性
  5. 状态区分:选中态使用实色紫色背景+白色文字,标签态使用半透明紫色背景+紫色文字,二者对比清晰

半透明叠加是深色模式设计中广泛使用的技巧。除了标签背景,还可以用于弹窗遮罩、卡片悬浮态、按钮按下态等场景。这款应用对半透明叠加的熟练运用,体现了深色模式设计的专业水准。

13.5 文字对比度与可读性

应用的文字色系统确保了在深色背景上的良好可读性:

  • SP.text #FFFFFF 纯白:主文字色,与背景 #121212 的对比度约为 16:1,远超 WCAG AAA 级标准(7:1),可读性极佳
  • SP.textSub #B0B0B0 中灰:次级文字色,与背景的对比度约为 7:1,满足 WCAG AAA 级标准,可读性良好

文字对比度的设计考量:

  1. 层级清晰:纯白主文字和中灰次级文字形成了清晰的信息层级,用户可以快速区分核心信息和辅助信息
  2. 避免眩光:纯白文字在纯黑背景上可能产生眩光效应(halation),即文字边缘的光晕扩散,导致长时间阅读疲劳。应用使用 #121212(非纯黑)作为背景,在一定程度上缓解了眩光效应
  3. 字号适配:主文字使用 11-18px 的字号,次级文字使用 8-10px 的字号,不同层级的文字使用不同字号,进一步强化了信息层级
  4. 行间距:卡片和列表中的元素通过 margin 控制行间距,确保文字不会过于拥挤,提升阅读舒适度

文字对比度和可读性是 UI 设计的基础。这款应用在深色模式下的文字设计遵循了 WCAG 无障碍标准,确保了不同视力水平的用户都能清晰阅读。

13.6 时尚感的设计要素综合

时尚感是这款美发沙龙应用视觉设计的核心目标,它通过多个设计要素的综合作用实现:

  1. 深色背景:#121212 深黑背景营造了高级时尚的基底氛围,与高端美发沙龙的装修风格一致
  2. 三级灰度:背景/卡片/浅卡片三级灰度构建了有序的视觉深度,避免了界面的轻浮感
  3. 紫金配色:优雅紫 #9B59B6 + 明亮金 #F1C40F 的配色方案,传递了创意、个性、尊贵与品质的复合感受,是时尚感的核心来源
  4. 圆角克制:卡片圆角使用 8-12px 的中等圆角,按钮圆角使用 12-16px,既不过于尖锐(生硬),也不过于圆润(可爱),保持了时尚高级感
  5. 字体稳重:使用系统默认的无衬线字体,字重以 Medium 和 Bold 为主,文字清晰有力,标题使用 Bold 字重增强视觉冲击力
  6. 布局有序:宫格、列表、卡片等布局元素整齐排列,间距统一,对齐规范,营造了秩序感和专业感
  7. 动效克制:仅使用 Tab 图标缩放这一种交互动画,动画时长 200ms,缓动曲线 EaseOut,动效克制不花哨,保持了高级感
  8. 内容精致:发型名称、设计师职称、产品品牌等内容文字简洁专业,没有网络用语和夸张表达,体现了平台的专业定位

这些设计要素的综合作用,让整个应用呈现出时尚、高级、专业、可信赖的视觉感受。这对于美发服务平台来说至关重要——用户在选择美发服务时,首先会通过 App 的视觉设计判断平台的专业度和时尚感,一个时尚高级的 App 设计会让用户更信任平台的服务品质。

13.7 深色模式的未来

深色模式已经从"可选功能"变成了时尚类应用的"标配功能",未来的发展趋势包括:

  1. 系统级深色模式:iOS、Android、HarmonyOS 等操作系统都提供了系统级深色模式开关,应用可以跟随系统设置自动切换
  2. 动态深色模式:根据时间(日落自动切换)、环境光(暗光环境自动切换)等动态调整深色模式
  3. 个性化深色主题:用户可以自定义深色模式的背景色、强调色、对比度等,打造个性化的深色主题
  4. 高对比度深色模式:为视力障碍用户提供高对比度深色模式,提升无障碍体验
  5. 深色模式设计系统:建立完整的深色模式设计系统,包括色彩、字体、间距、组件、动效等规范,确保深色模式下的设计一致性

这款应用采用固定深色模式(不提供浅色模式切换),是基于美发行业时尚属性的设计决策。未来如果需要扩展到更多用户群体,可以考虑增加浅色模式和跟随系统设置的功能,让用户根据自己的偏好选择。

深色模式不仅仅是一种视觉风格,更是一种以用户体验为中心的设计哲学。它关注用户在不同环境下的视觉舒适度,关注内容与界面的视觉层级,关注品牌情感的传递,关注时尚感与专业感的平衡。这款美发沙龙应用的深色模式设计,正是这种设计哲学的体现——通过精心调配的紫金配色和三级灰度层级,为用户创造一个时尚、高级、舒适的美发服务体验。


第十四章 开发环境搭建与运行指南

本章提供完整的开发环境搭建步骤,包括 DevEco Studio 安装、HarmonyOS SDK 配置、项目创建、代码运行和预览调试。按照本章步骤操作,你可以在 30 分钟内将本应用在模拟器或真机上运行起来。

14.1 安装 DevEco Studio

DevEco Studio 是华为官方提供的 HarmonyOS 应用开发 IDE,基于 IntelliJ IDEA 社区版构建,提供了代码编辑、编译构建、调试运行、模拟器等完整的开发工具链。

系统要求

  • 操作系统:Windows 10/11(64位)、macOS 11+、Ubuntu 20.04+
  • 内存:最低 8GB,推荐 16GB 及以上
  • 硬盘:至少 10GB 可用空间(IDE + SDK + 模拟器)
  • 分辨率:最低 1280×800

安装步骤

  1. 访问华为开发者联盟官网(developer.huawei.com),进入"开发 > 工具 > DevEco Studio"下载页面
  2. 根据你的操作系统选择对应的安装包下载(Windows .exe、macOS .dmg、Linux .tar.gz)
  3. 运行安装程序,按照向导完成安装:
    • Windows:双击 .exe 安装包,选择安装路径,勾选"创建桌面快捷方式",点击安装
    • macOS:双击 .dmg 镜像,将 DevEco Studio 拖拽到 Applications 文件夹
    • Linux:解压 .tar.gz 到目标目录,运行 bin/devecostudio.sh 启动
  4. 首次启动 DevEco Studio 时,会引导你完成初始配置:
    • 选择 UI 主题(Darcula 深色 / IntelliJ 浅色)
    • 配置 Node.js 环境(DevEco Studio 会自动下载内置的 Node.js)
    • 配置 HarmonyOS SDK 路径(默认即可)
    • 登录华为账号(部分功能需要登录)

DevEco Studio 安装界面

安装完成后,启动 DevEco Studio,你会看到欢迎界面,包含"创建项目"、“打开项目”、"从版本控制获取"等选项。此时 DevEco Studio 的基础环境已经就绪,接下来需要配置 HarmonyOS SDK。

14.2 配置 HarmonyOS SDK

HarmonyOS SDK 是开发 HarmonyOS 应用所需的软件开发工具包,包含编译器、运行时、系统 API、模拟器镜像等。DevEco Studio 安装时会自动下载默认版本的 SDK,但你可能需要手动配置或更新 SDK 版本。

SDK 配置步骤

  1. 打开 DevEco Studio,进入欢迎界面或任意项目
  2. 菜单栏选择 File > Settings(Windows/Linux)或 DevEco Studio > Preferences(macOS)
  3. 在左侧导航栏选择 HarmonyOS > SDK
  4. 在 SDK 配置页面中:
    • SDK Location:显示当前 SDK 的安装路径,默认即可
    • SDK Platforms:勾选需要的 API 版本(推荐 API 9 及以上,本应用使用 API 9+)
    • SDK Tools:勾选需要的工具,包括:
      • HarmonyOS SDK Toolchains(编译构建工具)
      • HarmonyOS SDK Platform Tools(平台工具)
      • HarmonyOS Emulator(模拟器,需要单独下载)
      • Previewer(预览器,用于实时预览 UI)
  5. 点击 Apply 应用配置,DevEco Studio 会自动下载和安装勾选的 SDK 组件
  6. 等待下载和安装完成后,点击 OK 关闭设置窗口

HarmonyOS SDK 配置界面

SDK 版本说明

  • API 9:首个支持 Stage 模型的 API 版本,推荐使用
  • API 10/11/12:后续版本,增加了更多 API 和功能
  • 本应用使用 API 9+ 的 Stage 模型和 ArkTS 声明式 UI,兼容 API 9 及以上版本

配置完成后,你可以在项目的 build-profile.json5 文件中查看和修改项目使用的 SDK 版本:

{
  "app": {
    "signingConfigs": [],
    "products": [
      {
        "name": "default",
        "signingConfig": "default",
        "compatibleSdkVersion": "9.0.0",
        "runtimeOS": "HarmonyOS"
      }
    ]
  }
}

14.3 创建 HarmonyOS 项目

SDK 配置完成后,你可以创建一个新的 HarmonyOS 项目来运行本应用。

创建项目步骤

  1. 打开 DevEco Studio 欢迎界面,点击 Create Project(创建项目)
  2. 在项目模板选择页面:
    • 选择 Application(应用)分类
    • 选择 Empty Ability(空 Ability)模板,这是最基础的项目模板
    • 点击 Next
  3. 在项目配置页面:
    • Project name:项目名称,输入 HairApp 或你喜欢的名称
    • Bundle name:应用包名,格式为 com.example.hairapp(反向域名格式,全局唯一)
    • Save location:项目保存路径,选择一个空文件夹
    • Compile SDK:编译 SDK 版本,选择 9 或更高版本
    • Compatible SDK:兼容 SDK 版本,选择 9
    • Model:选择 Stage(Stage 模型,API 9+ 推荐)
    • Language:选择 ArkTS(ArkTS 语言)
    • 勾选 Enable Super Visual(可选,启用超级视觉,用于低代码开发)
  4. 点击 Finish 完成项目创建,DevEco Studio 会自动生成项目结构和初始代码

创建 HarmonyOS 项目界面

项目结构说明

创建完成后,项目的目录结构如下:

HairApp/
├── AppScope/                    # 应用全局配置
│   ├── app.json5               # 应用配置文件
│   └── resources/              # 应用全局资源
├── entry/                       # 主模块(HAP 包)
│   ├── src/main/
│   │   ├── ets/
│   │   │   ├── entryability/  # Ability 入口
│   │   │   │   └── EntryAbility.ets
│   │   │   └── pages/          # 页面目录
│   │   │       └── Index.ets   # 首页(将替换为本应用代码)
│   │   ├── resources/          # 模块资源
│   │   └── module.json5        # 模块配置文件
│   └── build-profile.json5     # 模块构建配置
├── build-profile.json5          # 项目构建配置
├── hvigorfile.ts                # 构建脚本
└── oh-package.json5             # 依赖配置

替换应用代码

项目创建完成后,你需要将本应用的代码替换到项目中:

  1. 打开 entry/src/main/ets/pages/Index.ets 文件
  2. 删除文件中的所有默认代码
  3. 将本文附录中的完整 ArkTS 源码复制粘贴到 Index.ets 文件中
  4. 保存文件(Ctrl+S / Cmd+S)

或者,你也可以创建一个新的 .ets 文件:

  1. entry/src/main/ets/pages/ 目录上右键,选择 New > ArkTS File
  2. 输入文件名 HairApp,点击 OK
  3. 将附录中的完整源码复制到 HairApp.ets 文件中
  4. 修改 module.json5 中的 srcEntry 配置,将入口页面指向新文件

14.4 运行应用

代码替换完成后,你可以在模拟器或真机上运行应用。

方式一:在模拟器上运行

  1. 打开 DevEco Studio 菜单栏,选择 Tools > Device Manager(设备管理器)
  2. 在设备管理器中:
    • 选择 Emulator(模拟器)标签
    • 点击 + Create Emulator(创建模拟器)
    • 选择设备型号(推荐 Phone > P50 或类似的手机型号)
    • 选择系统镜像(API 9 及以上,HarmonyOS)
    • 配置模拟器参数(内存、存储、分辨率等,默认即可)
    • 点击 Finish 创建模拟器
  3. 模拟器创建完成后,在设备管理器中点击模拟器的启动按钮(▶️),等待模拟器启动
  4. 模拟器启动完成后,DevEco Studio 顶部工具栏的设备选择器会显示当前连接的模拟器
  5. 点击工具栏的运行按钮(▶️ Run ‘entry’),或使用快捷键 Shift+F10(Windows/Linux)/ Ctrl+R(macOS)
  6. DevEco Studio 会自动编译项目、安装 HAP 包到模拟器、启动应用
  7. 等待应用在模拟器中启动,你就可以看到美发沙龙应用的界面了

运行应用界面

方式二:在真机上运行

  1. 准备一台 HarmonyOS 手机(API 9 及以上)
  2. 在手机上开启开发者模式:
    • 进入 设置 > 关于手机
    • 连续点击 版本号 7 次,开启开发者模式
  3. 开启 USB 调试:
    • 进入 设置 > 系统和更新 > 开发人员选项
    • 开启 USB 调试 开关
  4. 用 USB 数据线将手机连接到电脑
  5. 在手机上弹出的"允许 USB 调试"对话框中点击"允许"
  6. DevEco Studio 顶部工具栏的设备选择器会显示连接的真机
  7. 点击运行按钮(▶️ Run ‘entry’),应用会自动安装到真机并启动

编译构建说明

DevEco Studio 使用 hvigor 构建系统编译 HarmonyOS 应用。构建过程包括:

  1. 代码编译:将 ArkTS 代码编译为 JavaScript
  2. 资源编译:编译图片、字符串、布局等资源文件
  3. 打包:将编译后的代码和资源打包为 HAP(HarmonyOS Ability Package)文件
  4. 签名:对 HAP 包进行签名(调试模式使用自动生成的调试证书)
  5. 安装:将签名后的 HAP 包安装到设备

如果编译过程中出现错误,DevEco Studio 会在底部的 Build 窗口中显示错误信息。常见的错误包括:

  • SDK 版本不匹配:检查 build-profile.json5 中的 SDK 版本配置
  • 语法错误:检查 ArkTS 代码是否符合严格模式规范
  • 资源缺失:检查引用的资源文件是否存在
  • 签名配置:检查签名证书是否正确配置

14.5 预览与调试

DevEco Studio 提供了强大的预览和调试工具,帮助你在开发过程中实时查看 UI 效果和排查问题。

预览器(Previewer)

预览器是 DevEco Studio 内置的 UI 实时预览工具,可以在不运行应用的情况下实时查看 ArkTS 声明式 UI 的渲染效果。

使用方法:

  1. 打开包含 ArkTS 声明式 UI 代码的 .ets 文件
  2. 点击编辑器右上角的 Previewer 标签(或使用快捷键 Alt+2
  3. 预览器会在右侧打开,实时显示当前文件中 UI 组件的渲染效果
  4. 修改代码后,预览器会自动更新显示效果(热重载)
  5. 预览器顶部提供设备选择、横竖屏切换、深色/浅色模式切换等功能

预览器的优势:

  • 实时预览:修改代码后立即看到效果,不需要重新编译运行
  • 多设备预览:可以在不同设备型号上预览 UI 效果
  • 交互模拟:可以在预览器中模拟点击、滑动等交互操作
  • 组件树查看:可以查看 UI 组件的层级结构

预览与调试界面

调试器(Debugger)

调试器用于在应用运行时排查代码问题,支持断点、变量查看、调用栈跟踪等功能。

使用方法:

  1. 在代码编辑器中,点击行号左侧的空白区域设置断点(断点显示为红色圆点)
  2. 点击工具栏的调试按钮(🐛 Debug ‘entry’),或使用快捷键 Shift+F9
  3. 应用会在调试模式下启动,当执行到断点时会暂停
  4. 在调试窗口中可以查看:
    • Variables:当前作用域的变量值
    • Watches:自定义监视的表达式
    • Call Stack:函数调用栈
    • Breakpoints:所有断点列表
  5. 使用调试工具栏的按钮控制执行流程:
    • ▶️ Resume(继续执行)
    • ⏭️ Step Over(单步跳过)
    • ⏬ Step Into(单步进入)
    • ⏫ Step Out(单步跳出)
    • 🛑 Stop(停止调试)

日志查看(Log)

应用运行时的日志输出可以在 DevEco Studio 底部的 Log 窗口中查看:

  • 应用的 console.log() 输出会显示在 Log 窗口中
  • 可以按日志级别(Verbose/Debug/Info/Warn/Error)过滤
  • 可以按关键词搜索日志
  • 可以选择查看特定设备或进程的日志

性能分析(Profiler)

DevEco Studio 还提供了性能分析工具,可以分析应用的 CPU 使用率、内存占用、帧率、网络请求等性能指标:

  1. 菜单栏选择 View > Tool Windows > Profiler
  2. 选择要分析的设备和进程
  3. 开始性能分析,查看实时性能数据
  4. 可以录制性能会话,事后分析性能瓶颈

14.6 常见问题与解决方案

在开发和运行过程中,可能会遇到一些常见问题:

Q1:DevEco Studio 启动时提示"Node.js 未安装"
A:DevEco Studio 会自动下载内置的 Node.js,如果自动下载失败,可以手动配置:

  1. 下载安装 Node.js 16+ 版本
  2. Settings > HarmonyOS > Node.js 中配置 Node.js 路径

Q2:SDK 下载失败或速度慢
A:可以配置华为镜像源加速下载:

  1. Settings > Appearance & Behavior > System Settings > HTTP Proxy 中配置代理
  2. 或者手动下载 SDK 包,解压到 SDK 目录

Q3:模拟器启动失败
A:常见原因和解决方案:

  • 电脑未开启虚拟化技术(VT-x/AMD-V):进入 BIOS 开启虚拟化
  • 内存不足:关闭其他占用内存的程序,或增加模拟器内存配置
  • 显卡驱动问题:更新显卡驱动到最新版本

Q4:编译报错"ArkTS 严格模式不允许…"
A:本应用严格遵循 ArkTS 严格模式规范,如果你的代码报错:

  • 检查是否使用了 Object.assign(严格模式不允许,应使用对象展开或手动赋值)
  • 检查是否使用了计算属性名(如 obj[key],严格模式不允许,应使用 if-else 或 switch)
  • 检查是否使用了 any 类型(严格模式不允许,应使用具体类型)
  • 检查变量和函数是否都有显式类型标注

Q5:真机安装失败"签名校验失败"
A:需要配置正确的签名证书:

  1. 菜单栏选择 File > Project Structure > Project > Signing Configs
  2. 勾选"Automatically generate signature"(自动生成签名)
  3. 登录华为账号,DevEco Studio 会自动生成调试证书
  4. 重新编译运行

Q6:预览器不显示或显示空白
A:尝试以下解决方案:

  1. 确保文件中包含 @Component 装饰的组件
  2. 确保文件语法正确,没有编译错误
  3. 点击预览器顶部的刷新按钮重新加载
  4. 重启 DevEco Studio

按照本章的步骤操作,你应该能够顺利搭建开发环境、创建项目、运行应用并进行预览调试。如果遇到本章未覆盖的问题,可以参考华为开发者联盟官网的文档和社区,或者在 DevEco Studio 的帮助菜单中查找解决方案。


总结与展望

全文总结

本文对基于 HarmonyOS ArkTS 声明式 UI 开发的美发沙龙发型设计一站式平台进行了全方位的深度解析。这款应用以优雅紫 #9B59B6 和明亮金 #F1C40F 为核心配色,在深黑 #121212 背景上构建了时尚高级的视觉体验,通过 8 个 Tab(首页/发型/预约/设计师/产品/社区/优惠/我的)覆盖了美发服务从发现到消费到分享的全流程。

在技术层面,应用严格遵循 ArkTS 严格模式规范,使用 getTabTitle 的 if-else 链替代对象字面量避免计算属性名,采用双头部设计(HomeHeader 品牌展示 + CommonHeader 简洁导航),实现了完整的预约流程(设计师选择→时段选择→确认预约)和发型分类筛选(全部/男士/女士/儿童)。应用包含 7 个数据接口、6 组静态数据、1 个纯函数工具、12 个 UI 组件,约 750 行代码在一个 .ets 文件中,无第三方依赖,复制即可运行。

在设计层面,应用的紫金配色在深色背景上具有极强的视觉表现力,紫色传递创意与个性,金色传递品质与尊贵,二者协同构建了既时尚又专业的美发服务视觉体验。三级灰度层级(#121212/#1E1E1E/#2C2C2C)构建了有序的视觉深度,半透明叠加标签、克制的圆角和动效、清晰的文字对比度等设计细节,共同营造了高级时尚的使用体验。

在业务层面,应用构建了完整的美发服务生态:8 款发型覆盖男士/女士/儿童三个客群和剪发/烫发/造型三种服务类型,4 位设计师各有专长,4 款国际品牌洗护产品,3 条社区帖子覆盖不同主题,3 张优惠券覆盖新客引流/烫染促销/生日营销三种场景。这些业务元素共同构成了从发型浏览→设计师选择→在线预约→到店服务→产品购买→社区分享→优惠复购的完整服务闭环。

美发沙龙应用总结

技术亮点回顾

  1. 8 Tab 全流程覆盖:首页/发型/预约/设计师/产品/社区/优惠/我的,8 个 Tab 覆盖美发服务全流程,是目前解析的应用中 Tab 数量最多的之一
  2. 完整预约流程:预约 Tab 实现了设计师选择→时段选择→确认预约的完整流程,包含三态时段标签(已选/可约/不可约)和状态联动,是服务类应用预约功能的典型实现
  3. 发型分类筛选:发型 Tab 实现了全部/男士/女士/儿童四分类筛选,通过 @Builder categoryChip 封装可复用的筛选标签,状态联动清晰
  4. getTabTitle 严格模式合规:使用 if-else 链替代对象字面量,避免计算属性名,是 ArkTS 严格模式的典型实践
  5. 双头部设计:首页使用 HomeHeader(品牌标识+副标题),其他 Tab 使用 CommonHeader(标题+通知),通过条件渲染切换,兼顾品牌展示和简洁导航
  6. 四列设计师宫格:首页热门设计师使用 23% 宽度的四列宫格,在有限空间内展示多位设计师,是首页的特色布局
  7. 紫金时尚配色:优雅紫 #9B59B6 + 明亮金 #F1C40F 在深黑 #121212 背景上构建了时尚高级的视觉体验,符合美发行业的创意属性
  8. 三级灰度层级:背景/卡片/浅卡片三级灰度构建了有序的视觉深度,是深色模式设计的最佳实践
  9. 优惠券营销设计:3 张优惠券覆盖新客引流/烫染促销/生日营销三种场景,金色折扣信息+紫色领取按钮的紫金搭配醒目突出
  10. 单文件零依赖:约 750 行代码在一个 .ets 文件中,无第三方依赖,复制即运行,适合作为学习案例

未来展望

这款美发沙龙应用作为概念原型,已经涵盖了美发服务平台的核心功能和设计要素。未来可以从以下方向进行扩展和深化:

功能扩展

  1. 发型详情页:为每款发型增加详情页,包含发型介绍、适合脸型、打理方法、相关产品、用户评价等详细信息
  2. 设计师详情页:为每位设计师增加详情页,包含个人介绍、作品集、用户评价、可约时段、服务价格等
  3. 产品详情页:为每款产品增加详情页,包含产品介绍、成分说明、适用发质、使用方法、用户评价等
  4. AI 发型试戴:集成 AR/AI 技术,用户可以上传照片虚拟试戴不同发型,预览效果后再决定
  5. 智能推荐系统:基于用户的脸型、发质、风格偏好、历史消费等数据,AI 智能推荐适合的发型和设计师
  6. 在线支付:集成支付功能,用户可以在线支付预约定金或全款,完成交易闭环
  7. 评价系统:用户到店消费后可以对设计师和服务进行评价,评价内容展示在设计师详情页和社区中

社交深化
8. 关注系统:用户可以关注喜欢的设计师和发型达人,获取他们的最新动态和作品
9. 私信功能:用户可以与设计师或其他用户私信沟通,咨询发型问题或预约细节
10. 话题标签:社区帖子增加话题标签(如 #空气刘海 #男士短发 #烫染护理),方便用户按话题浏览
11. 图片/视频发布:社区支持发布图片和视频,用户可以展示发型效果和打理过程
12. 设计师直播:设计师可以在平台上直播发型教程和趋势解读,增加用户互动和设计师 IP 影响力

会员与营销
13. 会员等级体系:建立普通/银卡/金卡/钻石会员等级体系,不同等级享受不同折扣和权益
14. 积分系统:消费和社区互动获得积分,积分可以兑换产品、服务、优惠券等
15. 储值卡/次卡:支持储值卡和次卡销售,提升用户预存和复购
16. 生日特权:用户生日月享受专属折扣和免费服务,提升用户忠诚度
17. 邀请返利:老用户邀请新用户注册消费,双方获得优惠券或积分奖励

技术升级
18. 后端服务对接:对接真实的后端 API,实现用户登录、预约同步、支付、评价等真实功能
19. 数据持久化:使用关系型数据库或 Preferences 存储用户数据、预约记录、收藏等,实现数据持久化
20. 推送通知:集成推送服务,预约提醒、优惠通知、社区互动等消息实时推送给用户
21. 多端适配:适配手机、平板、折叠屏等多种设备形态,提供一致的用户体验
22. 国际化:支持多语言(中文/英文/日文等),拓展国际市场
23. 性能优化:使用懒加载、虚拟列表、图片压缩等技术优化应用性能,提升加载速度和流畅度

业务拓展
24. 多门店支持:支持连锁美发店的多门店管理,用户可以选择门店和该门店的设计师
25. 上门服务:支持设计师上门服务,用户预约后设计师到用户指定地点服务
26. 美发教育:增加美发教育板块,为美发师提供在线课程和认证考试
27. 供应链服务:为美发店提供产品采购供应链服务,整合上游产品品牌和下游美发店
28. 行业数据:基于平台数据发布美发行业报告,包括流行趋势、消费洞察、设计师排名等

美发服务是一个万亿级的大市场,数字化和平台化是行业发展的必然趋势。这款美发沙龙应用作为概念原型,展示了美发服务平台化的核心功能和设计思路,为美业数字化转型提供了有价值的参考。随着技术的发展和用户需求的升级,美发服务平台将不断演进,为用户提供更加便捷、个性化、高品质的美发服务体验。


附录:完整 ArkTS 源码

以下是美发沙龙发型设计一站式平台的完整 ArkTS 源码,严格遵循 ArkTS 严格模式规范,无第三方依赖,复制到 DevEco Studio 项目的 .ets 文件中即可运行。


// ============================================================
// HairApp.ets —— 美发沙龙 · 发型设计一站式平台
// 8 个 Tab:首页 | 发型 | 预约 | 设计师 | 产品 | 社区 | 优惠 | 我的
// 主题:深色底 #121212,主色 #9B59B6,辅色 #F1C40F
// 适配 ArkTS 严格模式(无展开,无 Object.assign,无计算属性名)
// ============================================================

// ---------- 调色板 ----------
interface AppPalette {
  bg: string;
  primary: string;
  primaryDark: string;
  accent: string;
  card: string;
  cardLight: string;
  text: string;
  textSub: string;
  chip: string;
  border: string;
  white: string;
}

const SP: AppPalette = {
  bg: '#121212',
  primary: '#9B59B6',
  primaryDark: '#8E44AD',
  accent: '#F1C40F',
  card: '#1E1E1E',
  cardLight: '#2C2C2C',
  text: '#FFFFFF',
  textSub: '#B0B0B0',
  chip: '#3A3A3A',
  border: '#444444',
  white: '#FFFFFF'
};

// ---------- 数据接口 ----------
interface HairStyle {
  id: number;
  name: string;
  icon: string;
  category: string;      // '男士' | '女士' | '儿童'
  length: string;
  price: number;
  hot: boolean;
}

interface Designer {
  id: number;
  name: string;
  avatar: string;
  title: string;
  rating: number;
  experience: string;
  style: string;
}

interface AppointmentSlot {
  id: number;
  date: string;
  time: string;
  available: boolean;
}

interface Product {
  id: number;
  name: string;
  brand: string;
  icon: string;
  price: number;
  type: string;
}

interface Post {
  id: number;
  user: string;
  avatar: string;
  title: string;
  content: string;
  time: string;
  likes: number;
  comments: number;
}

interface Coupon {
  id: number;
  name: string;
  discount: string;
  validUntil: string;
}

// ---------- 模拟数据 ----------
const HAIR_STYLES: HairStyle[] = [
  { id: 1, name: '经典短发', icon: '💇', category: '男士', length: '短发', price: 68, hot: true },
  { id: 2, name: '韩式纹理烫', icon: '🔥', category: '男士', length: '中发', price: 188, hot: false },
  { id: 3, name: '寸头', icon: '✂️', category: '男士', length: '短发', price: 58, hot: false },
  { id: 4, name: '长发波浪', icon: '🌊', category: '女士', length: '长发', price: 268, hot: true },
  { id: 5, name: '齐耳短发', icon: '🎀', category: '女士', length: '短发', price: 88, hot: false },
  { id: 6, name: '日系空气刘海', icon: '🌸', category: '女士', length: '中发', price: 128, hot: true },
  { id: 7, name: '儿童丸子头', icon: '🍡', category: '儿童', length: '长发', price: 68, hot: false },
  { id: 8, name: '儿童平头', icon: '🧒', category: '儿童', length: '短发', price: 48, hot: false },
];

const DESIGNERS: Designer[] = [
  { id: 1, name: 'Tony 老师', avatar: '💈', title: '首席发型师', rating: 4.9, experience: '10年经验', style: '韩式剪发' },
  { id: 2, name: 'Allen', avatar: '✂️', title: '高级发型师', rating: 4.7, experience: '7年经验', style: '日系造型' },
  { id: 3, name: 'Lisa', avatar: '💄', title: '烫染专家', rating: 4.8, experience: '8年经验', style: '烫染设计' },
  { id: 4, name: 'Kevin', avatar: '🪒', title: '男士理发师', rating: 4.6, experience: '5年经验', style: '复古油头' },
];

const APPOINTMENT_SLOTS: AppointmentSlot[] = [
  { id: 1, date: '2026-08-28', time: '10:00', available: true },
  { id: 2, date: '2026-08-28', time: '11:00', available: true },
  { id: 3, date: '2026-08-28', time: '14:00', available: false },
  { id: 4, date: '2026-08-28', time: '15:00', available: true },
  { id: 5, date: '2026-08-29', time: '09:30', available: true },
  { id: 6, date: '2026-08-29', time: '13:00', available: false },
];

const PRODUCTS: Product[] = [
  { id: 1, name: '滋润洗发水', brand: 'Kérastase', icon: '🧴', price: 128, type: '洗护' },
  { id: 2, name: '护发精油', brand: 'Moroccanoil', icon: '✨', price: 188, type: '洗护' },
  { id: 3, name: '定型喷雾', brand: 'Schwarzkopf', icon: '💨', price: 68, type: '造型' },
  { id: 4, name: '烫发修复霜', brand: 'Wella', icon: '🧪', price: 158, type: '烫染' },
];

const POSTS: Post[] = [
  { id: 1, user: '时尚达人', avatar: '👩', title: '推荐这款空气刘海,超减龄!', content: '剪了Lisa同款,朋友都说像换了个人...', time: '2026-08-25', likes: 56, comments: 12 },
  { id: 2, user: '发型控', avatar: '🧔', title: '男士短发打理技巧', content: '用发蜡和吹风机,三分钟搞定...', time: '2026-08-22', likes: 34, comments: 8 },
  { id: 3, user: '宝妈小惠', avatar: '👩‍👦', title: '儿童第一次理发体验', content: '造型师很有耐心,宝宝没哭...', time: '2026-08-18', likes: 27, comments: 5 },
];

const COUPONS: Coupon[] = [
  { id: 1, name: '新客专享', discount: '满100减20', validUntil: '2026-09-30' },
  { id: 2, name: '烫染特惠', discount: '第二件半价', validUntil: '2026-10-15' },
  { id: 3, name: '生日礼券', discount: '8折优惠', validUntil: '2026-12-31' },
];

// ---------- Tab 枚举 ----------
enum MainTab {
  HOME = 0,
  STYLES = 1,
  BOOKING = 2,
  DESIGNER = 3,
  PRODUCT = 4,
  COMMUNITY = 5,
  COUPON = 6,
  MINE = 7
}

// ---------- 辅助函数 ----------
function genId(): number {
  return Math.floor(Math.random() * 1000000);
}

// ---------- 入口 ----------
@Entry @Component struct HairApp {
  @State activeTab: number = MainTab.HOME;

  build() {
    Column() {
      if (this.activeTab === MainTab.HOME) {
        HomeHeader();
      } else {
        CommonHeader({ title: this.getTabTitle(this.activeTab) });
      }

      Stack() {
        if (this.activeTab === MainTab.HOME) {
          HomeContent();
        } else if (this.activeTab === MainTab.STYLES) {
          StylesContent();
        } else if (this.activeTab === MainTab.BOOKING) {
          BookingContent();
        } else if (this.activeTab === MainTab.DESIGNER) {
          DesignerContent();
        } else if (this.activeTab === MainTab.PRODUCT) {
          ProductContent();
        } else if (this.activeTab === MainTab.COMMUNITY) {
          CommunityContent();
        } else if (this.activeTab === MainTab.COUPON) {
          CouponContent();
        } else {
          MineContent();
        }
      }
      .layoutWeight(1)
      .width('100%');

      Row() {
        this.tabItem('🏠', '首页', MainTab.HOME);
        this.tabItem('💇', '发型', MainTab.STYLES);
        this.tabItem('📅', '预约', MainTab.BOOKING);
        this.tabItem('👨', '设计师', MainTab.DESIGNER);
        this.tabItem('🧴', '产品', MainTab.PRODUCT);
        this.tabItem('💬', '社区', MainTab.COMMUNITY);
        this.tabItem('🎫', '优惠', MainTab.COUPON);
        this.tabItem('👤', '我的', MainTab.MINE);
      }
      .width('100%')
      .height(58)
      .backgroundColor(SP.card)
      .padding({ left: 2, right: 2, top: 4 })
      .border({ width: { top: 0.5 }, color: SP.border });
    }
    .width('100%')
    .height('100%')
    .backgroundColor(SP.bg);
  }

  @Builder
  tabItem(icon: string, label: string, tab: number) {
    Column() {
      Text(icon)
        .fontSize(20)
        .scale({
          x: this.activeTab === tab ? 1.2 : 1,
          y: this.activeTab === tab ? 1.2 : 1
        })
        .animation({ duration: 200, curve: Curve.EaseOut });
      Text(label)
        .fontSize(9)
        .fontColor(this.activeTab === tab ? SP.primary : SP.textSub)
        .margin({ top: 2 });
      Divider()
        .strokeWidth(2)
        .color(this.activeTab === tab ? SP.primary : Color.Transparent)
        .width(12)
        .borderRadius(1)
        .margin({ top: 2 });
    }
    .layoutWeight(1)
    .onClick(() => {
      this.activeTab = tab;
    });
  }

  getTabTitle(tab: number): string {
    if (tab === MainTab.STYLES) {
      return '发型';
    } else if (tab === MainTab.BOOKING) {
      return '预约';
    } else if (tab === MainTab.DESIGNER) {
      return '设计师';
    } else if (tab === MainTab.PRODUCT) {
      return '产品';
    } else if (tab === MainTab.COMMUNITY) {
      return '社区';
    } else if (tab === MainTab.COUPON) {
      return '优惠';
    } else if (tab === MainTab.MINE) {
      return '我的';
    }
    return '页面';
  }
}

// ---------- 通用头部 ----------
@Component struct CommonHeader {
  @Prop title: string;

  build() {
    Row() {
      Text(this.title)
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .fontColor(SP.text)
        .margin({ left: 16 });
      Column().layoutWeight(1);
      Text('🔔')
        .fontSize(18)
        .margin({ right: 16 });
    }
    .width('100%')
    .height(48)
    .backgroundColor(SP.card)
    .border({ width: { bottom: 0.5 }, color: SP.border });
  }
}

// ---------- 首页头部 ----------
@Component struct HomeHeader {
  build() {
    Row() {
      Text('💇')
        .fontSize(24);
      Column() {
        Text('美发沙龙')
          .fontSize(18)
          .fontWeight(FontWeight.Bold)
          .fontColor(SP.primary);
        Text('剪发 · 烫染 · 护发')
          .fontSize(9)
          .fontColor(SP.accent);
      }
      .alignItems(HorizontalAlign.Start)
      .margin({ left: 6 })
      .layoutWeight(1);

      Text('🔔')
        .fontSize(20)
        .margin({ right: 14 });
      Text('👤')
        .fontSize(20);
    }
    .width('100%')
    .height(48)
    .backgroundColor(SP.card)
    .padding({ left: 16, right: 16 })
    .border({ width: { bottom: 0.5 }, color: SP.border });
  }
}

// ---------- 首页内容 ----------
@Component struct HomeContent {
  build() {
    Scroll() {
      Column() {
        // 快捷入口
        Row() {
          this.quickItem('💇', '发型');
          this.quickItem('📅', '预约');
          this.quickItem('👨', '设计师');
          this.quickItem('🧴', '产品');
          this.quickItem('💬', '社区');
          this.quickItem('🎫', '优惠');
          this.quickItem('📖', '资讯');
          this.quickItem('📞', '客服');
        }
        .width('100%')
        .padding({ top: 12, bottom: 8 });

        // 热门发型横向滚动
        Scroll() {
          Row() {
            ForEach(HAIR_STYLES.filter(s => s.hot), (item: HairStyle) => {
              Column() {
                Text(item.icon)
                  .fontSize(44)
                  .textAlign(TextAlign.Center)
                  .width('100%');
                Text(item.name)
                  .fontSize(12)
                  .fontColor(SP.text)
                  .margin({ top: 4 });
                Text('¥' + item.price)
                  .fontSize(10)
                  .fontColor(SP.accent);
              }
              .width(110)
              .backgroundColor(SP.cardLight)
              .borderRadius(12)
              .padding(8)
              .margin({ left: 10, right: 10 });
            });
          }
          .padding({ left: 4, right: 4 });
        }
        .scrollable(ScrollDirection.Horizontal)
        .height(140)
        .margin({ top: 6 });

        // 热门设计师
        Row() {
          Text('👨 热门设计师')
            .fontSize(15)
            .fontWeight(FontWeight.Bold)
            .fontColor(SP.text);
          Column().layoutWeight(1);
          Text('更多 >')
            .fontSize(10)
            .fontColor(SP.textSub);
        }
        .width('94%')
        .margin({ top: 14 });

        Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) {
          ForEach(DESIGNERS, (d: Designer) => {
            Column() {
              Text(d.avatar)
                .fontSize(32)
                .textAlign(TextAlign.Center)
                .width('100%');
              Text(d.name)
                .fontSize(12)
                .fontColor(SP.text)
                .margin({ top: 4 });
              Text(d.title)
                .fontSize(9)
                .fontColor(SP.accent);
              Text('⭐ ' + d.rating.toFixed(1))
                .fontSize(10)
                .fontColor(SP.primary)
                .margin({ top: 2 });
            }
            .width('23%')
            .backgroundColor(SP.card)
            .borderRadius(8)
            .padding(6)
            .margin({ top: 8 })
            .alignItems(HorizontalAlign.Center);
          });
        }
        .width('94%');

        // 社区热帖
        Row() {
          Text('💬 社区热帖')
            .fontSize(15)
            .fontWeight(FontWeight.Bold)
            .fontColor(SP.text);
          Column().layoutWeight(1);
          Text('更多 >')
            .fontSize(10)
            .fontColor(SP.textSub);
        }
        .width('94%')
        .margin({ top: 14 });

        ForEach(POSTS.slice(0, 2), (p: Post) => {
          Column() {
            Row() {
              Text(p.avatar)
                .fontSize(16)
                .margin({ right: 6 });
              Column() {
                Text(p.user)
                  .fontSize(12)
                  .fontColor(SP.text);
                Text(p.time)
                  .fontSize(8)
                  .fontColor(SP.textSub);
              }
              .alignItems(HorizontalAlign.Start)
              .layoutWeight(1);
            }
            .width('100%');
            Text(p.title)
              .fontSize(13)
              .fontWeight(FontWeight.Medium)
              .fontColor(SP.text)
              .width('100%')
              .margin({ top: 4 });
            Text(p.content)
              .fontSize(11)
              .fontColor(SP.textSub)
              .maxLines(1)
              .textOverflow({ overflow: TextOverflow.Ellipsis })
              .width('100%');
            Row() {
              Text('❤️ ' + p.likes)
                .fontSize(10)
                .fontColor(SP.textSub);
              Text('💬 ' + p.comments)
                .fontSize(10)
                .fontColor(SP.textSub)
                .margin({ left: 12 });
            }
            .width('100%')
            .margin({ top: 6 });
          }
          .width('94%')
          .backgroundColor(SP.cardLight)
          .borderRadius(10)
          .padding(10)
          .margin({ top: 8 });
        });

        Text('— 美丽从头开始 —')
          .fontSize(10)
          .fontColor(SP.textSub)
          .margin({ top: 16, bottom: 16 });
      }
      .width('100%')
      .alignItems(HorizontalAlign.Center);
    }
    .scrollable(ScrollDirection.Vertical)
    .width('100%')
    .height('100%');
  }

  @Builder
  quickItem(icon: string, label: string) {
    Column() {
      Text(icon)
        .fontSize(24);
      Text(label)
        .fontSize(10)
        .fontColor(SP.textSub)
        .margin({ top: 2 });
    }
    .layoutWeight(1)
    .alignItems(HorizontalAlign.Center);
  }
}

// ---------- 发型 Tab ----------
@Component struct StylesContent {
  @State styles: HairStyle[] = HAIR_STYLES;
  @State selectedCategory: string = '全部';

  build() {
    Scroll() {
      Column() {
        Row() {
          Text('💇 发型大全')
            .fontSize(16)
            .fontWeight(FontWeight.Bold)
            .fontColor(SP.text)
            .width('94%')
            .margin({ top: 12 });
        }

        // 分类筛选
        Row() {
          this.categoryChip('全部');
          this.categoryChip('男士');
          this.categoryChip('女士');
          this.categoryChip('儿童');
        }
        .width('94%')
        .margin({ top: 8 });

        Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) {
          ForEach(this.styles, (s: HairStyle) => {
            Column() {
              Text(s.icon)
                .fontSize(40)
                .textAlign(TextAlign.Center)
                .width('100%');
              Text(s.name)
                .fontSize(13)
                .fontWeight(FontWeight.Medium)
                .fontColor(SP.text)
                .margin({ top: 4 });
              Text(s.category + ' · ' + s.length)
                .fontSize(9)
                .fontColor(SP.textSub);
              Text('¥' + s.price)
                .fontSize(12)
                .fontColor(SP.accent)
                .margin({ top: 4 });
              if (s.hot) {
                Text('🔥 热')
                  .fontSize(8)
                  .fontColor(SP.primary)
                  .backgroundColor(SP.primary + '33')
                  .borderRadius(4)
                  .padding({ left: 4, right: 4, top: 1, bottom: 1 })
                  .margin({ top: 2 });
              }
            }
            .width('47%')
            .backgroundColor(SP.card)
            .borderRadius(10)
            .padding(10)
            .margin({ top: 10 })
            .alignItems(HorizontalAlign.Center);
          });
        }
        .width('94%')
        .padding({ bottom: 16 });
      }
      .width('100%');
    }
    .scrollable(ScrollDirection.Vertical)
    .width('100%')
    .height('100%');
  }

  @Builder
  categoryChip(label: string) {
    Text(label)
      .fontSize(11)
      .fontColor(this.selectedCategory === label ? SP.text : SP.textSub)
      .backgroundColor(this.selectedCategory === label ? SP.primary : SP.chip)
      .borderRadius(12)
      .padding({ left: 12, right: 12, top: 4, bottom: 4 })
      .margin({ right: 8 })
      .onClick(() => {
        this.selectedCategory = label;
        if (label === '全部') {
          this.styles = HAIR_STYLES;
        } else {
          this.styles = HAIR_STYLES.filter(s => s.category === label);
        }
      });
  }
}

// ---------- 预约 Tab ----------
@Component struct BookingContent {
  @State slots: AppointmentSlot[] = APPOINTMENT_SLOTS;
  @State selectedDesigner: number = 1;
  @State selectedSlot: number = -1;

  build() {
    Scroll() {
      Column() {
        Text('📅 预约理发')
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .fontColor(SP.text)
          .width('94%')
          .margin({ top: 12 });

        Text('选择设计师')
          .fontSize(12)
          .fontColor(SP.textSub)
          .width('94%')
          .margin({ top: 12 });

        Row() {
          ForEach(DESIGNERS, (d: Designer) => {
            Column() {
              Text(d.avatar)
                .fontSize(28);
              Text(d.name)
                .fontSize(11)
                .fontColor(SP.text)
                .margin({ top: 2 });
            }
            .padding(8)
            .backgroundColor(this.selectedDesigner === d.id ? SP.primary : SP.chip)
            .borderRadius(10)
            .margin({ right: 8 })
            .onClick(() => {
              this.selectedDesigner = d.id;
            })
            .alignItems(HorizontalAlign.Center);
          });
        }
        .width('94%')
        .margin({ top: 6 });

        Text('可选时间段')
          .fontSize(12)
          .fontColor(SP.textSub)
          .width('94%')
          .margin({ top: 16 });

        Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start }) {
          ForEach(this.slots, (s: AppointmentSlot) => {
            Column() {
              Text(s.date + ' ' + s.time)
                .fontSize(11)
                .fontColor(s.available ? SP.text : SP.textSub)
                .padding(6)
                .backgroundColor(
                  this.selectedSlot === s.id ? SP.primary :
                    s.available ? SP.cardLight : SP.chip
                )
                .borderRadius(8)
                .margin({ right: 8, bottom: 8 })
                .onClick(() => {
                  if (s.available) {
                    this.selectedSlot = s.id;
                  }
                });
            }
          });
        }
        .width('94%')
        .margin({ top: 6 });

        if (this.selectedSlot !== -1) {
          Text('已选:' + this.slots.filter(s => s.id === this.selectedSlot)[0]?.date + ' ' + this.slots.filter(s => s.id === this.selectedSlot)[0]?.time)
            .fontSize(12)
            .fontColor(SP.accent)
            .width('94%')
            .margin({ top: 10 });
          Text('确认预约')
            .fontSize(14)
            .fontColor(SP.text)
            .backgroundColor(SP.primary)
            .borderRadius(16)
            .padding({ left: 30, right: 30, top: 8, bottom: 8 })
            .margin({ top: 10 })
            .onClick(() => {
              // 模拟预约成功
            });
        } else {
          Text('请选择时间段')
            .fontSize(12)
            .fontColor(SP.textSub)
            .width('94%')
            .margin({ top: 10 });
        }

        Text('— 提前预约,避免排队 —')
          .fontSize(10)
          .fontColor(SP.textSub)
          .margin({ top: 20, bottom: 16 });
      }
      .width('100%')
      .alignItems(HorizontalAlign.Center);
    }
    .scrollable(ScrollDirection.Vertical)
    .width('100%')
    .height('100%');
  }
}

// ---------- 设计师 Tab ----------
@Component struct DesignerContent {
  @State designers: Designer[] = DESIGNERS;

  build() {
    Scroll() {
      Column() {
        Text('👨 发型设计师')
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .fontColor(SP.text)
          .width('94%')
          .margin({ top: 12 });

        ForEach(this.designers, (d: Designer) => {
          Column() {
            Row() {
              Text(d.avatar)
                .fontSize(32)
                .margin({ right: 12 });
              Column() {
                Text(d.name)
                  .fontSize(14)
                  .fontWeight(FontWeight.Medium)
                  .fontColor(SP.text);
                Text(d.title + ' · ' + d.experience)
                  .fontSize(10)
                  .fontColor(SP.textSub);
                Text('擅长: ' + d.style)
                  .fontSize(10)
                  .fontColor(SP.accent)
                  .margin({ top: 2 });
              }
              .alignItems(HorizontalAlign.Start)
              .layoutWeight(1);
              Text('⭐ ' + d.rating.toFixed(1))
                .fontSize(12)
                .fontColor(SP.primary);
            }
            .width('100%');
          }
          .width('94%')
          .backgroundColor(SP.cardLight)
          .borderRadius(10)
          .padding(10)
          .margin({ top: 10 });
        });
        Text('— 精选资深设计师 —')
          .fontSize(10)
          .fontColor(SP.textSub)
          .margin({ top: 16, bottom: 16 });
      }
      .width('100%')
      .alignItems(HorizontalAlign.Center);
    }
    .scrollable(ScrollDirection.Vertical)
    .width('100%')
    .height('100%');
  }
}

// ---------- 产品 Tab ----------
@Component struct ProductContent {
  @State products: Product[] = PRODUCTS;

  build() {
    Scroll() {
      Column() {
        Text('🧴 洗护造型产品')
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .fontColor(SP.text)
          .width('94%')
          .margin({ top: 12 });

        Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) {
          ForEach(this.products, (p: Product) => {
            Column() {
              Text(p.icon)
                .fontSize(36)
                .textAlign(TextAlign.Center)
                .width('100%');
              Text(p.name)
                .fontSize(13)
                .fontWeight(FontWeight.Medium)
                .fontColor(SP.text)
                .margin({ top: 4 });
              Text(p.brand + ' · ' + p.type)
                .fontSize(9)
                .fontColor(SP.textSub);
              Text('¥' + p.price)
                .fontSize(12)
                .fontColor(SP.accent)
                .margin({ top: 4 });
            }
            .width('47%')
            .backgroundColor(SP.card)
            .borderRadius(10)
            .padding(10)
            .margin({ top: 10 })
            .alignItems(HorizontalAlign.Center);
          });
        }
        .width('94%')
        .padding({ bottom: 16 });
      }
      .width('100%');
    }
    .scrollable(ScrollDirection.Vertical)
    .width('100%')
    .height('100%');
  }
}

// ---------- 社区 Tab ----------
@Component struct CommunityContent {
  @State posts: Post[] = POSTS;

  build() {
    Scroll() {
      Column() {
        Text('💬 美发社区')
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .fontColor(SP.text)
          .width('94%')
          .margin({ top: 12 });

        ForEach(this.posts, (p: Post) => {
          Column() {
            Row() {
              Text(p.avatar)
                .fontSize(16)
                .margin({ right: 6 });
              Column() {
                Text(p.user)
                  .fontSize(12)
                  .fontColor(SP.text);
                Text(p.time)
                  .fontSize(9)
                  .fontColor(SP.textSub);
              }
              .alignItems(HorizontalAlign.Start)
              .layoutWeight(1);
            }
            .width('100%');
            Text(p.title)
              .fontSize(13)
              .fontWeight(FontWeight.Medium)
              .fontColor(SP.text)
              .width('100%')
              .margin({ top: 4 });
            Text(p.content)
              .fontSize(11)
              .fontColor(SP.textSub)
              .maxLines(2)
              .textOverflow({ overflow: TextOverflow.Ellipsis })
              .width('100%');
            Row() {
              Text('❤️ ' + p.likes)
                .fontSize(10)
                .fontColor(SP.textSub);
              Text('💬 ' + p.comments)
                .fontSize(10)
                .fontColor(SP.textSub)
                .margin({ left: 12 });
              Column().layoutWeight(1);
              Text('发帖')
                .fontSize(10)
                .fontColor(SP.primary);
            }
            .width('100%')
            .margin({ top: 6 });
          }
          .width('94%')
          .backgroundColor(SP.cardLight)
          .borderRadius(10)
          .padding(10)
          .margin({ top: 10 });
        });
        Text('— 分享你的发型故事 —')
          .fontSize(10)
          .fontColor(SP.textSub)
          .margin({ top: 16, bottom: 16 });
      }
      .width('100%')
      .alignItems(HorizontalAlign.Center);
    }
    .scrollable(ScrollDirection.Vertical)
    .width('100%')
    .height('100%');
  }
}

// ---------- 优惠 Tab ----------
@Component struct CouponContent {
  @State coupons: Coupon[] = COUPONS;

  build() {
    Scroll() {
      Column() {
        Text('🎫 优惠券')
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .fontColor(SP.text)
          .width('94%')
          .margin({ top: 12 });

        ForEach(this.coupons, (c: Coupon) => {
          Column() {
            Row() {
              Column() {
                Text(c.name)
                  .fontSize(14)
                  .fontWeight(FontWeight.Bold)
                  .fontColor(SP.text);
                Text(c.discount)
                  .fontSize(12)
                  .fontColor(SP.accent)
                  .margin({ top: 2 });
                Text('有效期至 ' + c.validUntil)
                  .fontSize(9)
                  .fontColor(SP.textSub)
                  .margin({ top: 2 });
              }
              .alignItems(HorizontalAlign.Start)
              .layoutWeight(1);
              Text('立即领取')
                .fontSize(11)
                .fontColor(SP.text)
                .backgroundColor(SP.primary)
                .borderRadius(12)
                .padding({ left: 12, right: 12, top: 4, bottom: 4 })
                .onClick(() => {});
            }
            .width('100%');
          }
          .width('94%')
          .backgroundColor(SP.cardLight)
          .borderRadius(10)
          .padding(10)
          .margin({ top: 10 });
        });
        Text('— 更多优惠到店咨询 —')
          .fontSize(10)
          .fontColor(SP.textSub)
          .margin({ top: 16, bottom: 16 });
      }
      .width('100%')
      .alignItems(HorizontalAlign.Center);
    }
    .scrollable(ScrollDirection.Vertical)
    .width('100%')
    .height('100%');
  }
}

// ---------- 我的 Tab ----------
@Component struct MineContent {
  build() {
    Scroll() {
      Column() {
        Column() {
          Text('👤')
            .fontSize(48)
            .backgroundColor(SP.cardLight)
            .borderRadius(50)
            .width(80)
            .height(80)
            .textAlign(TextAlign.Center);
          Text('未登录')
            .fontSize(16)
            .fontWeight(FontWeight.Bold)
            .fontColor(SP.text)
            .margin({ top: 8 });
          Text('登录查看我的预约')
            .fontSize(11)
            .fontColor(SP.accent)
            .margin({ top: 2 });
        }
        .width('100%')
        .padding(20)
        .alignItems(HorizontalAlign.Center);

        Column() {
          this.menuItem('📋', '我的预约');
          this.menuItem('❤️', '收藏发型');
          this.menuItem('📝', '我的评论');
          this.menuItem('🎫', '优惠券');
          this.menuItem('⚙️', '设置');
        }
        .width('94%')
        .backgroundColor(SP.cardLight)
        .borderRadius(12)
        .padding({ left: 12, right: 12 })
        .margin({ top: 16 });

        Text('— 美丽人生,从"头"开始 —')
          .fontSize(10)
          .fontColor(SP.textSub)
          .margin({ top: 20, bottom: 16 });
      }
      .width('100%')
      .alignItems(HorizontalAlign.Center);
    }
    .scrollable(ScrollDirection.Vertical)
    .width('100%')
    .height('100%');
  }

  @Builder
  menuItem(icon: string, label: string) {
    Row() {
      Text(icon)
        .fontSize(18)
        .margin({ right: 12 });
      Text(label)
        .fontSize(14)
        .fontColor(SP.text);
      Column().layoutWeight(1);
      Text('>')
        .fontColor(SP.textSub);
    }
    .width('100%')
    .padding({ top: 12, bottom: 12 })
    .border({ width: { bottom: 0.5 }, color: SP.border });
  }
}
Logo

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

更多推荐