HarmonyOS 3D 拆解分析:登录守卫与毛玻璃视觉体系
2026/7/10 7:46:19 网站建设 项目流程

前言

之前的 3D 拆解分析是完全开放的——打开就能用,不需要任何身份验证。这在 demo 阶段没问题,但一旦要接入网络功能(发现页、AI 分析、历史记录),就需要知道"当前用户是谁"。

这次迭代做了两件事:

  1. 接入 AuthService,未登录用户强制跳转登录页
  2. 全面引入毛玻璃(frosted glass)视觉风格——半透明背景 + 全局渐变

登录守卫

AuthService 接入

import{isLoggedIn}from'../services/AuthService'

新增AuthServiceisLoggedIn方法——返回当前用户是否已登录。

aboutToAppear 的守卫

aboutToAppear():void{if(!isLoggedIn()){router.pushUrl({url:'pages/LoginPage'})return}this.loadDiscover()}

App 启动时先检查登录状态:

  1. 未登录 → 跳转 LoginPage,return不执行后续逻辑
  2. 已登录 → 正常加载发现页数据

onPageShow 的二次检查

onPageShow():void{if(!isLoggedIn()){router.pushUrl({url:'pages/LoginPage'})}}

除了启动时检查,每次页面重新显示时也检查。这防止了一种情况:用户在 App 运行期间退出登录(比如在设置页点了退出),回到首页时应该被踢到登录页。

为什么用 router.pushUrl 而不是 router.replaceUrl?

router.pushUrl({url:'pages/LoginPage'})

pushUrl会把 LoginPage 压入导航栈。用户登录成功后,可以router.back()回到首页。

如果用replaceUrl,LoginPage 会替换首页。用户登录后无法返回——因为首页已经不在导航栈里了。

登录状态对功能的影响

@StateloggedIn:boolean=false

虽然定义了loggedIn状态变量,但当前代码没有用它做条件渲染。所有功能(发现页、AI 分析)在登录后都可以使用。

后续如果要做"未登录只能看 3 个发现项,登录后看全部",可以用loggedIn控制。

全局渐变背景

旧版:纯色背景

.width('100%').height('100%').backgroundColor(BG)// BG = '#E6E0F0'

新版:全局渐变

.width('100%').height('100%').linearGradient({angle:160,colors:[['#F0EDF8',0],['#E8F0FE',0.5],['#FFF5EE',1]]})

三色渐变:

  • 起点(0%):#F0EDF8—— 淡紫
  • 中间(50%):#E8F0FE—— 淡蓝
  • 终点(100%):#FFF5EE—— 淡橙

角度 160°——从左上到右下,不是正上方到正下方。

为什么是 160° 而不是 180°?

180° 是正上方到正下方,渐变会显得"太规整"。160° 稍微偏一点,让渐变方向和用户阅读方向(从左到右)更一致,视觉上更自然。

三种颜色的搭配逻辑:

紫色(#F0EDF8)→ 蓝色(#E8F0FE)→ 橙色(#FFF5EE),是色轮上的相邻色。从冷色到暖色的过渡,给用户一种"从理性到感性"的心理暗示——左边是数据(紫色=科技),右边是体验(橙色=温暖)。

毛玻璃视觉体系

核心概念

毛玻璃(frosted glass)的本质是:半透明白色背景 + 极淡边框 + 微弱阴影。

// 统一的毛玻璃样式.backgroundColor('rgba(255,255,255,0.65)')// 65% 不透明度.border({width:1,color:'rgba(138,93,250,0.08)'})// 极淡紫色边框.shadow({radius:18,color:'rgba(138,93,250,0.06)',offsetY:3})// 紫色阴影

各组件的毛玻璃实现

统计卡片:

// 旧版.backgroundColor(CW)// 纯白// 新版.backgroundColor('rgba(255,255,255,0.70)')// 70% 白

控制面板:

// 旧版.backgroundColor(CW)// 新版.backgroundColor('rgba(255,255,255,0.80)').border({width:1,color:'rgba(138,93,250,0.06)'}).shadow({radius:10,color:'rgba(138,93,250,0.04)',offsetY:2})

功能按钮:

// 旧版.backgroundColor(this.list?AL:'#F5F5F7')// 新版(FeatureBtn).backgroundColor(active?bgColor:'#F5F5F7')

部件清单:

// 旧版.backgroundColor(CW)// 新版.backgroundColor('rgba(255,255,255,0.60)').border({width:0.5,color:'rgba(138,93,250,0.06)'})

透明度的层次

不同组件用了不同的透明度:

组件透明度为什么
统计卡片70%需要足够不透明才能看清文字
控制面板80%滑块和按钮需要高对比度
工作区65%需要透出背景渐变
部件清单60%内容密度高,需要更多透明度减轻视觉重量

越需要"看清内容"的组件,透明度越高(越接近纯白)。越需要"融入背景"的组件,透明度越低(越透明)。

点阵网格回归

旧版的点阵

之前有过 DotData 的点阵模式,后来被粒子场替代。这次又加回来了——但实现方式不同。

新版的点阵

// 生成点阵数据constdlist:DotData[]=[]for(letr:number=0;r<12;r++){for(letc:number=0;c<8;c++){dlist.push({x:(c*12.5+6).toString()+'%',y:(r*8.3+4).toString()+'%'})}}this.dots=dlist

8 列 × 12 行 = 96 个点,用百分比定位。

点阵的渲染

ForEach(this.dots,(d:DotData)=>{Circle({width:2,height:2}).fill('rgba(138,93,250,0.15)').position({x:d.x,y:d.y})})

每个点是 2×2 的紫色圆形,15% 透明度。

为什么点阵比粒子场更适合?

  1. 性能:点阵是静态的,不消耗 CPU 做动画
  2. 可控:点的位置和密度可以精确控制
  3. 简洁:不会干扰用户对内容的注意力

粒子场虽然酷炫,但作为工作区背景太"吵"了——用户需要专注看爆炸效果,不需要背景在动。

FeatureBtn:功能按钮的统一

旧版:三个独立按钮

Row(){// AI 分析按钮Row(){Text('🤖').fontSize(13).margin({right:2})Text(this.aiLoading?'分析中...':'AI 分析').fontSize(11)...}.padding(...).backgroundColor(...).onClick(...)// 部件清单按钮Row(){Text('☰').fontSize(12).fontColor(...)Text(' 部件').fontSize(11)...}.padding(...).backgroundColor(...).onClick(...)Blank()// 重置按钮Row(){Text('🔄 重置').fontSize(11)...}.padding(...).backgroundColor(...).onClick(...)}

每个按钮的样式都手写一遍,代码重复。

新版:FeatureBtn Builder

@BuilderFeatureBtn(icon:string,label:string,active:boolean,bgColor:string,action:()=>void){Row(){Text(icon).fontSize(12)Text(' '+label).fontSize(10).fontWeight(FontWeight.Medium).fontColor(active?A:T2)}.padding({left:10,right:10,top:6,bottom:6}).backgroundColor(active?bgColor:'#F5F5F7').borderRadius(12).layoutWeight(1).justifyContent(FlexAlign.Center).onClick(action)}

调用方式:

Row({space:6}){this.FeatureBtn('🤖',this.aiLoading?'分析中':'AI 识别',this.aiLoading,AL,()=>{if(!this.aiLoading){this.runAiAnalysis()}})this.FeatureBtn('📋','部件清单',this.list,AL,()=>{this.list=!this.list})this.FeatureBtn('🔄','重置',false,'#F5F5F7',()=>{this.setV(0);this.cg(3,3)})}

FeatureBtn 的设计:

  1. layoutWeight(1)—— 三个按钮等宽
  2. active控制颜色——激活时用主题色背景,否则用灰色
  3. bgColor参数——不同按钮可以有不同的激活背景色

重置按钮的特殊处理

this.FeatureBtn('🔄','重置',false,'#F5F5F7',()=>{this.setV(0);this.cg(3,3)})

重置按钮的active永远是false——它不会处于"激活"状态。bgColor'#F5F5F7'(灰色),因为重置不需要强调色。

拆解页 Header 的变化

Tag 新增爆炸状态

Row({space:6}){this.Tag('#8A5DFA','#F4F1FC',this.count+'部件')this.Tag('#00B894','#E8F8F5',this.cols+'×'+this.rows)if(this.on){this.Tag('#FF6B6B','#FFF0F0',Math.round(this.val*100)+'%')}}

爆炸时新增第三个 Tag:红色背景 + 百分比数字。用户一眼就能看到"当前爆炸力度是多少"。

空状态的数字放大

// 旧版Text(this.count.toString()).fontSize(44)// 新版Text(this.count.toString()).fontSize(48)

从 44px 增大到 48px——空状态的数字是视觉焦点,大一点更有冲击力。

网格预览的样式微调

// 旧版.backgroundColor('rgba(138,93,250,0.08)').border({width:1.5,color:'rgba(138,93,250,0.15)'})// 新版.backgroundColor('rgba(138,93,250,0.06)').border({width:1.5,color:'rgba(138,93,250,0.12)'})

背景和边框都降低了约 25% 的不透明度——点阵网格已经提供了背景纹理,网格预览不需要那么显眼。

踩坑记录

1. isLoggedIn 的调用时机

aboutToAppear():void{if(!isLoggedIn()){router.pushUrl({url:'pages/LoginPage'})return}this.loadDiscover()}

isLoggedIn()是同步调用——它读取本地存储的登录状态。如果后续改成异步(比如需要验证 token 有效性),需要用async/await

aboutToAppear():asyncvoid{constloggedIn=awaitisLoggedIn()if(!loggedIn){router.pushUrl({url:'pages/LoginPage'})return}this.loadDiscover()}

2. onPageShow 的重复检查

onPageShow在每次页面显示时都会调用。如果用户快速切换 Tab,isLoggedIn()会被频繁调用。

优化方案:在aboutToAppear中缓存登录状态,onPageShow只在状态变化时检查。

3. 毛玻璃在低端设备上的性能

半透明背景(rgba(255,255,255,0.65))需要 GPU 做 alpha 混合。在低端设备上,如果同时有多个半透明层叠,可能导致掉帧。

建议:在性能敏感的场景(比如爆炸动画进行中),可以把工作区背景改成纯白,减少 alpha 混合的层数。

4. 点阵的 ForEach 性能

96 个点用ForEach渲染——每个点都是一个独立的Circle组件。如果点阵更密(比如 20×20 = 400 个点),可能影响渲染性能。

优化方案:把点阵画在一张 Canvas 上,而不是用 96 个独立组件。

写在最后

登录守卫让 App 从"公开工具"变成了"用户产品"。用户需要注册才能使用,这意味着后续可以做个性化功能——保存分析历史、分享到发现页、AI 分析的调用次数限制。

毛玻璃视觉体系让整个 App 的视觉语言统一了。从首页的统计卡片到拆解页的控制面板,所有组件都用同样的半透明白色 + 极淡紫色边框。用户在不同页面之间切换时,视觉感受是一致的。

点阵网格的回归说明了一个道理:酷炫的动效(粒子场)不一定比静态的纹理(点阵)好。在需要用户专注的场景,安静的背景比吵闹的背景更合适。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询