从徕卡M3到哈苏500C/M,从佳能AE-1到Polaroid SX-70,从徕卡50mm夜神到哈苏XPAN宽幅——本文以一套完整的ArkTS光影相机社应用为例,深度解析HarmonyOS ArkTS API 24在复古摄影风二手交易场景下的双Tab嵌套架构、14粒子漂浮动效、传世孤品/稀有级/紧俏级/流通级四级稀有度分级、暗红复古米黄详情头、以机换机交换帖等核心技术实现。

一、引言

复古相机、镜头、胶片、暗房、摄影配件——这些承载着摄影人光影梦想的器材,在胶片复兴热潮下焕发了新的生机。从徕卡M3到哈苏500C/M,从佳能AE-1到Polaroid SX-70,从徕卡50mm夜神到哈苏XPAN宽幅,复古摄影器材二手交易已经成为一个庞大的收藏市场。然而摄影器材交易长期依赖闲鱼、转转等泛平台,缺乏针对摄影人的专业化功能——器材稀有度评级、规格尺寸区分(35mm/120/M口/G口等)、以机换机交换、暗房冲洗教程等核心需求无法得到满足。

本应用(光影相机社)以"暗红+复古米黄"复古摄影风为视觉基调,打造集器材交易、换件交换、图鉴收藏、个人中心四大模块于一体的复古摄影风二手交易与收藏社区。18款器材覆盖胶片机/单反/镜头/胶片/暗房/经典老机全品类,8条交换帖覆盖以机换机场景,5套教程覆盖暗房/摄影/维修/中画幅/选购,9款配件覆盖摄影周边,6套图鉴收藏记录收藏进度,3条圈友点评提供真实评价。

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

二、整体架构

本应用采用单组件双Tab嵌套架构——@Entry @Component struct Index作为唯一入口组件,通过@State currentBottomTab控制四大底部Tab(器材/换件/图鉴/我的),器材Tab内部再通过@State currentTopTab控制六大顶部分类Tab(全部/胶片机/单反/镜头/胶片/暗房),形成双层Tab嵌套。

架构层次:

  • 入口层:Index,负责双层Tab切换、头部、底部导航、粒子动效、弹框管理
  • 页面层:4个底部Tab对应的Builder方法(bazaarContent/swapContent/collectionContent/mineContent),器材Tab内含6个顶部Tab对应的Builder方法(cityContent/retiredContent/mocContent/figContent/techContent/streetContent)
  • 数据层:8个全局const数组(18器材+8交换帖+5教程+9配件+6图鉴+3点评+2图表数据+2弹框选项)+1个配色常量PALETTE
  • 工具函数层:10+全局纯函数(catColor/catLabel/rarityLabel/rarityColor/tradeBarHeight/rateColor/6个分类筛选函数/swapBadge)
  • 弹框层:4种弹框(发布出售/发起交换/下架/器材详情),均通过@State布尔值控制显隐

单组件架构的优势在于状态集中管理、数据共享方便、弹框统一调度,适合中等复杂度的应用。双层Tab嵌套是本应用的架构特色——器材作为主品类,内部再按胶片机/单反/镜头/胶片/暗房细分,摄影人可以快速切换品类浏览。

三、色彩系统:暗红+复古米黄复古摄影风

复古摄影风的视觉语言应该是"复古、文艺、有暗房的氛围感"。本应用采用暗红+复古米黄配色:

主色体系:

  • #F5F1E8 复古米黄:应用根背景、浅色卡片背景——代表老照片的泛黄质感
  • #FFFFFF 纯白:卡片背景、弹框背景、底部Tab背景——代表层次
  • #8B2E2E 暗红:主高亮色、Tab选中态、按钮、标签、渐变——代表暗房红灯的氛围感
  • #3B2B2B 深褐:头部渐变终点、最深背景——代表深邃
  • #C9A24B 复古金:价格、等级标签、统计数字、交换弹框头部、Banner渐变——代表老镜头的金色镀膜
  • #6B8E6B 复古绿:辅助色、Tab下划线、稀有度流通级色——代表自然的生机
  • #8A8577 烟灰:辅助文字、未选中Tab、说明文字——代表素雅
  • #E5E1D5 浅米:分割线、进度条背景——代表层次

浅色背景层次(浅色主题下的层次):

  • #F5F1E8 复古米黄:应用根背景
  • #FFFFFF 纯白:卡片背景、弹框背景
  • #F0E5E5 浅红:高亮卡片背景、选中态背景、标签背景
  • #F0EAD8 浅金:高亮卡片背景、教程步骤背景、选中态背景
  • #E5E1D5 浅米:分割线、进度条背景

渐变设计:

  • 头部:linearGradient angle 135 从#8B2E2E到#3B2B2B——暗红到深褐的复古渐变
  • 全部Tab Banner:linearGradient angle 120 从#C9A24B到#E2CE94——复古金到浅金的闪耀渐变
  • 胶片机Tab横滑大卡:linearGradient angle 160 从#8B2E2E到#3B2B2B——暗红到深褐
  • 胶片Tab对决卡:linearGradient angle 150 从#8B2E2E到#3B2B2B——暗红到深褐
  • 我的页会员卡:linearGradient angle 120 从#8B2E2E到#3B2B2B——暗红到深褐
  • 发布出售弹框头部:linearGradient angle 120 从#8B2E2E到#3B2B2B——暗红到深褐
  • 器材详情弹框头部:linearGradient angle 135 从#C9A24B到#F0E5E5——复古金到浅红的闪耀渐变

暗红+复古米黄的配色通过复古米黄根背景+纯白卡片+浅红/浅金高亮背景营造复古摄影风格的文艺氛围感,暗红#8B2E2E作为主高亮和按钮色,复古金#C9A24B作为Tab下划线和等级色,复古绿#6B8E6B作为稀有度流通级色,确保视觉一致性和复古摄影风韵味。本应用是所有主题中渐变使用最多的(7处渐变),营造出丰富的视觉层次。

四、数据模型

应用定义了7个接口,覆盖摄影器材二手交易全链路:

  • GearItem器材(id/name/eng/cat/price/rarity/year/rating/starStr/seller/tag/desc/want/sales/emoji/size)——18款,含中英文名称、分类、稀有度0-100、发布年份、规格尺寸(35mm/120/M口/G口等)、卖家想换等二手交易特色字段
  • SwapItem交换帖(id/user/avatar/offer/want/time/likes/content/place)——8条交换帖,含我提供/我想换/地点/点赞数
  • GuideItem摄影教程(id/name/type/pages/author/likes/downloads/emoji/steps)——5套教程,含步骤数组
  • AccessoryItem配件周边(id/name/series/price/condition/seller/emoji/desc)——9款配件
  • CollectionItem图鉴收藏(id/name/series/owned/total/rate/emoji)——6套图鉴,含已收/总数/进度百分比
  • GearReview圈友点评(id/user/setName/starStr/content)——3条点评
  • ColorPalette配色(bg/card/red/cream/deep/gold/green/sub/line)——9色配色常量

rarity稀有度字段是摄影器材的特色设计——0-100数值,通过rarityLabel函数映射为四级(传世孤品≥95/稀有级≥80/紧俏级≥60/流通级<60),通过rarityColor函数映射为四色(暗红/橙/亮蓝/复古绿),在柱状图和器材详情中直接渲染。这是本应用区别于其他主题的特色——稀有度标签不是标准的S/A/B/C,而是更符合摄影收藏语境的"传世孤品/稀有级/紧俏级/流通级"。size规格字段区分35mm/120/M口/G口等不同规格,want卖家想换字段支持以机换机交易场景。

五、Tab0 器材交易(双Tab嵌套)

器材页是应用的核心,采用底部Tab+顶部Tab双层嵌套架构。顶部6个分类Tab(全部/胶片机/单反/镜头/胶片/暗房),每个Tab有独立的布局风格:

全部Tab:Banner+双列瀑布

  • 复古金渐变Banner:复古摄影节春季专场+经典器材3天限时卖家免服务费+顶级收藏/胶卷专区标签
  • 全城新上架:双列瀑布布局,左列2件(爱克发Optima/美能达X-700),右列1件(哈苏XPAN,浅红高亮背景),每件含emoji/中文名/英文名/描述/价格/标签

胶片机Tab:横滑大卡+稀有度柱状图+捡漏榜

  • 顶级收藏专区:3件横滑大卡(徕卡M3/哈苏500C/M/佳能AE-1),暗红渐变背景160宽,含emoji/名称/英文+年份/价格+稀有度标签
  • 稀有度排行:3根柱状图(90/85/75),第三根佳能AE-1用复古金高亮,底部说明"徕卡M3以90分稀有度登顶,市面流通极少"
  • 今日捡漏榜:3件排行列表,第1名暗红数字,含排名/emoji/名称+稀有度+卖家想换/价格

单反Tab:教程时间轴

  • 5套教程时间轴布局(暗房冲洗入门/胶片摄影基础/徕卡相机维修/中画幅摄影入门/老相机购买指南),左侧emoji+复古金竖线连接,右侧卡片含名称/下载数/作者+类型+页数/步骤列表(带序号圆点)/点赞+教程可下载

镜头Tab:三列格子+交换建议

  • 镜头交易三列网格(9款配件,31%宽度),每件含emoji/名称/系列/价格
  • 配件交换行情:偶数ID配件的交换列表,含emoji/名称+成色/描述/价格(复古绿)

胶片Tab:对决卡+侧栏统计

  • 器材对决:徕卡M3 VS 徕卡50mm,两张暗红渐变对决卡中间VS标识
  • 左侧3件单反机械列表(尼康F3/奥林巴斯OM-1/玛米亚RZ67),右侧3格统计(12本周器材成交暗红/2.2万器材总交易额复古金/96%好评率复古绿)

暗房Tab:标签云+紧凑列表

  • 暗房收藏标签云:6套图鉴(徕卡/中画幅/尼康/镜头/胶片/暗房),浅红背景chip
  • 3件紧凑列表(柯达Retina IIa/福伦达Bessa R2A/禄来35S),第3件浅红高亮背景,含稀有度彩色标签
  • 底部提示:集齐三大相机可召唤隐藏福利:徕卡+哈苏+XPAN

双层Tab嵌套让摄影人可以在器材主Tab内快速切换6大品类,每个品类有独立的视觉布局和数据展示方式,避免单一布局的单调感。

六、Tab1 换件交换

换件页是摄影器材二手交易的特色功能——以机换机。由两个层次构成:

1. 统计条+发交换按钮:四格统计(156在交换中暗红/42今日成交复古金/98%面交好评复古绿)+右侧发交换按钮(暗红底,触发发起交换弹框)。

2. 交换帖列表:8条交换帖卡片,每帖含:

  • 头部:头像emoji+用户名+热度标签(🔥热门≥50/👍热度≥30/🌱新帖<30,通过swapBadge函数动态生成)+时间+地点+右侧⋯菜单(触发下架弹框)
  • 交换区:我提供(浅红背景,暗红标题)⇄我想换(浅金背景,暗红标题),左右对称布局
  • 内容:帖文描述
  • 底部:📍地点标签(暗红底复古米黄背景)+❤️点赞数(暗红)

换件页解决了摄影器材二手交易中"以机换机"的核心需求——摄影人可以用自己的闲置器材(徕卡M3/哈苏500C/M/徕卡50mm/暗房配方/Polaroid SX-70/哈苏XPAN/奥林巴斯OM-1/胶卷)交换心仪的器材,通过地点标签支持汉口江滩面交和线上交换,通过热度标签筛选热门交换帖。

七、Tab2 图鉴收藏

图鉴页是摄影器材收藏进度管理功能。由三个层次构成:

1. 标题+登记按钮:我的摄影图鉴标题+记录每一件器材的收藏进度+右侧✚登记按钮(暗红底,触发发布出售弹框复用)。

2. 图鉴进度列表:6套图鉴(徕卡/中画幅/尼康/镜头/胶片/暗房),每套含:

  • 头部:emoji+名称+英文系列名+已收X/总数+右侧进度百分比(通过rateColor函数动态着色:≥55复古绿/≥40复古金/<40暗红)
  • 进度条:双色进度条(已收部分rateColor色+未收部分浅米),宽度通过百分比动态计算

3. 图鉴成就墙:4个成就标签(🎖️徕卡收藏家/🏆暗房大师/📷胶卷摄影家/🔭镜头专家),不同颜色文字。

图鉴页让摄影人可以系统化管理自己的收藏进度,通过进度条和百分比直观看到每套图鉴的完成度,通过成就墙增加收藏的趣味性和成就感。

八、Tab3 个人中心

我的页是摄影人个人信息管理。由三个层次构成:

1. 会员信息卡:暗红渐变背景,含🎞️头像+摄影收藏家老影+LV.10资深摄影人·信用分990+右侧>箭头+三格统计(38在售器材复古金/12求购中复古金/¥6.8万累计成交额复古金)。

2. 我的求购清单:3件求购器材(柯达Retina IIa/哈苏XPAN/美能达X-700),每件含emoji/名称+预算+卖家想换/右侧出价中标签(复古金底浅金背景)。

3. 常去面交点:5个地点列表(汉口江滩/徐东古玩城/洪山广场站/楚河汉街站/线上互换),每个含不同emoji(🚇/🏬/🚌/🏪/📦)+地点名+右侧站点说明(汉口站台/徐东入口/洪山转盘/楚河入口/顺丰网点)。

我的页通过求购清单和常去面交点两个特色功能,将摄影器材二手交易的线下场景融入个人中心,让摄影人可以管理自己的求购器材和常去面交地点。

九、弹框体系

本应用有4种弹框,均通过@State布尔值控制显隐,zIndex通过Stack层叠实现:

1. 发布出售弹框(新增):88%宽76%高,暗红渐变头部(📷发布出售+闲置回血神机不愁卖),滚动内容含:要出售的器材(8个器材chip选择,选中暗红底白字)+成色说明(5档chip:全新未拆/仅拆封/9成新/8成新/有瑕疵,选中复古金底白字)+出售价格(−/¥价格/+步进器,步进10元,价格>20000显示"高价好物建议包邮"否则"实惠价更容易出手")+宝贝描述(TextInput输入)+取消/上架出售双按钮。

2. 发起交换弹框(新增):88%宽72%高,复古金头部(🤝发起交换+用闲置换心头好摄友互助),滚动内容含:我提供(5个器材chip选择,选中深褐底白字)+我想换可多选(5个器材chip,选中暗红底白字带✓)+面交地点(5个地点chip,选中暗红底白字)+安全提示(💡交换双方可自行协商补差价,面交请选择人流密集的公共场所,注意安全)+再想想/发布交换帖双按钮。

3. 下架弹框(删除):72%宽居中,🗑️图标+下架这件器材?+说明文字(下架后买家将无法搜索到这条信息,收藏和留言会一并清空,可重新上架)+留着(暗红底浅红背景)/确认下架(暗红底白字)双按钮。

4. 器材详情弹框:88%宽78%高,复古金到浅红渐变头部(emoji+中文名+英文名+标签+稀有度标签),滚动内容含:四格数据(售价暗红/规格暗红/稀有度动态色/年份复古金)+宝贝描述(描述文字+卖家+星级评分)+卖家想换(🤝+卖家想换,浅金背景)+圈友点评(3条点评卡片)+留言问问(暗红底浅红背景)/立即购买(暗红底白字)双按钮。

所有弹框均通过Stack层叠+半透明黑色背景(99000000)+居中布局实现,点击背景区域关闭弹框。

十、核心技术特性

1. 双Tab嵌套架构:底部4Tab+器材Tab内部顶部6Tab,通过两个@State(currentBottomTab/currentTopTab)独立控制,if-else链分发到对应的Builder方法,实现双层分类浏览。

2. 14粒子漂浮动效:aboutToAppear生命周期中buildParticles生成14个粒子(📷/🎞️/🔭/🧪/🎬五种emoji随机,大小12-22px,速度0.6-2.0,透明度0.2-0.6),setInterval每80ms调用driftParticles更新x坐标(超出360重置为-20),通过position绝对定位漂浮在页面上,营造复古摄影氛围。aboutToDisappear中clearInterval清理定时器避免内存泄漏。

3. 传世孤品/稀有级/紧俏级/流通级四级稀有度分级:rarity字段0-100数值,通过rarityLabel映射为四级标签(传世孤品≥95/稀有级≥80/紧俏级≥60/流通级<60),通过rarityColor映射为四色(暗红/橙/亮蓝/复古绿),在柱状图、器材详情、紧凑列表中统一渲染,数据驱动UI。这是本应用区别于其他主题的特色——稀有度标签不是标准的S/A/B/C,而是更符合摄影收藏语境的自定义标签。

4. 暗红复古米黄头部设计:头部使用暗红#8B2E2E到深褐#3B2B2B的linearGradient渐变,白色文字和标签在深色背景上形成鲜明对比,营造复古摄影风格的文艺氛围感。

5. 以机换机交换帖:换件页每条帖子采用我提供(浅红背景,暗红标题)⇄我想换(浅金背景,暗红标题)的对称布局,通过swapBadge函数根据点赞数动态生成热度标签(🔥热门/👍热度/🌱新帖),支持汉口江滩面交和线上交换,解决摄影器材二手交易中的以机换机需求。

6. 全局纯函数工具集:10+全局纯函数(catColor/catLabel/rarityLabel/rarityColor/tradeBarHeight/rateColor/6个分类筛选函数/swapBadge),将数据到UI的映射逻辑抽离为纯函数,便于复用和维护,符合函数式编程思想。

7. 分类筛选函数:6个函数(retiredSets/mocSets/figSets/techSets/streetSets/classicSets)通过数组切片返回对应分类的3件器材,cityLeft/cityRight返回全部Tab的双列数据,hotSets返回热门器材,数据筛选逻辑清晰。

8. 详情数据取值方法:14个detailXxx方法(detailName/detailEng/detailEmoji/detailPrice/detailSize/detailRarity/detailYear/detailSeller/detailTag/detailStar/detailRating/detailDesc/detailWant)通过遍历GEARS数组查找selectedGearId对应的器材字段,在详情弹框中调用,避免在Builder中写复杂的查找逻辑。

9. 步进器价格输入:发布出售弹框的价格采用−/¥价格/+步进器设计,步进10元,通过@State sellPrice控制,价格>20000时动态显示"高价好物建议包邮"提示,交互友好。

10. Stack层叠弹框管理:4种弹框通过Stack层叠+@State布尔值控制,半透明黑色背景99000000,点击背景关闭,弹框内容居中,zIndex自动由Stack层叠顺序决定,无需手动管理zIndex。

11. 7处渐变设计:本应用是所有主题中渐变使用最多的,头部、全部Tab Banner、胶片机Tab横滑大卡、胶片Tab对决卡、我的页会员卡、发布出售弹框头部、器材详情弹框头部均使用linearGradient渐变,营造出丰富的视觉层次和复古摄影风韵味。

十一、同类对比

维度 通用二手平台 本应用(光影相机社)
主题 浅色/蓝色为主 暗红+复古米黄复古摄影风
架构 单Tab或简单分类 双Tab嵌套(底部4+顶部6)
动效 无或简单 14个粒子漂浮动效
稀有度 无或简单星级 0-100数值+传世孤品/稀有级/紧俏级/流通级四级+四色映射
以机换机 无或简单留言 交换帖+我提供⇄我想换对称布局
暗房教程 无或外部链接 5套时间轴布局教程+步骤列表
器材图鉴 无或简单收藏 6套图鉴+进度条+成就墙
求购清单 3件求购器材+预算+出价中
常去面交点 5个地点+站点说明
弹框 2-3种 4种(发布出售/发起交换/下架/详情)
渐变 无或1处 7处渐变设计

十二、完整代码结构总览

1318.ets
├── 数据结构(7个interface)
├── 静态配置(PALETTE配色 + 2个Tab配置 + 2个弹框选项 + 2个图表数据)
├── 静态数据(8个数组:18器材+8交换帖+5教程+9配件+6图鉴+3点评)
├── 全局纯函数(10+个:catColor/catLabel/rarityLabel/rarityColor/rateColor/6分类筛选/swapBadge)
├── Index入口组件(@Entry @Component)
│   ├── 状态(currentBottomTab/currentTopTab/selectedGearId/4个弹框显隐/发布出售表单/发起交换表单/particles粒子)
│   ├── 生命周期(aboutToAppear生成粒子+启动定时器/aboutToDisappear清理定时器)
│   ├── 粒子方法(buildParticles/driftParticles)
│   ├── 详情取值方法(14个detailXxx)
│   ├── 头部Builder
│   ├── 顶部Tab Builder
│   ├── 6个顶部Tab内容Builder(city/retired/moc/fig/tech/street)
│   ├── 器材首页Builder(bazaarContent)
│   ├── 换件页Builder(swapContent)
│   ├── 图鉴页Builder(collectionContent)
│   ├── 我的页Builder(mineContent)
│   ├── 底部Tab Builder
│   ├── 4种弹框Builder(sellModal/swapModal/deleteModal/detailModal)
│   ├── 交换多选辅助方法(pickedWant/toggleWant)
│   └── build主布局(Stack层叠+Column内容+粒子+4弹框)

十三、开发环境搭建

13.1 环境要求

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

13.2 安装DevEco Studio

DevEco Studio 安装界面

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

13.3 配置SDK

SDK 配置界面

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

13.4 创建项目

创建项目界面

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

13.5 运行应用

运行应用界面

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

13.6 预览调试

预览调试界面

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

十四、总结展望

本文完整解析了基于HarmonyOS ArkTS API 24的光影相机社应用,从暗红+复古米黄复古摄影配色系统、双Tab嵌套架构、器材数据模型(含稀有度0-100/规格尺寸/卖家想换等特色字段)、器材交易六大品类独立布局(全部双列瀑布/胶片机横滑大卡+稀有度柱状图+捡漏榜/单反教程时间轴/镜头三列网格/胶片对决卡+侧栏统计/暗房标签云+紧凑列表)、换件以机换机交换帖、图鉴收藏进度条、个人中心求购清单+常去面交点,到4种弹框体系、14粒子漂浮动效、传世孤品/稀有级/紧俏级/流通级四级稀有度分级、暗红复古米黄头部、7处渐变设计、全局纯函数工具集、详情数据取值方法,展现了ArkTS在复古摄影风二手交易场景下的完整工程实践。

核心价值:

  1. 暗红+复古米黄复古摄影配色:复古风格的文艺氛围感,暗红高亮营造暗房红灯氛围
  2. 双Tab嵌套架构:底部4Tab+顶部6Tab,双层分类浏览体验
  3. 14粒子漂浮动效:setInterval驱动emoji粒子漂浮,aboutToDisappear清理定时器
  4. 传世孤品/稀有级/紧俏级/流通级四级稀有度分级:0-100数值→四级自定义标签→四色映射,数据驱动UI,更符合摄影收藏语境
  5. 以机换机交换帖:我提供⇄我想换对称布局+热度标签动态生成+汉口江滩面交
  6. 器材图鉴进度管理:6套图鉴+双色进度条+成就墙,收藏系统化
  7. 7处渐变设计:所有主题中渐变使用最多,营造丰富视觉层次
  8. 全局纯函数工具集:10+纯函数抽离数据到UI映射逻辑,代码可维护

未来可扩展:

  • 接入真实摄影器材数据库,自动识别器材类型和规格,替代手动分类
  • 粒子动效接入设备陀螺仪,随手机倾斜方向漂移,增强沉浸感
  • 稀有度接入真实成交数据和市场行情,动态更新器材稀有度评分
  • 以机换机接入智能匹配算法,根据器材类型和价值推荐交换对象
  • 器材图鉴接入器材扫码识别,自动更新器材收藏记录
  • 接入摄影展会推荐功能,根据器材类型推荐适合的摄影展会活动
  • 求购清单接入推送通知,有匹配器材时自动提醒摄影人

光影相机社,让每一台老相机都找到懂它的摄影人,让暗红流转、复古米黄生香。


附录:完整源码

// ============================================================
// 场景:复古相机/镜头/胶片/暗房/摄影配件的二手交易与收藏社区(复古摄影风)
// 风格:暗红 #8B2E2E + 复古米黄 #F5F1E8 复古摄影风
// 底部Tab:器材 / 换件 / 图鉴 / 我的
// 顶部Tab:全部 / 胶片机 / 单反 / 镜头 / 胶片 / 暗房
// 弹框:发布出售(新增) / 发起交换(新增) / 下架(删除) / 器材详情(详情)
// ============================================================
// ---------------- 配色 ----------------
interface ColorPalette {
bg: string;
card: string;
red: string;
cream: string;
deep: string;
gold: string;
green: string;
sub: string;
line: string;
}
const PALETTE: ColorPalette = {
bg: '#F5F1E8',
card: '#FFFFFF',
red: '#8B2E2E',
cream: '#F5F1E8',
deep: '#3B2B2B',
gold: '#C9A24B',
green: '#6B8E6B',
sub: '#8A8577',
line: '#E5E1D5'
};
// ---------------- 通用结构 ----------------
interface TabItem { label: string; icon: string; }
interface ParticleItem { x: number; emoji: string; size: number; speed: number; opacity: number; }
// ---------------- 器材条目 ----------------
interface GearItem {
id: number; name: string; eng: string; cat: string; price: number;
rarity: number; year: number; rating: number; starStr: string; seller: string;
tag: string; desc: string; want: string; sales: number; emoji: string; size: string;
}
// ---------------- 交换帖 ----------------
interface SwapItem {
id: number; user: string; avatar: string; offer: string; want: string;
time: string; likes: number; content: string; place: string;
}
// ---------------- 教程/攻略 ----------------
interface GuideItem {
id: number; name: string; type: string; pages: number; author: string;
likes: number; downloads: number; emoji: string; steps: string[];
}
// ---------------- 配件/周边 ----------------
interface AccessoryItem {
id: number; name: string; series: string; price: number; condition: string;
seller: string; emoji: string; desc: string;
}
// ---------------- 图鉴收藏 ----------------
interface CollectionItem {
id: number; name: string; series: string; owned: number; total: number; rate: number; emoji: string;
}
// ---------------- 点评 ----------------
interface GearReview {
id: number; user: string; setName: string; starStr: string; content: string;
}
// ---------------- Tab 配置 ----------------
const BOTTOM_TABS: TabItem[] = [
{ label: '器材', icon: '📷' }, { label: '换件', icon: '🤝' }, { label: '图鉴', icon: '📖' }, { label: '我的', icon: '🎞️' }
];
const TOP_TABS: TabItem[] = [
{ label: '全部', icon: '🧿' }, { label: '胶片机', icon: '📷' }, { label: '单反', icon: '📸' },
{ label: '镜头', icon: '🔭' }, { label: '胶片', icon: '🎞️' }, { label: '暗房', icon: '🌑' }
];
// ---------------- 器材数据(18款写死) ----------------
const GEARS: GearItem[] = [
{ id: 1, name: '徕卡 M3', eng: 'Leica M3', cat: 'retired', price: 32000, rarity: 90, year: 1954, rating: 5.0, starStr: '⭐⭐⭐⭐⭐', seller: '德味老店', tag: '传世经典', desc: '徕卡M3,完美成色,黄斑对焦清晰,快门声清脆,机械感极强,收藏级。', want: '换 徕卡M6', sales: 1, emoji: '📷', size: '35mm' },
{ id: 2, name: '哈苏 500C/M', eng: 'Hasselblad 500C/M', cat: 'retired', price: 15800, rarity: 85, year: 1970, rating: 4.9, starStr: '⭐⭐⭐⭐⭐', seller: '中画幅玩家', tag: '极致锐利', desc: '哈苏500C/M,全套A12后背,镜头镀膜完美,反转片专业户首选。', want: '换 玛米亚', sales: 2, emoji: '🎞️', size: '120' },
{ id: 3, name: '佳能 AE-1', eng: 'Canon AE-1', cat: 'retired', price: 2800, rarity: 75, year: 1976, rating: 4.7, starStr: '⭐⭐⭐⭐', seller: '日系情怀所', tag: '入门经典', desc: '佳能AE-1,快门清脆,配50mm 1.4标头,随拿随拍超好看。', want: '换 奥林巴斯', sales: 9, emoji: '📷', size: '135' },
{ id: 4, name: '暗房冲洗配方集', eng: 'D76 & C41 Formula', cat: 'moc', price: 39, rarity: 30, year: 2025, rating: 4.8, starStr: '⭐⭐⭐⭐✨', seller: '深色药师', tag: '复古配方', desc: '含D76、Dektol、C41彩负黑白反转等全套配方,附操作步骤,适合自冲。', want: '可换胶卷', sales: 126, emoji: '🧪', size: '电子版' },
{ id: 5, name: '彩色放大暗房教程', eng: 'Color Enlarging', cat: 'moc', price: 58, rarity: 40, year: 2024, rating: 4.7, starStr: '⭐⭐⭐⭐', seller: '红光之下', tag: '暗房必学', desc: '从负片到相纸,涵盖放大机操作、滤镜校色、冲洗步骤,送定制相纸样品。', want: '换 试机卷', sales: 98, emoji: '💡', size: '电子版' },
{ id: 6, name: 'Polaroid SX-70', eng: 'Polaroid SX-70', cat: 'moc', price: 4200, rarity: 80, year: 1972, rating: 4.9, starStr: '⭐⭐⭐⭐⭐', seller: '拍立得修理匠', tag: '折叠大拿', desc: '全球唯一折叠单反拍立得,皮腔完好,自动测光,记录当下瞬间的复古色彩。', want: '换 宝丽来SLR680', sales: 6, emoji: '🖼️', size: 'SX-70' },
{ id: 7, name: '徕卡 50mm f/1.4', eng: 'Summilux-M 50', cat: 'fig', price: 18000, rarity: 92, year: 1961, rating: 4.9, starStr: '⭐⭐⭐⭐⭐', seller: '镜头博物馆老白', tag: '夜神之眼', desc: '完美玻璃无霉无雾,光圈全开柔美无比,焦外如奶油般化开,极品。', want: '换 徕卡 35mm', sales: 1, emoji: '🔭', size: 'M口' },
{ id: 8, name: '蔡司 35mm f/2', eng: 'Zeiss Biogon 35', cat: 'fig', price: 8900, rarity: 85, year: 2005, rating: 4.8, starStr: '⭐⭐⭐⭐✨', seller: '德系玻璃控', tag: '锐利之王', desc: 'G系列镜头,T*镀膜抗眩光极佳,色彩浓郁,微反差极佳,扫街必备。', want: '换 徕卡R', sales: 3, emoji: '🔭', size: 'G口' },
{ id: 9, name: '尼康 85mm f/1.4', eng: 'Nikkor 85mm', cat: 'fig', price: 6500, rarity: 75, year: 1981, rating: 4.6, starStr: '⭐⭐⭐⭐', seller: '人像大师傅', tag: '空气切割', desc: 'AIS手动人像头,全开光圈奶油般的背景虚化,女神必备,镜组干净通透。', want: '换 85mm f/1.2', sales: 5, emoji: '🔭', size: 'AIS' },
{ id: 10, name: '尼康 F3', eng: 'Nikon F3 HP', cat: 'tech', price: 5200, rarity: 80, year: 1980, rating: 4.9, starStr: '⭐⭐⭐⭐⭐', seller: '新闻机收藏铺', tag: '钛合金旗舰', desc: '当年新闻机之王,高眼点取景器,快门横走金属帘,机械与电子的完美结合。', want: '换 尼康 F2', sales: 7, emoji: '📷', size: '135' },
{ id: 11, name: '奥林巴斯 OM-1', eng: 'Olympus OM-1', cat: 'tech', price: 3800, rarity: 68, year: 1972, rating: 4.8, starStr: '⭐⭐⭐⭐✨', seller: '口袋机械所', tag: '小巧精致', desc: '当时最小巧的全画幅单反,双轴减震卷片器,拿在手里像艺术品。', want: '换 美能达X700', sales: 10, emoji: '📷', size: '135' },
{ id: 12, name: '玛米亚 RZ67', eng: 'Mamiya RZ67', cat: 'tech', price: 9800, rarity: 60, year: 1982, rating: 4.7, starStr: '⭐⭐⭐⭐', seller: '影棚大画幅', tag: '终极画质', desc: '6x7中画幅,皮腔对焦,镜头群极其庞大,商业静物与婚纱影棚的终极武器。', want: '换 哈苏500', sales: 4, emoji: '🎞️', size: '6x7' },
{ id: 13, name: '柯达 Retina IIa', eng: 'Kodak Retina IIa', cat: 'street', price: 2400, rarity: 65, year: 1949, rating: 4.8, starStr: '⭐⭐⭐⭐✨', seller: '折叠老兵', tag: '战前经典', desc: '折叠式机身,罗德刚50mm f/2镜头,极具年代感,出片锐利清晰。', want: '换 福伦达', sales: 12, emoji: '📷', size: '135' },
{ id: 14, name: '福伦达 Bessa R2A', eng: 'Voigtlander R2A', cat: 'street', price: 4200, rarity: 55, year: 2004, rating: 4.9, starStr: '⭐⭐⭐⭐⭐', seller: '日系器材店', tag: '实用旁轴', desc: '性价比极高的旁轴机身,电子快门安静轻巧,可转接各种徕卡M口镜头。', want: '换 徕卡CL', sales: 8, emoji: '📷', size: '135' },
{ id: 15, name: '禄来 35S', eng: 'Rolleiflex 35S', cat: 'street', price: 3500, rarity: 70, year: 1966, rating: 4.7, starStr: '⭐⭐⭐⭐', seller: '掌心传奇', tag: '便携神机', desc: '世界最小全画幅胶卷机,天塞镜头,做工精美,装进口袋随时记录生活。', want: '换 奥林巴斯XA', sales: 11, emoji: '🕶️', size: '135' },
{ id: 16, name: '哈苏 XPAN', eng: 'Hasselblad XPAN', cat: 'classic', price: 15000, rarity: 90, year: 1998, rating: 4.9, starStr: '⭐⭐⭐⭐⭐', seller: '全景宽幅者', tag: '宽幅神兵', desc: '极其罕见的宽幅相机,24x65画幅,拍出的照片如同电影截图,非常有冲击力。', want: '换 禄来6008', sales: 2, emoji: '🎬', size: '135宽幅' },
{ id: 17, name: '爱克发 Optima', eng: 'Agfa Optima', cat: 'classic', price: 1200, rarity: 45, year: 1959, rating: 4.5, starStr: '⭐⭐⭐⭐', seller: '德国老古董', tag: '自动快门', desc: '世界上第一台全自动曝光相机,金属机身非常重,出片有着独特的德味复古色彩。', want: '换 蔡司依康', sales: 13, emoji: '📷', size: '135' },
{ id: 18, name: '美能达 X-700', eng: 'Minolta X-700', cat: 'classic', price: 1800, rarity: 50, year: 1981, rating: 4.6, starStr: '⭐⭐⭐⭐', seller: '元祖黑机', tag: '程序自动', desc: '当年荣获欧洲相机大奖,P档自动曝光,机身稍带磨损,但功能一切正常。', want: '换 尼康FM2', sales: 8, emoji: '📷', size: '135' }
];
// ---------------- 交换帖数据(8条写死) ----------------
const SWAPS: SwapItem[] = [
{ id: 1, user: '德味老店', avatar: '📷', offer: '徕卡M3', want: '徕卡M6', time: '今天 13:20', likes: 46, content: '经典徕卡M3换徕卡M6,可补差价,面交。', place: '汉口江滩' },
{ id: 2, user: '中画幅玩家', avatar: '🎞️', offer: '哈苏500C/M', want: '玛米亚RZ67', time: '今天 11:05', likes: 38, content: '哈苏换玛米亚,都是中画幅,可补差价,诚心换。', place: '徐东古玩城' },
{ id: 3, user: '镜头博物馆老白', avatar: '🔭', offer: '徕卡50mm', want: '徕卡35mm', time: '昨天 18:42', likes: 61, content: '徕卡50换徕卡35,都是顶级头,可补差价,诚心换。', place: '洪山广场站' },
{ id: 4, user: '深色药师', avatar: '🧪', offer: '暗房配方', want: '任意胶卷', time: '昨天 15:30', likes: 29, content: '电子版配方免费换,换取任意有缘的胶卷,学生党优先。', place: '线上交换' },
{ id: 5, user: '拍立得修理匠', avatar: '🖼️', offer: 'Polaroid SX-70', want: '宝丽来SLR680', time: '前天 20:15', likes: 22, content: 'SX-70换SLR680,都是拍立得,可补差价,诚心换。', place: '楚河汉街站' },
{ id: 6, user: '全景宽幅者', avatar: '🎬', offer: '哈苏XPAN', want: '禄来6008', time: '前天 09:50', likes: 41, content: 'XPAN换禄来6008,都是顶级,补差价换,可聊聊看。', place: '线上互换' },
{ id: 7, user: '口袋机械所', avatar: '📷', offer: '奥林巴斯OM-1', want: '美能达X700', time: '3天前 22:08', likes: 55, content: 'OM-1换X700,都是好机,愿补差价,面交优先。', place: '武昌火车站' },
{ id: 8, user: '新手玩家', avatar: '🎞️', offer: '胶卷', want: '相机', time: '4天前 14:26', likes: 17, content: '胶卷换相机,都是入门,学生党不容易,大家帮帮忙。', place: '线上交换' }
];
// ---------------- 教程/攻略数据(5条写死) ----------------
const GUIDES: GuideItem[] = [
{ id: 1, name: '暗房冲洗入门', type: '暗房', pages: 20, author: '深色药师', likes: 342, downloads: 2100, emoji: '🧪', steps: ['药水配制 1-8页', '温度控制 9-15页', '显影定影 16-20页'] },
{ id: 2, name: '胶片摄影基础', type: '摄影', pages: 35, author: '胶卷情怀', likes: 276, downloads: 1580, emoji: '🎞️', steps: ['曝光补偿 1-10页', '胶片选择 11-20页', '冲洗扫描 21-35页'] },
{ id: 3, name: '徕卡相机维修', type: '维修', pages: 40, author: '老相机维修师', likes: 415, downloads: 3300, emoji: '🔧', steps: ['快门修理 1-15页', '测距仪校准 16-28页', '镜头保养 29-40页'] },
{ id: 4, name: '中画幅摄影入门', type: '中画幅', pages: 30, author: '中画幅玩家', likes: 198, downloads: 1260, emoji: '🎞️', steps: ['相机类型 1-10页', '镜头选择 11-20页', '冲洗流程 21-30页'] },
{ id: 5, name: '老相机购买指南', type: '选购', pages: 25, author: '德味老店', likes: 233, downloads: 1420, emoji: '📷', steps: ['成色判断 1-10页', '常见故障 11-18页', '价格参考 19-25页'] }
];
// ---------------- 配件/周边数据(9条写死) ----------------
const ACCESSORIES: AccessoryItem[] = [
{ id: 1, name: '真皮相机背带', series: '复古', price: 80, condition: '全新', seller: '摄影配件', emoji: '👜', desc: '头层牛皮,舒适透气' },
{ id: 2, name: '相机防潮箱', series: '电子', price: 200, condition: '9成新', seller: '器材保养', emoji: '📦', desc: '防潮防霉,恒定湿度' },
{ id: 3, name: '胶卷收纳盒', series: '铝合金', price: 60, condition: '全新', seller: '摄影配件', emoji: '🧰', desc: '防压防潮,可放20卷' },
{ id: 4, name: '镜头清洁套装', series: '专业', price: 45, condition: '全新', seller: '摄影配件', emoji: '🧴', desc: '含气吹、镜头笔、擦镜纸' },
{ id: 5, name: '快门线', series: '机械', price: 30, condition: '全新', seller: '摄影配件', emoji: '🔗', desc: '传统快门线,适合慢门' },
{ id: 6, name: '相机皮套', series: '半套', price: 120, condition: '9成新', seller: '摄影配件', emoji: '👜', desc: '头层牛皮,贴合机身' },
{ id: 7, name: '复古相机包', series: '帆布', price: 150, condition: '全新', seller: '摄影包', emoji: '🎒', desc: '防撞内胆,复古设计' },
{ id: 8, name: '滤镜', series: 'ND', price: 80, condition: '全新', seller: '摄影配件', emoji: '🕶️', desc: '减光镜,适合长曝光' },
{ id: 9, name: '底片扫描器', series: '便携', price: 300, condition: '9成新', seller: '摄影配件', emoji: '📠', desc: '扫描底片,方便分享' }
];
// ---------------- 图鉴收藏数据(6条写死) ----------------
const COLLECTIONS: CollectionItem[] = [
{ id: 1, name: '徕卡', series: 'Leica', owned: 3, total: 12, rate: 25, emoji: '📷' },
{ id: 2, name: '中画幅', series: 'Medium Format', owned: 2, total: 8, rate: 25, emoji: '🎞️' },
{ id: 3, name: '尼康', series: 'Nikon', owned: 5, total: 15, rate: 33, emoji: '📸' },
{ id: 4, name: '镜头', series: 'Lenses', owned: 8, total: 20, rate: 40, emoji: '🔭' },
{ id: 5, name: '胶片', series: 'Film', owned: 10, total: 25, rate: 40, emoji: '🎞️' },
{ id: 6, name: '暗房', series: 'Darkroom', owned: 4, total: 10, rate: 40, emoji: '🌑' }
];
// ---------------- 点评数据(3条写死) ----------------
const GEAR_REVIEWS: GearReview[] = [
{ id: 1, user: '摄影爱好者', setName: '徕卡M3', starStr: '⭐⭐⭐⭐⭐', content: '经典中的经典,手感极佳,快门声清脆,收藏价值和拍摄体验都非常棒。' },
{ id: 2, user: '暗房玩家', setName: '暗房冲洗配方', starStr: '⭐⭐⭐⭐✨', content: '配方详尽,操作简单,按着做就能在家冲洗,太实用了。' },
{ id: 3, user: '人像摄影师', setName: '尼康85mm', starStr: '⭐⭐⭐⭐⭐', content: '背景虚化如奶油般化开,人像利器,色彩浓郁,非常值得。' }
];
// ---------------- 全城周交易量图表数据 ----------------
const TRADE_LABELS: string[] = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
const TRADE_BARS: number[] = [56, 64, 72, 58, 102, 146, 138];
// ---------------- 弹框选项 ----------------
const CONDITION_OPTIONS: string[] = ['全新未拆', '仅拆封', '9成新', '8成新', '有瑕疵'];
const PLACES: string[] = ['汉口江滩', '徐东古玩城', '洪山广场站', '楚河汉街站', '线上互换'];
// ---------------- 全局纯函数 ----------------
function catColor(cat: string): string {
if (cat === 'retired') return '#8B2E2E';
if (cat === 'moc') return '#7C4DFF';
if (cat === 'fig') return '#6B8E6B';
if (cat === 'tech') return '#C9A24B';
if (cat === 'street') return '#1E88E5';
return '#8B2E2E';
}
function catLabel(cat: string): string {
if (cat === 'retired') return '顶级收藏';
if (cat === 'moc') return '暗房教程';
if (cat === 'fig') return '镜头交易';
if (cat === 'tech') return '单反机械';
if (cat === 'street') return '街头旁轴';
return '经典老机';
}
function rarityLabel(r: number): string {
if (r >= 95) return '传世孤品';
if (r >= 80) return '稀有级';
if (r >= 60) return '紧俏级';
return '流通级';
}
function rarityColor(r: number): string {
if (r >= 95) return '#8B2E2E';
if (r >= 80) return '#FF8A00';
if (r >= 60) return '#1E88E5';
return '#6B8E6B';
}
function tradeBarHeight(v: number): string {
return Math.round(v / 146 * 96).toString() + 'vp';
}
function rateColor(r: number): string {
if (r >= 55) return '#6B8E6B';
if (r >= 40) return '#C9A24B';
return '#8B2E2E';
}
function retiredSets(): GearItem[] { return [GEARS[0], GEARS[1], GEARS[2]]; }
function mocSets(): GearItem[] { return [GEARS[3], GEARS[4], GEARS[5]]; }
function figSets(): GearItem[] { return [GEARS[6], GEARS[7], GEARS[8]]; }
function techSets(): GearItem[] { return [GEARS[9], GEARS[10], GEARS[11]]; }
function streetSets(): GearItem[] { return [GEARS[12], GEARS[13], GEARS[14]]; }
function classicSets(): GearItem[] { return [GEARS[15], GEARS[16], GEARS[17]]; }
function cityLeft(): GearItem[] { return [GEARS[16], GEARS[17]]; }
function cityRight(): GearItem[] { return [GEARS[15]]; }
function hotSets(): GearItem[] { return [GEARS[3], GEARS[5], GEARS[16], GEARS[17], GEARS[9]]; }
function swapBadge(likes: number): string {
if (likes >= 50) return '🔥热门';
if (likes >= 30) return '👍热度';
return '🌱新帖';
}
// ============================================================
// 主页面
// ============================================================
@Entry
@Component
struct Index {
@State currentBottomTab: number = 0;
@State currentTopTab: number = 0;
@State selectedGearId: number = 1;
@State showSellModal: boolean = false;
@State showSwapModal: boolean = false;
@State showDeleteModal: boolean = false;
@State showDetailModal: boolean = false;
@State sellGearIdx: number = 0;
@State sellCondIdx: number = 2;
@State sellPrice: number = 100;
@State sellWords: string = '';
@State swapOfferIdx: number = 0;
@State swapWantIdx: number = 1;
@State swapPlaceIdx: number = 0;
@State particles: ParticleItem[] = [];
private timerId: number = -1;
aboutToAppear(): void {
this.buildParticles();
this.timerId = setInterval(() => { this.driftParticles(); }, 80);
}
aboutToDisappear(): void {
if (this.timerId !== -1) { clearInterval(this.timerId); this.timerId = -1; }
}
buildParticles(): void {
const emojis: string[] = ['📷', '🎞️', '🔭', '🧪', '🎬'];
const list: ParticleItem[] = [];
for (let i = 0; i < 14; i++) {
list.push({ x: Math.random() * 340, emoji: emojis[i % emojis.length], size: 12 + Math.random() * 10, speed: 0.6 + Math.random() * 1.4, opacity: 0.2 + Math.random() * 0.4 });
}
this.particles = list;
}
driftParticles(): void {
for (let i = 0; i < this.particles.length; i++) {
this.particles[i].x += this.particles[i].speed;
if (this.particles[i].x > 360) { this.particles[i].x = -20; }
}
this.particles = this.particles.slice();
}
// 详情弹框数据取值
detailName(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].name; return ''; }
detailEng(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].eng; return ''; }
detailEmoji(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].emoji; return '📷'; }
detailPrice(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return '¥' + GEARS[i].price.toString(); return ''; }
detailSize(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].size; return ''; }
detailRarity(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].rarity.toString(); return ''; }
detailYear(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].year.toString(); return ''; }
detailSeller(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].seller; return ''; }
detailTag(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].tag; return ''; }
detailStar(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].starStr; return ''; }
detailRating(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].rating.toFixed(1) + '分'; return ''; }
detailDesc(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].desc; return ''; }
detailWant(): string { for (let i = 0; i < GEARS.length; i++) if (GEARS[i].id === this.selectedGearId) return GEARS[i].want; return ''; }
// ---------------- 头部 ----------------
@Builder
headerBuilder() {
Column() {
Row() {
Column() {
Text('📷 光影相机社').fontSize(22).fontWeight(FontWeight.Bold).fontColor('#FFFFFF')
Text('淘器材 · 换心头好 · 玩摄影').fontSize(11).fontColor('#E3C8C8').margin({ top: 3 })
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Row({ space: 14 }) {
Text('🔎').fontSize(20)
Text('📦').fontSize(20)
Column() {
Text('🎒').fontSize(20)
Text('3').fontSize(9).fontColor('#8B2E2E').backgroundColor('#FFFFFF').borderRadius(6).padding({ left: 4, right: 4 }).margin({ top: -6 })
}.alignItems(HorizontalAlign.End)
}
}.width('100%').padding({ left: 16, right: 16, top: 14, bottom: 10 })
Row({ space: 8 }) {
Text('🔍 搜索:徕卡 / 暗房 / 胶卷').fontSize(12).fontColor('#D9A5A5').layoutWeight(1)
Text('🧰 我的求购').fontSize(11).fontColor('#8B2E2E').backgroundColor('#FFFFFF').borderRadius(10).padding({ left: 10, right: 10, top: 4, bottom: 4 })
}.width('100%').padding({ left: 16, right: 16, bottom: 12 })
}
.linearGradient({ angle: 135, colors: [['#8B2E2E', 0], ['#3B2B2B', 1]] })
.borderRadius({ bottomLeft: 18, bottomRight: 18 })
}
// ---------------- 顶部Tab ----------------
@Builder
topTabsBuilder() {
Row() {
ForEach(TOP_TABS, (t: TabItem, idx: number) => {
Column() {
Text(t.icon).fontSize(17)
Text(t.label).fontSize(12).fontColor(this.currentTopTab === idx ? '#8B2E2E' : '#8A8577').fontWeight(this.currentTopTab === idx ? FontWeight.Bold : FontWeight.Normal).margin({ top: 2 })
if (this.currentTopTab === idx) {
Divider().width(16).strokeWidth(3).color('#C9A24B').borderRadius(2).margin({ top: 4 })
} else {
Divider().width(16).strokeWidth(3).color('#F5F1E8').borderRadius(2).margin({ top: 4 })
}
}.layoutWeight(1).alignItems(HorizontalAlign.Center).padding({ top: 10, bottom: 6 }).onClick(() => { this.currentTopTab = idx; })
}, (t: TabItem, idx: number) => 'top' + idx.toString() + t.label)
}.width('100%').backgroundColor('#FFFFFF').borderRadius(14).margin({ top: 10 })
}
// ---------------- 全部Tab:banner + 双列瀑布 ----------------
@Builder
cityContent() {
Column({ space: 12 }) {
Column() {
Text('📷 复古摄影节 · 春季专场').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#8B2E2E')
Text('经典器材 3天限时 · 卖家免服务费').fontSize(12).fontColor('#8A8577').margin({ top: 6 })
Row({ space: 10 }) {
Text('🏆 顶级收藏').fontSize(11).fontColor('#8B2E2E').backgroundColor('#FFFFFF').borderRadius(12).padding({ left: 10, right: 10, top: 4, bottom: 4 })
Text('🎞️ 胶卷专区').fontSize(11).fontColor('#8B2E2E').backgroundColor('#FFFFFF').borderRadius(12).padding({ left: 10, right: 10, top: 4, bottom: 4 })
}.margin({ top: 10 })
}.width('100%').padding(18).alignItems(HorizontalAlign.Start).linearGradient({ angle: 120, colors: [['#C9A24B', 0], ['#E2CE94', 1]] }).borderRadius(16)
Text('✨ 全城新上架').fontSize(15).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
Row({ space: 10 }) {
Column({ space: 10 }) {
ForEach(cityLeft(), (t: GearItem) => {
Column() {
Text(t.emoji).fontSize(34).margin({ top: 16 })
Text(t.name).fontSize(14).fontWeight(FontWeight.Bold).fontColor('#3B2B2B').margin({ top: 8 })
Text(t.eng).fontSize(9).fontColor('#8A8577').margin({ top: 2 })
Text(t.desc).fontSize(11).fontColor('#8A8577').margin({ top: 8 }).maxLines(3).textOverflow({ overflow: TextOverflow.Ellipsis })
Row({ space: 6 }) {
Text('¥' + t.price.toString()).fontSize(15).fontWeight(FontWeight.Bold).fontColor('#8B2E2E')
Text(t.tag).fontSize(9).fontColor('#8B2E2E').backgroundColor('#F0E5E5').borderRadius(8).padding({ left: 6, right: 6, top: 2, bottom: 2 })
}.margin({ top: 10, bottom: 14 })
}.width('100%').backgroundColor('#FFFFFF').borderRadius(14).alignItems(HorizontalAlign.Start).padding({ left: 14, right: 14 })
.onClick(() => { this.selectedGearId = t.id; this.showDetailModal = true; })
}, (t: GearItem) => 'cl' + t.id.toString())
}.layoutWeight(1)
Column({ space: 10 }) {
ForEach(cityRight(), (t: GearItem) => {
Column() {
Text(t.emoji).fontSize(34).margin({ top: 24 })
Text(t.name).fontSize(14).fontWeight(FontWeight.Bold).fontColor('#3B2B2B').margin({ top: 8 })
Text(t.eng).fontSize(9).fontColor('#8A8577').margin({ top: 2 })
Text(t.desc).fontSize(11).fontColor('#8A8577').margin({ top: 10 }).maxLines(4).textOverflow({ overflow: TextOverflow.Ellipsis })
Row({ space: 6 }) {
Text('¥' + t.price.toString()).fontSize(15).fontWeight(FontWeight.Bold).fontColor('#8B2E2E')
Text(t.starStr).fontSize(10)
}.margin({ top: 12, bottom: 20 })
}.width('100%').backgroundColor('#F0E5E5').borderRadius(14).alignItems(HorizontalAlign.Start).padding({ left: 14, right: 14 })
.onClick(() => { this.selectedGearId = t.id; this.showDetailModal = true; })
}, (t: GearItem) => 'cr' + t.id.toString())
}.layoutWeight(1)
}.width('100%').alignItems(VerticalAlign.Top)
}.width('100%').padding({ left: 14, right: 14, top: 10, bottom: 16 })
}
// ---------------- 胶片机Tab:横滑大卡 + 稀有度柱状图 + 捡漏榜 ----------------
@Builder
retiredContent() {
Column({ space: 14 }) {
Text('🏆 顶级收藏专区').fontSize(15).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
Scroll() {
Row({ space: 12 }) {
ForEach(retiredSets(), (t: GearItem) => {
Column() {
Text(t.emoji).fontSize(40).margin({ top: 18 })
Text(t.name).fontSize(15).fontWeight(FontWeight.Bold).fontColor('#FFFFFF').margin({ top: 8 })
Text(t.eng + ' · ' + t.year.toString() + '年').fontSize(9).fontColor('#E3C8C8').margin({ top: 4 })
Row({ space: 6 }) {
Text('¥' + t.price.toString()).fontSize(16).fontWeight(FontWeight.Bold).fontColor('#E2CE94')
Text(rarityLabel(t.rarity)).fontSize(10).fontColor('#8B2E2E').backgroundColor('#C9A24B').borderRadius(8).padding({ left: 6, right: 6, top: 2, bottom: 2 })
}.margin({ top: 10, bottom: 18 })
}.width(160).linearGradient({ angle: 160, colors: [['#8B2E2E', 0], ['#3B2B2B', 1]] }).borderRadius(16).alignItems(HorizontalAlign.Center)
.onClick(() => { this.selectedGearId = t.id; this.showDetailModal = true; })
}, (t: GearItem) => 'rt' + t.id.toString())
}.padding({ left: 14, right: 14 })
}.scrollable(ScrollDirection.Horizontal).scrollBar(BarState.Off).width('100%')
Column() {
Text('📈 稀有度排行').fontSize(13).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
Row({ space: 6 }) {
ForEach(retiredSets(), (t: GearItem, i: number) => {
Column({ space: 5 }) {
Text(t.rarity.toString()).fontSize(9).fontColor('#8B2E2E')
Column().width(34).height((t.rarity).toString() + 'vp').backgroundColor(i === 2 ? '#C9A24B' : '#8B2E2E').borderRadius({ topLeft: 5, topRight: 5 })
Text(t.year.toString() + '年').fontSize(9).fontColor('#8A8577')
}.alignItems(HorizontalAlign.Center).layoutWeight(1)
}, (t: GearItem, i: number) => 'rb' + i.toString() + t.id.toString())
}.width('100%').justifyContent(FlexAlign.Center).alignItems(VerticalAlign.Bottom).padding({ top: 12 })
Text('徕卡M3以90分稀有度登顶,市面流通极少').fontSize(10).fontColor('#8A8577').margin({ top: 8 })
}.width('100%').backgroundColor('#FFFFFF').borderRadius(14).padding(14).margin({ left: 14, right: 14 })
Column() {
Text('🕵️ 今日捡漏榜').fontSize(14).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%').margin({ bottom: 8 })
ForEach(retiredSets(), (t: GearItem, i: number) => {
Row({ space: 10 }) {
Text((i + 1).toString()).fontSize(14).fontWeight(FontWeight.Bold).fontColor(i === 0 ? '#8B2E2E' : '#8A8577').width(20)
Text(t.emoji).fontSize(18)
Column() {
Text(t.name).fontSize(13).fontWeight(FontWeight.Bold).fontColor('#3B2B2B')
Text(rarityLabel(t.rarity) + ' · ' + t.want).fontSize(10).fontColor('#8A8577').margin({ top: 2 })
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Text('¥' + t.price.toString()).fontSize(13).fontWeight(FontWeight.Bold).fontColor('#8B2E2E')
}.width('100%').padding({ top: 8, bottom: 8 }).onClick(() => { this.selectedGearId = t.id; this.showDetailModal = true; })
}, (t: GearItem, i: number) => 'pck' + i.toString() + t.id.toString())
}.width('100%').backgroundColor('#FFFFFF').borderRadius(14).padding(14).margin({ left: 14, right: 14, bottom: 16 })
}.width('100%').alignItems(HorizontalAlign.Start).padding({ top: 10 })
}
// ---------------- 单反Tab:教程时间轴 ----------------
@Builder
mocContent() {
Column({ space: 0 }) {
Text('📖 摄影教程 · 干货满满').fontSize(15).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%').margin({ top: 10, bottom: 12 })
ForEach(GUIDES, (m: GuideItem, i: number) => {
Row({ space: 12 }) {
Column({ space: 4 }) {
Text(m.emoji).fontSize(20)
if (i < GUIDES.length - 1) {
Column().width(2).layoutWeight(1).backgroundColor('#C9A24B').margin({ top: 4 })
}
}.width(40).alignItems(HorizontalAlign.Center)
Column({ space: 6 }) {
Row({ space: 8 }) {
Text(m.name).fontSize(14).fontWeight(FontWeight.Bold).fontColor('#3B2B2B').layoutWeight(1)
Text('⬇ ' + m.downloads.toString()).fontSize(10).fontColor('#8B2E2E')
}.width('100%')
Text('by ' + m.author + ' · ' + m.type + ' · ' + m.pages.toString() + '页').fontSize(10).fontColor('#8A8577')
Column({ space: 5 }) {
ForEach(m.steps, (s: string, si: number) => {
Row({ space: 8 }) {
Text((si + 1).toString()).fontSize(9).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').backgroundColor('#F5F1E8').borderRadius(9).width(18).height(18).textAlign(TextAlign.Center)
Text(s).fontSize(10).fontColor('#4A5A6E').layoutWeight(1)
}.width('100%')
}, (s: string, si: number) => 'ms' + si.toString() + m.id.toString())
}.width('100%').backgroundColor('#F5F1E8').borderRadius(10).padding(10)
Row({ space: 8 }) {
Text('❤️ ' + m.likes.toString()).fontSize(10).fontColor('#8B2E2E')
Text(m.emoji + ' 教程可下载').fontSize(10).fontColor('#8B2E2E').layoutWeight(1).textAlign(TextAlign.End)
}.width('100%')
}.layoutWeight(1).backgroundColor(i === 1 ? '#F0E5E5' : '#FFFFFF').borderRadius(14).padding(12).margin({ bottom: 14 })
}.width('100%').alignItems(VerticalAlign.Top)
}, (m: GuideItem, i: number) => 'moc' + i.toString() + m.id.toString())
}.width('100%').padding({ left: 14, right: 14, bottom: 16 })
}
// ---------------- 镜头Tab:三列格子 + 交换建议 ----------------
@Builder
figContent() {
Column({ space: 14 }) {
Text('🔭 镜头交易 · 德味大赏').fontSize(15).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) {
ForEach(ACCESSORIES, (f: AccessoryItem) => {
Column() {
Text(f.emoji).fontSize(26).margin({ top: 12 })
Text(f.name).fontSize(11).fontWeight(FontWeight.Bold).fontColor('#3B2B2B').margin({ top: 6 }).maxLines(1)
Text(f.series).fontSize(8).fontColor('#8A8577').margin({ top: 2 })
Text('¥' + f.price.toString()).fontSize(13).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').margin({ top: 4, bottom: 12 })
}.width('31%').backgroundColor('#FFFFFF').borderRadius(12).alignItems(HorizontalAlign.Center).margin({ bottom: 8 })
.onClick(() => { this.selectedGearId = 7 + f.id % 3; this.showDetailModal = true; })
}, (f: AccessoryItem) => 'fg' + f.id.toString())
}.width('100%')
Column() {
Text('🤝 配件交换行情').fontSize(14).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%').margin({ bottom: 6 })
ForEach(ACCESSORIES, (f: AccessoryItem) => {
if (f.id % 2 === 0) {
Row({ space: 10 }) {
Text(f.emoji).fontSize(20)
Column({ space: 2 }) {
Text(f.name + ' · ' + f.condition).fontSize(12).fontWeight(FontWeight.Bold).fontColor('#3B2B2B')
Text(f.desc).fontSize(10).fontColor('#8A8577')
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Text('¥' + f.price.toString()).fontSize(12).fontWeight(FontWeight.Bold).fontColor('#6B8E6B')
}.width('100%').padding({ top: 8, bottom: 8 })
}
}, (f: AccessoryItem) => 'fgx' + f.id.toString())
}.width('100%').backgroundColor('#FFFFFF').borderRadius(14).padding(14)
}.width('100%').padding({ left: 14, right: 14, top: 10, bottom: 16 })
}
// ---------------- 胶片Tab:对决卡 + 侧栏统计 ----------------
@Builder
techContent() {
Column({ space: 14 }) {
Text('🎞️ 器材对决 · 摄影必备').fontSize(15).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
Row({ space: 10 }) {
Column() {
Text('📷').fontSize(34).margin({ top: 14 })
Text('徕卡M3').fontSize(13).fontWeight(FontWeight.Bold).fontColor('#FFFFFF').margin({ top: 6 })
Text('1954年 · 现价¥32000').fontSize(10).fontColor('#E3C8C8').margin({ top: 4, bottom: 14 })
}.layoutWeight(1).linearGradient({ angle: 150, colors: [['#8B2E2E', 0], ['#3B2B2B', 1]] }).borderRadius(14).alignItems(HorizontalAlign.Center)
Column() {
Text('VS').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#8B2E2E')
Text('本周').fontSize(9).fontColor('#8A8577')
}.alignItems(HorizontalAlign.Center)
Column() {
Text('🔭').fontSize(34).margin({ top: 14 })
Text('徕卡50mm').fontSize(13).fontWeight(FontWeight.Bold).fontColor('#FFFFFF').margin({ top: 6 })
Text('1961年 · 现价¥18000').fontSize(10).fontColor('#E3C8C8').margin({ top: 4, bottom: 14 })
}.layoutWeight(1).linearGradient({ angle: 150, colors: [['#8A8577', 0], ['#3B2B2B', 1]] }).borderRadius(14).alignItems(HorizontalAlign.Center)
}.width('100%')
Row({ space: 10 }) {
Column({ space: 10 }) {
ForEach(techSets(), (t: GearItem) => {
Row({ space: 10 }) {
Text(t.emoji).fontSize(22)
Column({ space: 2 }) {
Text(t.name).fontSize(12).fontWeight(FontWeight.Bold).fontColor('#3B2B2B')
Text(t.tag + ' · ' + t.size).fontSize(10).fontColor('#8A8577')
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Text('¥' + t.price.toString()).fontSize(12).fontWeight(FontWeight.Bold).fontColor('#8B2E2E')
}.width('100%').backgroundColor('#FFFFFF').borderRadius(12).padding(12).onClick(() => { this.selectedGearId = t.id; this.showDetailModal = true; })
}, (t: GearItem) => 'tc' + t.id.toString())
}.layoutWeight(1)
Column({ space: 10 }) {
Column({ space: 4 }) {
Text('12').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#8B2E2E')
Text('本周器材成交').fontSize(9).fontColor('#8A8577')
}.width('100%').backgroundColor('#F0E5E5').borderRadius(12).padding({ top: 10, bottom: 10 }).alignItems(HorizontalAlign.Center)
Column({ space: 4 }) {
Text('2.2万').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#C9A24B')
Text('器材总交易额').fontSize(9).fontColor('#8A8577')
}.width('100%').backgroundColor('#F0EAD8').borderRadius(12).padding({ top: 10, bottom: 10 }).alignItems(HorizontalAlign.Center)
Column({ space: 4 }) {
Text('96%').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#6B8E6B')
Text('好评率').fontSize(9).fontColor('#8A8577')
}.width('100%').backgroundColor('#FFFFFF').borderRadius(12).padding({ top: 10, bottom: 10 }).alignItems(HorizontalAlign.Center)
}.width(86)
}.width('100%').alignItems(VerticalAlign.Top)
}.width('100%').padding({ left: 14, right: 14, top: 10, bottom: 16 })
}
// ---------------- 暗房Tab:标签云 + 紧凑列表 ----------------
@Builder
streetContent() {
Column({ space: 14 }) {
Text('🌑 暗房收藏 · 影像艺术').fontSize(15).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start }) {
ForEach(COLLECTIONS, (c: CollectionItem) => {
Text(c.emoji + ' ' + c.name + ' ' + c.owned.toString() + '/' + c.total.toString()).fontSize(11).fontColor('#8B2E2E').backgroundColor('#F0E5E5').borderRadius(12).padding({ left: 10, right: 10, top: 6, bottom: 6 }).margin(4)
}, (c: CollectionItem) => 'ccoll' + c.id.toString())
}.width('100%')
ForEach(streetSets(), (t: GearItem) => {
Row({ space: 12 }) {
Text(t.emoji).fontSize(24)
Column({ space: 2 }) {
Row({ space: 6 }) {
Text(t.name).fontSize(13).fontWeight(FontWeight.Bold).fontColor('#3B2B2B')
Text(rarityLabel(t.rarity)).fontSize(8).fontColor('#FFFFFF').backgroundColor(rarityColor(t.rarity)).borderRadius(6).padding({ left: 5, right: 5, top: 1, bottom: 1 })
}
Text(t.desc).fontSize(10).fontColor('#8A8577').maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis })
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Text('¥' + t.price.toString()).fontSize(13).fontWeight(FontWeight.Bold).fontColor('#8B2E2E')
}.width('100%').backgroundColor(t.id === 15 ? '#F0E5E5' : '#FFFFFF').borderRadius(12).padding(12).onClick(() => { this.selectedGearId = t.id; this.showDetailModal = true; })
}, (t: GearItem) => 'st' + t.id.toString())
Text('💬 集齐三大相机可召唤隐藏福利:徕卡+哈苏+XPAN').fontSize(10).fontColor('#8A8577').width('100%')
}.width('100%').padding({ left: 14, right: 14, top: 10, bottom: 16 })
}
// ---------------- 器材首页 ----------------
@Builder
bazaarContent() {
Column() {
this.topTabsBuilder()
if (this.currentTopTab === 0) { this.cityContent() }
else if (this.currentTopTab === 1) { this.retiredContent() }
else if (this.currentTopTab === 2) { this.mocContent() }
else if (this.currentTopTab === 3) { this.figContent() }
else if (this.currentTopTab === 4) { this.techContent() }
else { this.streetContent() }
}.width('100%')
}
// ---------------- 换件页 ----------------
@Builder
swapContent() {
Column({ space: 12 }) {
Row({ space: 0 }) {
Column({ space: 4 }) { Text('156').fontSize(20).fontWeight(FontWeight.Bold).fontColor('#8B2E2E'); Text('在交换中').fontSize(10).fontColor('#8A8577') }.layoutWeight(1).alignItems(HorizontalAlign.Center)
Column({ space: 4 }) { Text('42').fontSize(20).fontWeight(FontWeight.Bold).fontColor('#C9A24B'); Text('今日成交').fontSize(10).fontColor('#8A8577') }.layoutWeight(1).alignItems(HorizontalAlign.Center)
Column({ space: 4 }) { Text('98%').fontSize(20).fontWeight(FontWeight.Bold).fontColor('#6B8E6B'); Text('面交好评').fontSize(10).fontColor('#8A8577') }.layoutWeight(1).alignItems(HorizontalAlign.Center)
Column({ space: 6 }) { Text('🤝 发交换').fontSize(12).fontColor('#FFFFFF').backgroundColor('#8B2E2E').borderRadius(14).padding({ left: 12, right: 12, top: 6, bottom: 6 }).onClick(() => { this.showSwapModal = true; }) }.alignItems(HorizontalAlign.Center)
}.width('100%').backgroundColor('#FFFFFF').borderRadius(14).padding({ top: 14, bottom: 14 })
ForEach(SWAPS, (s: SwapItem) => {
Column({ space: 8 }) {
Row({ space: 10 }) {
Text(s.avatar).fontSize(26)
Column({ space: 2 }) {
Row({ space: 6 }) {
Text(s.user).fontSize(13).fontWeight(FontWeight.Bold).fontColor('#3B2B2B')
Text(swapBadge(s.likes)).fontSize(8).fontColor('#C9A24B').backgroundColor('#F0EAD8').borderRadius(6).padding({ left: 5, right: 5, top: 1, bottom: 1 })
}
Text(s.time + ' · ' + s.place).fontSize(9).fontColor('#8A8577')
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Text('⋯').fontSize(16).fontColor('#8A8577').onClick(() => { this.showDeleteModal = true; })
}.width('100%')
Row({ space: 10 }) {
Column({ space: 4 }) { Text('我提供').fontSize(9).fontColor('#8B2E2E'); Text(s.offer).fontSize(11).fontWeight(FontWeight.Bold).fontColor('#3B2B2B') }.layoutWeight(1).backgroundColor('#F0E5E5').borderRadius(10).padding(8).alignItems(HorizontalAlign.Center)
Text('⇄').fontSize(14).fontColor('#C9A24B')
Column({ space: 4 }) { Text('我想换').fontSize(9).fontColor('#8B2E2E'); Text(s.want).fontSize(11).fontWeight(FontWeight.Bold).fontColor('#3B2B2B') }.layoutWeight(1).backgroundColor('#F0EAD8').borderRadius(10).padding(8).alignItems(HorizontalAlign.Center)
}.width('100%')
Text(s.content).fontSize(11).fontColor('#4A5A6E').lineHeight(16).width('100%')
Row({ space: 8 }) {
Text('📍 ' + s.place).fontSize(10).fontColor('#8B2E2E').backgroundColor('#F5F1E8').borderRadius(10).padding({ left: 8, right: 8, top: 4, bottom: 4 })
Text('❤️ ' + s.likes.toString()).fontSize(10).fontColor('#8B2E2E').layoutWeight(1).textAlign(TextAlign.End)
}.width('100%')
}.width('100%').backgroundColor('#FFFFFF').borderRadius(14).padding(14)
}, (s: SwapItem) => 'sw' + s.id.toString())
}.width('100%').padding({ left: 14, right: 14, top: 10, bottom: 16 })
}
// ---------------- 图鉴页 ----------------
@Builder
collectionContent() {
Column({ space: 12 }) {
Row({ space: 10 }) {
Column({ space: 4 }) {
Text('📖 我的摄影图鉴').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#8B2E2E')
Text('记录每一件器材的收藏进度').fontSize(10).fontColor('#8A8577')
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Text('✚ 登记').fontSize(12).fontColor('#FFFFFF').backgroundColor('#8B2E2E').borderRadius(14).padding({ left: 14, right: 14, top: 7, bottom: 7 }).onClick(() => { this.showSellModal = true; })
}.width('100%').margin({ top: 10 })
ForEach(COLLECTIONS, (c: CollectionItem) => {
Column({ space: 8 }) {
Row({ space: 10 }) {
Text(c.emoji).fontSize(28)
Column({ space: 3 }) {
Text(c.name).fontSize(14).fontWeight(FontWeight.Bold).fontColor('#3B2B2B')
Text(c.series + ' · 已收 ' + c.owned.toString() + '/' + c.total.toString()).fontSize(10).fontColor('#8A8577')
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Text(c.rate.toString() + '%').fontSize(15).fontWeight(FontWeight.Bold).fontColor(rateColor(c.rate))
}.width('100%')
Row({ space: 0 }) {
Column().width(c.rate.toString() + '%').height(6).backgroundColor(rateColor(c.rate)).borderRadius(3)
Column().width((100 - c.rate).toString() + '%').height(6).backgroundColor('#E5E1D5').borderRadius(3)
}.width('100%')
}.width('100%').backgroundColor(c.id === 5 ? '#F0EAD8' : '#FFFFFF').borderRadius(14).padding(14)
}, (c: CollectionItem) => 'coll' + c.id.toString())
Column() {
Text('🏅 图鉴成就墙').fontSize(14).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%').margin({ bottom: 8 })
Flex({ wrap: FlexWrap.Wrap }) {
Text('🎖️ 徕卡收藏家').fontSize(10).fontColor('#8B2E2E').backgroundColor('#F0E5E5').borderRadius(10).padding({ left: 8, right: 8, top: 5, bottom: 5 }).margin(4)
Text('🏆 暗房大师').fontSize(10).fontColor('#C9A24B').backgroundColor('#F0EAD8').borderRadius(10).padding({ left: 8, right: 8, top: 5, bottom: 5 }).margin(4)
Text('📷 胶卷摄影家').fontSize(10).fontColor('#6B8E6B').backgroundColor('#E8F7EF').borderRadius(10).padding({ left: 8, right: 8, top: 5, bottom: 5 }).margin(4)
Text('🔭 镜头专家').fontSize(10).fontColor('#1E88E5').backgroundColor('#E8F0FE').borderRadius(10).padding({ left: 8, right: 8, top: 5, bottom: 5 }).margin(4)
}.width('100%')
}.width('100%').backgroundColor('#FFFFFF').borderRadius(14).padding(14)
}.width('100%').padding({ left: 14, right: 14, bottom: 16 })
}
// ---------------- 我的页 ----------------
@Builder
mineContent() {
Column({ space: 14 }) {
Column() {
Row({ space: 12 }) {
Text('🎞️').fontSize(40)
Column({ space: 4 }) {
Text('摄影收藏家老影').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#FFFFFF')
Text('LV.10 资深摄影人 · 信用分 990').fontSize(10).fontColor('#E3C8C8')
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Text('>').fontSize(18).fontColor('#E3C8C8')
}.width('100%')
Row({ space: 0 }) {
Column({ space: 3 }) { Text('38').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#E2CE94'); Text('在售器材').fontSize(9).fontColor('#E3C8C8') }.layoutWeight(1).alignItems(HorizontalAlign.Center)
Column({ space: 3 }) { Text('12').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#E2CE94'); Text('求购中').fontSize(9).fontColor('#E3C8C8') }.layoutWeight(1).alignItems(HorizontalAlign.Center)
Column({ space: 3 }) { Text('¥6.8万').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#E2CE94'); Text('累计成交额').fontSize(9).fontColor('#E3C8C8') }.layoutWeight(1).alignItems(HorizontalAlign.Center)
}.width('100%').margin({ top: 16 })
}.width('100%').padding(18).linearGradient({ angle: 120, colors: [['#8B2E2E', 0], ['#3B2B2B', 1]] }).borderRadius(16).margin({ top: 10 })
Column() {
Text('🔨 我的求购清单').fontSize(14).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%').margin({ bottom: 6 })
ForEach(GEARS, (t: GearItem) => {
if (t.id === 13 || t.id === 16 || t.id === 18) {
Row({ space: 10 }) {
Text(t.emoji).fontSize(20)
Column({ space: 2 }) {
Text(t.name).fontSize(12).fontWeight(FontWeight.Bold).fontColor('#3B2B2B')
Text('预算 ¥' + t.price.toString() + ' 内 · ' + t.want).fontSize(9).fontColor('#8A8577')
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Text('出价中').fontSize(10).fontColor('#C9A24B').backgroundColor('#F0EAD8').borderRadius(10).padding({ left: 8, right: 8, top: 3, bottom: 3 })
}.width('100%').padding({ top: 9, bottom: 9 })
}
}, (t: GearItem) => 'wish' + t.id.toString())
}.width('100%').backgroundColor('#FFFFFF').borderRadius(14).padding(14)
Column() {
Text('📍 常去面交点').fontSize(14).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%').margin({ bottom: 6 })
ForEach(PLACES, (p: string, i: number) => {
Row({ space: 10 }) {
Text(['🚇', '🏬', '🚌', '🏪', '📦'][i]).fontSize(16)
Text(p).fontSize(12).fontWeight(FontWeight.Bold).fontColor('#3B2B2B').layoutWeight(1)
Text(['汉口站台', '徐东入口', '洪山转盘', '楚河入口', '顺丰网点'][i]).fontSize(9).fontColor('#8A8577')
}.width('100%').padding({ top: 9, bottom: 9 })
}, (p: string, i: number) => 'pl' + i.toString() + p)
}.width('100%').backgroundColor('#FFFFFF').borderRadius(14).padding(14)
}.width('100%').padding({ left: 14, right: 14, bottom: 16 })
}
// ---------------- 底部Tab ----------------
@Builder
bottomTabsBuilder() {
Row() {
ForEach(BOTTOM_TABS, (t: TabItem, idx: number) => {
Column({ space: 3 }) {
Text(t.icon).fontSize(20)
Text(t.label).fontSize(10).fontColor(this.currentBottomTab === idx ? '#8B2E2E' : '#8A8577').fontWeight(this.currentBottomTab === idx ? FontWeight.Bold : FontWeight.Normal)
}.layoutWeight(1).alignItems(HorizontalAlign.Center).padding({ top: 8, bottom: 8 }).onClick(() => { this.currentBottomTab = idx; })
}, (t: TabItem, idx: number) => 'bt' + idx.toString() + t.label)
}.width('100%').backgroundColor('#FFFFFF').borderRadius({ topLeft: 18, topRight: 18 })
}
// ---------------- 弹框1:发布出售(新增·红渐变头) ----------------
@Builder
sellModalBuilder() {
Column() {
Column() {
Text('📷 发布出售').fontSize(17).fontWeight(FontWeight.Bold).fontColor('#FFFFFF').margin({ top: 16 })
Text('闲置回血,神机不愁卖').fontSize(11).fontColor('#E3C8C8').margin({ top: 4, bottom: 16 })
}.width('100%').linearGradient({ angle: 120, colors: [['#8B2E2E', 0], ['#3B2B2B', 1]] }).borderRadius({ topLeft: 18, topRight: 18 })
Scroll() {
Column({ space: 14 }) {
Column({ space: 8 }) {
Text('要出售的器材').fontSize(12).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(GEARS, (t: GearItem, i: number) => {
if (i < 8) {
Text(t.emoji + ' ' + t.name).fontSize(10).fontColor(this.sellGearIdx === i ? '#FFFFFF' : '#8B2E2E').backgroundColor(this.sellGearIdx === i ? '#8B2E2E' : '#F0E5E5').borderRadius(12).padding({ left: 9, right: 9, top: 5, bottom: 5 }).margin(4).onClick(() => { this.sellGearIdx = i; })
}
}, (t: GearItem, i: number) => 'st' + i.toString() + t.id.toString())
}.width('100%')
}.width('100%').alignItems(HorizontalAlign.Start)
Column({ space: 8 }) {
Text('成色说明').fontSize(12).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(CONDITION_OPTIONS, (c: string, i: number) => {
Text(c).fontSize(10).fontColor(this.sellCondIdx === i ? '#FFFFFF' : '#C9A24B').backgroundColor(this.sellCondIdx === i ? '#C9A24B' : '#F0EAD8').borderRadius(12).padding({ left: 10, right: 10, top: 5, bottom: 5 }).margin(4).onClick(() => { this.sellCondIdx = i; })
}, (c: string, i: number) => 'sd' + i.toString() + c)
}.width('100%')
}.width('100%').alignItems(HorizontalAlign.Start)
Row({ space: 12 }) {
Text('出售价格').fontSize(12).fontWeight(FontWeight.Bold).fontColor('#8B2E2E')
Row({ space: 0 }) {
Text('−').fontSize(16).fontColor('#8B2E2E').backgroundColor('#F0E5E5').borderRadius({ topLeft: 10, bottomLeft: 10 }).width(34).height(30).textAlign(TextAlign.Center).onClick(() => { if (this.sellPrice > 10) { this.sellPrice -= 10; } })
Text('¥' + this.sellPrice.toString()).fontSize(13).fontWeight(FontWeight.Bold).fontColor('#3B2B2B').backgroundColor('#FFFFFF').height(30).textAlign(TextAlign.Center).padding({ left: 14, right: 14 })
Text('+').fontSize(16).fontColor('#FFFFFF').backgroundColor('#8B2E2E').borderRadius({ topRight: 10, bottomRight: 10 }).width(34).height(30).textAlign(TextAlign.Center).onClick(() => { if (this.sellPrice < 99999) { this.sellPrice += 10; } })
}.borderRadius(10)
Text(this.sellPrice > 20000 ? '💰 高价好物建议包邮' : '实惠价更容易出手').fontSize(9).fontColor(this.sellPrice > 20000 ? '#8B2E2E' : '#8A8577').layoutWeight(1).textAlign(TextAlign.End)
}.width('100%')
Column({ space: 8 }) {
Text('宝贝描述').fontSize(12).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
TextInput({ placeholder: '成色、瑕疵、配件情况如实描述…', text: this.sellWords }).fontSize(12).fontColor('#3B2B2B').backgroundColor('#F5F1E8').borderRadius(10).height(40).padding({ left: 12, right: 12 }).onChange((v: string) => { this.sellWords = v; })
}.width('100%').alignItems(HorizontalAlign.Start)
Row({ space: 12 }) {
Text('取消').fontSize(13).fontColor('#8A8577').backgroundColor('#F5F1E8').borderRadius(20).layoutWeight(1).height(42).textAlign(TextAlign.Center).onClick(() => { this.showSellModal = false; })
Text('上架出售').fontSize(13).fontWeight(FontWeight.Bold).fontColor('#FFFFFF').backgroundColor('#8B2E2E').borderRadius(20).layoutWeight(1).height(42).textAlign(TextAlign.Center).onClick(() => { this.showSellModal = false; })
}.width('100%').margin({ top: 4, bottom: 18 })
}.width('100%').padding({ left: 16, right: 16, top: 16 })
}.scrollBar(BarState.Off).layoutWeight(1).align(Alignment.Top)
}.width('88%').height('76%').backgroundColor('#FFFFFF').borderRadius(18).clip(true)
}
// ---------------- 弹框2:发起交换(新增·金头) ----------------
@Builder
swapModalBuilder() {
Column() {
Column() {
Row({ space: 8 }) { Text('🤝').fontSize(22); Text('发起交换').fontSize(17).fontWeight(FontWeight.Bold).fontColor('#3B2B2B') }.margin({ top: 16 })
Text('用闲置换心头好,摄友互助').fontSize(11).fontColor('#5B6B7F').margin({ top: 4, bottom: 14 })
}.width('100%').backgroundColor('#C9A24B').borderRadius({ topLeft: 18, topRight: 18 })
Scroll() {
Column({ space: 14 }) {
Column({ space: 8 }) {
Text('我提供').fontSize(12).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(GEARS, (t: GearItem, i: number) => {
if (i % 3 === 0 && i < 15) {
Text(t.emoji + ' ' + t.name).fontSize(10).fontColor(this.swapOfferIdx === i ? '#FFFFFF' : '#8B2E2E').backgroundColor(this.swapOfferIdx === i ? '#3B2B2B' : '#F5F1E8').borderRadius(12).padding({ left: 9, right: 9, top: 5, bottom: 5 }).margin(4).onClick(() => { this.swapOfferIdx = i; })
}
}, (t: GearItem, i: number) => 'wo' + i.toString() + t.id.toString())
}.width('100%')
}.width('100%').alignItems(HorizontalAlign.Start)
Column({ space: 8 }) {
Text('我想换(可多选)').fontSize(12).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(GEARS, (t: GearItem, i: number) => {
if (i % 3 === 2 && i < 15) {
Text((this.pickedWant(i) ? '✓ ' : '') + t.emoji + ' ' + t.name).fontSize(10).fontColor(this.pickedWant(i) ? '#FFFFFF' : '#8B2E2E').backgroundColor(this.pickedWant(i) ? '#8B2E2E' : '#F0EAD8').borderRadius(12).padding({ left: 9, right: 9, top: 5, bottom: 5 }).margin(4).onClick(() => { this.toggleWant(i); })
}
}, (t: GearItem, i: number) => 'ww' + i.toString() + t.id.toString())
}.width('100%')
}.width('100%').alignItems(HorizontalAlign.Start)
Column({ space: 8 }) {
Text('面交地点').fontSize(12).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(PLACES, (p: string, i: number) => {
Text(p).fontSize(10).fontColor(this.swapPlaceIdx === i ? '#FFFFFF' : '#8B2E2E').backgroundColor(this.swapPlaceIdx === i ? '#8B2E2E' : '#F0E5E5').borderRadius(12).padding({ left: 10, right: 10, top: 5, bottom: 5 }).margin(4).onClick(() => { this.swapPlaceIdx = i; })
}, (p: string, i: number) => 'wp' + i.toString() + p)
}.width('100%')
}.width('100%').alignItems(HorizontalAlign.Start)
Row({ space: 8 }) {
Text('💡').fontSize(14)
Text('交换双方可自行协商补差价,面交请选择人流密集的公共场所,注意安全。').fontSize(10).fontColor('#8A8577').lineHeight(15).layoutWeight(1)
}.width('100%').backgroundColor('#F0EAD8').borderRadius(10).padding(10)
Row({ space: 12 }) {
Text('再想想').fontSize(13).fontColor('#8A8577').backgroundColor('#F5F1E8').borderRadius(20).layoutWeight(1).height(42).textAlign(TextAlign.Center).onClick(() => { this.showSwapModal = false; })
Text('发布交换帖').fontSize(13).fontWeight(FontWeight.Bold).fontColor('#FFFFFF').backgroundColor('#8B2E2E').borderRadius(20).layoutWeight(1).height(42).textAlign(TextAlign.Center).onClick(() => { this.showSwapModal = false; })
}.width('100%').margin({ top: 4, bottom: 18 })
}.width('100%').padding({ left: 16, right: 16, top: 16 })
}.scrollBar(BarState.Off).layoutWeight(1).align(Alignment.Top)
}.width('88%').height('72%').backgroundColor('#FFFFFF').borderRadius(18).clip(true)
}
// ---------------- 弹框3:下架/删除 ----------------
@Builder
deleteModalBuilder() {
Column({ space: 14 }) {
Text('🗑️').fontSize(36)
Text('下架这件器材?').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#8B2E2E')
Text('下架后买家将无法搜索到这条信息,\n收藏和留言会一并清空,可重新上架。').fontSize(11).fontColor('#8A8577').textAlign(TextAlign.Center).lineHeight(17)
Row({ space: 12 }) {
Text('留着').fontSize(13).fontColor('#8B2E2E').backgroundColor('#F0E5E5').borderRadius(20).layoutWeight(1).height(40).textAlign(TextAlign.Center).onClick(() => { this.showDeleteModal = false; })
Text('确认下架').fontSize(13).fontWeight(FontWeight.Bold).fontColor('#FFFFFF').backgroundColor('#8B2E2E').borderRadius(20).layoutWeight(1).height(40).textAlign(TextAlign.Center).onClick(() => { this.showDeleteModal = false; })
}.width('100%').margin({ top: 6 })
}.width('72%').backgroundColor('#FFFFFF').borderRadius(18).padding({ left: 20, right: 20, top: 24, bottom: 22 }).alignItems(HorizontalAlign.Center)
}
// ---------------- 弹框4:器材详情(红金渐变头) ----------------
@Builder
detailModalBuilder() {
Column() {
Column() {
Text(this.detailEmoji()).fontSize(40).margin({ top: 18 })
Text(this.detailName()).fontSize(18).fontWeight(FontWeight.Bold).fontColor('#3B2B2B').margin({ top: 8 })
Text(this.detailEng()).fontSize(10).fontColor('#8A8577').margin({ top: 2 })
Row({ space: 8 }) {
Text(this.detailTag()).fontSize(9).fontColor('#FFFFFF').backgroundColor('#8B2E2E').borderRadius(8).padding({ left: 7, right: 7, top: 2, bottom: 2 })
Text(rarityLabel(Number(this.detailRarity()))).fontSize(9).fontColor('#3B2B2B').backgroundColor('#C9A24B').borderRadius(8).padding({ left: 7, right: 7, top: 2, bottom: 2 })
}.margin({ top: 10, bottom: 18 })
}.width('100%').linearGradient({ angle: 135, colors: [['#C9A24B', 0], ['#F0E5E5', 1]] }).borderRadius({ topLeft: 18, topRight: 18 }).alignItems(HorizontalAlign.Center)
Scroll() {
Column({ space: 14 }) {
Row({ space: 0 }) {
Column({ space: 4 }) { Text(this.detailPrice()).fontSize(17).fontWeight(FontWeight.Bold).fontColor('#8B2E2E'); Text('售价').fontSize(9).fontColor('#8A8577') }.layoutWeight(1).alignItems(HorizontalAlign.Center)
Column({ space: 4 }) { Text(this.detailSize()).fontSize(17).fontWeight(FontWeight.Bold).fontColor('#8B2E2E'); Text('规格').fontSize(9).fontColor('#8A8577') }.layoutWeight(1).alignItems(HorizontalAlign.Center)
Column({ space: 4 }) { Text(this.detailRarity()).fontSize(17).fontWeight(FontWeight.Bold).fontColor(rarityColor(Number(this.detailRarity()))); Text('稀有度').fontSize(9).fontColor('#8A8577') }.layoutWeight(1).alignItems(HorizontalAlign.Center)
Column({ space: 4 }) { Text(this.detailYear()).fontSize(17).fontWeight(FontWeight.Bold).fontColor('#C9A24B'); Text('年份').fontSize(9).fontColor('#8A8577') }.layoutWeight(1).alignItems(HorizontalAlign.Center)
}.width('100%').backgroundColor('#F5F1E8').borderRadius(12).padding({ top: 12, bottom: 12 })
Column({ space: 8 }) {
Text('🧾 宝贝描述').fontSize(12).fontWeight(FontWeight.Bold).fontColor('#3B2B2B').width('100%')
Text(this.detailDesc()).fontSize(11).fontColor('#4A5A6E').lineHeight(18)
Row({ space: 8 }) {
Text('👤 ' + this.detailSeller()).fontSize(10).fontColor('#8B2E2E')
Text(this.detailStar() + ' ' + this.detailRating()).fontSize(10).fontColor('#C9A24B').layoutWeight(1).textAlign(TextAlign.End)
}.width('100%')
}.width('100%').alignItems(HorizontalAlign.Start)
Row({ space: 8 }) {
Text('🤝').fontSize(14)
Text('卖家想换:' + this.detailWant()).fontSize(11).fontColor('#8B2E2E').layoutWeight(1)
}.width('100%').backgroundColor('#F0EAD8').borderRadius(10).padding(10)
Column({ space: 10 }) {
Text('💬 圈友点评').fontSize(12).fontWeight(FontWeight.Bold).fontColor('#8B2E2E').width('100%')
ForEach(GEAR_REVIEWS, (r: GearReview) => {
Column({ space: 5 }) {
Row({ space: 8 }) { Text('👤').fontSize(14); Text(r.user).fontSize(11).fontWeight(FontWeight.Bold).fontColor('#3B2B2B'); Text(r.starStr).fontSize(9).layoutWeight(1).textAlign(TextAlign.End) }.width('100%')
Text(r.content).fontSize(10).fontColor('#8A8577').lineHeight(15)
}.width('100%').backgroundColor('#F5F1E8').borderRadius(10).padding(10)
}, (r: GearReview) => 'rv' + r.id.toString())
}.width('100%').alignItems(HorizontalAlign.Start)
Row({ space: 12 }) {
Text('💬 留言问问').fontSize(13).fontColor('#8B2E2E').backgroundColor('#F0E5E5').borderRadius(20).layoutWeight(1).height(42).textAlign(TextAlign.Center).onClick(() => { this.showDetailModal = false; })
Text('🛒 立即购买').fontSize(13).fontWeight(FontWeight.Bold).fontColor('#FFFFFF').backgroundColor('#8B2E2E').borderRadius(20).layoutWeight(1).height(42).textAlign(TextAlign.Center).onClick(() => { this.showDetailModal = false; })
}.width('100%').margin({ top: 2, bottom: 18 })
}.width('100%').padding({ left: 16, right: 16, top: 14 })
}.scrollBar(BarState.Off).layoutWeight(1).align(Alignment.Top)
}.width('88%').height('78%').backgroundColor('#FFFFFF').borderRadius(18).clip(true)
}
// 交换多选辅助
pickedWant(i: number): boolean { return (i % 2) === 0; }
toggleWant(i: number): void { this.swapWantIdx = i; }
// ---------------- 主布局 ----------------
build() {
Stack() {
Column() {
this.headerBuilder()
Scroll() {
Column() {
if (this.currentBottomTab === 0) { this.bazaarContent() }
else if (this.currentBottomTab === 1) { this.swapContent() }
else if (this.currentBottomTab === 2) { this.collectionContent() }
else { this.mineContent() }
}.width('100%')
}.layoutWeight(1).scrollBar(BarState.Off).align(Alignment.Top)
this.bottomTabsBuilder()
}.width('100%').height('100%')
ForEach(this.particles, (p: ParticleItem, i: number) => {
Text(p.emoji).fontSize(p.size).opacity(p.opacity).position({ x: p.x, y: 80 + (i % 5) * 118 })
}, (p: ParticleItem, i: number) => 'pt' + i.toString())
if (this.showDetailModal) {
Column() { this.detailModalBuilder() }.width('100%').height('100%').backgroundColor('99000000').justifyContent(FlexAlign.Center).onClick(() => { this.showDetailModal = false; })
}
if (this.showSellModal) {
Column() { this.sellModalBuilder() }.width('100%').height('100%').backgroundColor('99000000').justifyContent(FlexAlign.Center).onClick(() => { this.showSellModal = false; })
}
if (this.showSwapModal) {
Column() { this.swapModalBuilder() }.width('100%').height('100%').backgroundColor('99000000').justifyContent(FlexAlign.Center).onClick(() => { this.showSwapModal = false; })
}
if (this.showDeleteModal) {
Column() { this.deleteModalBuilder() }.width('100%').height('100%').backgroundColor('99000000').justifyContent(FlexAlign.Center).onClick(() => { this.showDeleteModal = false; })
}
}.width('100%').height('100%').backgroundColor(PALETTE.bg)
}
}
Logo

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

更多推荐