news 2025/12/25 13:06:29

【江鸟中原】鸿蒙云播客(原有基础加上新功能)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【江鸟中原】鸿蒙云播客(原有基础加上新功能)

1. 核心创新功能实现(重点)

核心创新亮点:针对现有播客App“查找繁琐、续听不便、筛选低效”三大痛点,新增「播客收藏与本地缓存」「播放进度记忆」「分类筛选」3大核心功能,结合鸿蒙数据持久化、状态联动等技术,显著提升用户使用体验,为应用核心竞争力。

1.1 创新功能1:播客收藏与本地缓存

1.1.1 功能痛点解决

用户常用播客需反复在列表中查找,且离线场景下无法播放。本功能支持一键收藏播客,同时可选择本地缓存,离线状态下也能流畅收听,提升用户粘性。

1.1.2 核心技术点

  • 鸿蒙数据持久化:使用ohos.data.preferences存储收藏列表,保证重启应用后收藏状态不丢失
  • 文件管理:通过@kit.FileKit获取应用沙箱目录,实现播客音频文件本地缓存
  • 状态联动:收藏按钮状态与偏好设置实时同步,避免重复收藏

1.1.3 实现代码(以find页面新增收藏按钮为例)

Plain Text

// 新增导入:数据持久化与文件管理相关API
import preferences from '@ohos.data.preferences';
import { FileManager, FileType } from '@kit.FileKit';
import { BusinessError } from '@ohos.base';

@Preview
@ComponentV2
struct find{
GlobalPodcast:GlobalPodcast = AppStorageV2.connect(GlobalPodcast,"GlobalPodcast",()=> new GlobalPodcast())!
pageStack: NavPathStack = AppStorageV2.connect(NavPathStack,"navStack",()=> new NavPathStack())!
podcasts: PodcastItemType[]=podcastpodcastsList
// 新增:偏好设置实例(存储收藏列表)
private pref: preferences.Preferences | null = null;
// 新增:收藏状态映射
@Local collectStatus: Map<string, boolean> = new Map();

// 新增:页面初始化时加载收藏列表
async aboutToAppear() {
// 初始化偏好设置
this.pref = await preferences.getPreferences(this.context, 'podcast_collect');
// 读取收藏列表并初始化状态
const collectList = await this.pref.getString('collectIds', '');
if (collectList) {
collectList.split(',').forEach(id => {
this.collectStatus.set(id, true);
});
}
}

// 新增:收藏/取消收藏方法
async toggleCollect(item: PodcastItemType) {
if (!this.pref) return;
const isCollected = this.collectStatus.get(item.id) || false;
if (isCollected) {
// 取消收藏:移除偏好设置中的id
this.collectStatus.delete(item.id);
const collectIds = Array.from(this.collectStatus.keys()).join(',');
await this.pref.putString('collectIds', collectIds);
} else {
// 新增收藏:添加到偏好设置
this.collectStatus.set(item.id, true);
const collectIds = Array.from(this.collectStatus.keys()).join(',');
await this.pref.putString('collectIds', collectIds);
// 可选:本地缓存播客音频
this.cachePodcast(item);
}
// 提交偏好设置修改
await this.pref.flush();
}

// 新增:播客本地缓存方法
async cachePodcast(item: PodcastItemType) {
try {
// 获取应用沙箱缓存目录
const cacheDir = await FileManager.getCacheDir(this.context);
// 模拟下载:实际项目中替换为真实音频下载请求
const audioData = await this.downloadPodcastAudio(item.url);
// 写入本地文件
const file = await FileManager.createFile(cacheDir, `${item.id}.mp3`, FileType.FILE);
await FileManager.writeFile(file.uri, audioData);
console.log(`播客${item.name}缓存成功,路径:${file.uri}`);
} catch (error) {
const err = error as BusinessError;
console.error(`缓存失败:${err.message}`);
}
}

// 新增:模拟播客音频下载(实际对接后端接口)
async downloadPodcastAudio(url: string): Promise<ArrayBuffer> {
const response = await fetch(url);
return await response.arrayBuffer();
}

build() {
Column(){
List(){
ForEach(this.podcasts,((item:PodcastItemType,index:number)=>{
ListItem(){
Flex({alignItems:ItemAlign.Center}){
Row(){
Image($r('app.media.'+item.img)).width("30%").borderRadius(15).margin(5)
Column({space:15}){
Text(item.name).fontColor(Color.White).fontWeight(FontWeight.Bold)
Flex({alignItems:ItemAlign.Center}){
Text("vip").border({width:1,color:"#837F41",radius:"40%"}).fontColor("#837F41").width(35)
.textAlign(TextAlign.Center)
Text(item.author).fontColor("#ff9d9d9d").height(30).margin({left:10})
}
}.margin({left:5}).alignItems(HorizontalAlign.Start)
.onClick(()=>{
if (this.GlobalPodcast.podcastList.length<=0) {
this.GlobalPodcast.podcastList=this.podcasts
}
avPlayerPodcastManage.playPodcastResources(item)
this.pageStack.pushPathByName("play",item)
})
}.margin(5) .justifyContent(FlexAlign.Center)
// 新增:收藏按钮(根据状态切换图标)
Image(this.collectStatus.get(item.id) ? $r('app.media.ic_collect_selected') : $r('app.media.ic_collect_normal'))
.height(25).fillColor(Color.White).margin({right:5})
.onClick(()=>this.toggleCollect(item))
// 新增:缓存按钮
Image($r('app.media.ic_cache')).height(25).fillColor(Color.White).margin({right:5})
.onClick(()=>this.cachePodcast(item))
}
}
}))
}.width("100%").height("100%")
}
.alignItems(HorizontalAlign.Start)
.width("100%").height("100%")
}
}

1.2 创新功能2:播放进度记忆

1.2.1 功能痛点解决

用户播放播客时切换页面、中断播放或重启应用后,需重新拖动进度条查找上次播放位置,操作繁琐。本功能自动记忆每首播客的最后播放进度,再次播放时直接从记忆位置续听。

1.2.2 核心技术点

  • 播放状态监听:通过avPlayerPodcastManage监听播放进度变化,每3秒同步一次进度数据
  • 键值对存储:使用偏好设置以「播客id-播放进度」的键值对形式存储,查询效率高
  • 初始化联动:播客开始播放前,先读取对应进度数据,实现无缝续听

1.2.3 实现代码(工具类avPlayerPodcast新增进度记忆)

Plain Text

// avPlayerPodcast.ts 新增进度记忆逻辑
import { GlobalPodcast } from "../type/GlobalPodcast";
import preferences from '@ohos.data.preferences';

export class avPlayerPodcastManage {
private static instance: avPlayerPodcastManage;
private avPlayer: media.AVPlayer | null = null;
private pref: preferences.Preferences | null = null;
// 进度同步定时器
private progressTimer: number | null = null;

// 初始化时创建偏好设置
async init() {
this.pref = await preferences.getPreferences(globalThis.context, 'podcast_progress');
}

// 播放播客时,先读取进度
async playPodcastResources(item: PodcastItemType) {
if (!this.avPlayer || !this.pref) return;
// 读取该播客的历史播放进度(单位:秒)
const progress = await this.pref.getNumber(item.id, 0);
// 设置播放源
this.avPlayer.src = item.url;
await this.avPlayer.prepare();
// 跳转到历史进度
if (progress > 0) {
this.avPlayer.currentTime = progress;
}
// 开始播放
await this.avPlayer.play();
// 启动进度同步定时器(每3秒同步一次)
this.startProgressSync(item.id);
}

// 新增:进度同步到偏好设置
private startProgressSync(podcastId: string) {
// 清除原有定时器
if (this.progressTimer) {
clearInterval(this.progressTimer);
}
this.progressTimer = setInterval(async () => {
if (!this.avPlayer || !this.pref) return;
const currentProgress = this.avPlayer.currentTime;
// 存储当前进度
await this.pref.putNumber(podcastId, currentProgress);
await this.pref.flush();
}, 3000);
}

// 停止播放时,清除定时器
async stopOrContinuePodcast() {
if (this.avPlayer) {
if (this.avPlayer.state === media.PlaybackState.PLAYING) {
await this.avPlayer.pause();
if (this.progressTimer) {
clearInterval(this.progressTimer);
}
} else {
await this.avPlayer.play();
// 重新启动进度同步
const currentPodcast = GlobalPodcast.getInstance().currentPodcast;
if (currentPodcast) {
this.startProgressSync(currentPodcast.id);
}
}
}
}

// 单例模式
static getInstance(): avPlayerPodcastManage {
if (!this.instance) {
this.instance = new avPlayerPodcastManage();
this.instance.init();
}
return this.instance;
}
}

1.3 创新功能3:播客分类筛选

1.3.1 功能痛点解决

原有播客列表仅按默认顺序展示,用户难以快速找到“科技”“情感”“职场”等特定类型内容。本功能新增顶部分类标签栏,支持按类型筛选,提升内容查找效率。

1.3.2 核心技术点

  • 数据分类定义:扩展PodcastItemType类型,新增category字段标记播客类型
  • 状态驱动筛选:通过@State维护当前选中分类,实现列表实时过滤
  • 弹性布局适配:分类标签使用横向滚动布局,支持多分类且不挤压页面空间

1.3.3 实现代码(recommend页面新增分类筛选)

Plain Text

// 1. 先扩展PodcastItemType类型(type/PodcastItemType.ts)
export interface PodcastItemType {
id: string;
name: string;
author: string;
img: string;
url: string;
category: 'tech' | 'emotion' | 'work' | 'entertainment'; // 新增分类字段
}

// 2. recommend页面新增分类筛选栏
@Component
struct recommend {
// 轮播图数据
swiperList: string[] = [
"https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner1.png",
"https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner2.png",
"https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner3.png",
"https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner4.png",
"https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner5.png"
]
@State dailyRecommend: recommendDailyType[] = []
@State recommendList: recommendListType[] = []
// 新增:分类列表与当前选中分类
@State categories: { key: string; label: string }[] = [
{ key: 'all', label: '全部' },
{ key: 'tech', label: '科技' },
{ key: 'emotion', label: '情感' },
{ key: 'work', label: '职场' },
{ key: 'entertainment', label: '娱乐' }
]
@State selectedCategory: string = 'all'; // 默认选中“全部”

aboutToAppear(): void {
this.dailyRecommend = dailyRecommend;
this.recommendList = recommendList;
}

@Builder
naviRow(title: string) {
Flex({ justifyContent: FlexAlign.SpaceBetween }) {
Text(title).fontColor("#fff6f5f5").fontSize(18).fontWeight(FontWeight.Bold)
Image($r("app.media.ic_more")).height(20).fillColor("#ffd6d6d6")
}.margin(10)
}

build() {
Column() {
// 搜索栏(原有代码不变)
Flex({ justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.Center }) {
Image($r("app.media.ic_search")).height(20).fillColor("#ffa5a5a5")
TextInput({ placeholder: "搜索播客..." }).fontColor("##fff").placeholderColor("#FF696969")
Image($r("app.media.ic_code")).height(20).fillColor("#ffa5a5a5")
}
.backgroundColor("#ff2b2b2b")
.margin({ left: 10, right: 10, bottom: 10 })
.padding({ left: 10, right: 10 })
.borderRadius("50%")

// 新增:分类筛选栏(横向滚动)
List() {
ListItem() {
Flex({ alignItems: ItemAlign.Center, space: 15 }) {
ForEach(this.categories, (cat) => {
Text(cat.label)
.fontSize(15)
.fontColor(this.selectedCategory === cat.key ? Color.White : Color.Gray)
.backgroundColor(this.selectedCategory === cat.key ? "#837F41" : "transparent")
.padding({ left: 12, right: 12, top: 5, bottom: 5 })
.borderRadius(20)
.onClick(() => {
this.selectedCategory = cat.key; // 切换选中分类
})
})
}
}
}
.listDirection(Axis.Horizontal)
.scrollBar(BarState.Off)
.margin({ left: 10, bottom: 10 })

// 轮播图(原有代码不变)
Swiper() {
ForEach(this.swiperList, ((item: string) => {
Image(item).width("100%").height("25%").borderRadius("3%")
}))
}.margin(10).autoPlay(true)

this.naviRow("每日推荐")

// 新增:分类筛选逻辑(过滤每日推荐列表)
List() {
ForEach(this.dailyRecommend.filter(item => {
// 全部分类显示所有,否则按category匹配
return this.selectedCategory === 'all' || item.category === this.selectedCategory;
}), ((item: recommendDailyType) => {
ListItem() {
Column() {
Text(item.type)
.height("15%")
.width("100%")
.backgroundColor(item.top)
.fontColor(Color.White)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.padding({ left: 5 })
.borderRadius({ topLeft: 5, topRight: 5 })

Image(item.img).height("65%").width("100%")

Text(item.title)
.height("20%")
.width("100%")
.backgroundColor(item.bottom)
.fontColor(Color.White)
.fontSize(13)
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.ellipsisMode(EllipsisMode.END)
.padding({ left: 5 })
.borderRadius({ bottomLeft: 5, bottomRight: 5 })

}.width("40%").height("100%")
}.margin({ left: 10 })
}))
}.scrollBar(BarState.Off)
.width("100%")
.height("30%")
.listDirection(Axis.Horizontal)

this.naviRow("推荐播客单")

// 新增:分类筛选逻辑(过滤推荐播客单)
List() {
ForEach(this.recommendList.filter(item => {
return this.selectedCategory === 'all' || item.category === this.selectedCategory;
}), ((item: recommendListType) => {
ListItem() {
Column() {
Stack() {
Image(item.img).width(100).height(100).borderRadius(10)
Text(item.count).fontColor(Color.White).fontSize(12).fontWeight(FontWeight.Bold)
.padding(10).position({top:0})
}.width("30%")

Text(item.title)
.fontColor("#ffc8c8c8")
.fontSize(12)
.padding({ left: 5 })
.width("30%")
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.ellipsisMode(EllipsisMode.END)
.margin({top:5})
}
}
}))
}
.listDirection(Axis.Horizontal)
.width("100%")
.height("30%")
}
.width("100%")
.height("100%")
}
}

. 项目概述

2.1 应用介绍

2. 项目概述

2.2 核心功能清单

“鸿蒙云播客”是基于HarmonyOS SDK开发的播客类应用,聚焦播客播放播客核心需求,延伸出播客单展示、用户互动、个性化推荐等功能。应用采用声明式UI框架ArkUI开发,适配鸿蒙多设备界面规范,支持跨页面状态共享,为用户提供流畅的播客体验。

. 技术栈与项目结构

3.1 技术选型

功能模块

具体实现

对应页面

播客播客播放管理

播客列表展示、播放播客/暂停播客控制、播客播放播客页跳转

find页面

个人信息展示

用户昵称、标签、关注/粉丝/赞数据统计

mine页面

用户互动

动态列表、播客关联播放播客、点赞/评论/分享

moment页面

内容推荐

轮播图、每日推荐、推荐播客单、搜索功能

recommend页面

3. 核心页面实现详解

3.1 find页面:播客列表与播放播客触发

3.1.1 功能定位

作为播客列表核心入口,展示所有可播放播客播客,点击播客项触发播放播客逻辑,同步全局播放播客列表,并跳转至播客播放播客页面。

3.1.2 核心技术点

  • List+ForEach组件:高效渲染播客列表,循环遍历podcastpodcastsList数据
  • AppStorageV2:连接GlobalPodcast全局状态,维护播放播客列表podcastList
  • 页面跳转:通过NavPathStack的pushPathByName方法跳转至播客播放播客页
  • 图片资源引用:通过$r('app.media.'+item.img)动态加载播客封面

3.1.3 完整代码

typescript








import { podcastpodcastsList } from "../../type/data"
import { PodcastItemType } from "../../type/PodcastItemType"
import { AppStorageV2 } from "@kit.ArkUI"
import { avPlayerPodcastManage } from "../../ulits/avPlayerPodcast"
import { GlobalPodcast } from "../../type/GlobalPodcast"
import { hilog } from "@kit.PerformanceAnalysisKit"

@Preview
@ComponentV2
struct find{
GlobalPodcast:GlobalPodcast = AppStorageV2.connect(GlobalPodcast,"GlobalPodcast",()=> new GlobalPodcast())!
pageStack: NavPathStack = AppStorageV2.connect(NavPathStack,"navStack",()=> new NavPathStack())!
podcasts: PodcastItemType[]=podcastpodcastsList

build() {
Column(){
List(){
ForEach(this.podcasts,((item:PodcastItemType,index:number)=>{
ListItem(){
Flex({alignItems:ItemAlign.Center}){
Row(){
Image($r('app.media.'+item.img)).width("30%").borderRadius(15).margin(5)
Column({space:15}){
Text(item.name).fontColor(Color.White).fontWeight(FontWeight.Bold)
Flex({alignItems:ItemAlign.Center}){
Text("vip").border({width:1,color:"#837F41",radius:"40%"}).fontColor("#837F41").width(35)
.textAlign(TextAlign.Center)
Text(item.author).fontColor("#ff9d9d9d").height(30).margin({left:10})
}
}.margin({left:5}).alignItems(HorizontalAlign.Start)
.onClick(()=>{
if (this.GlobalPodcast.podcastList.length<=0) {
this.GlobalPodcast.podcastList=this.podcasts
}
avPlayerPodcastManage.playPodcastResources(item)
this.pageStack.pushPathByName("play",item)
})
}.margin(5) .justifyContent(FlexAlign.Center)
Image($r('app.media.'+item.img)).height(30)
.fillColor(Color.White).margin({right:5})
}
}
}))
}.width("100%").height("100%")
}
.alignItems(HorizontalAlign.Start)
.width("100%").height("100%")
}
}

export default find

3.2 mine页面:个人信息展示

3.2.1 功能定位

展示用户个性化信息,包括头像、昵称、用户标签及关注、粉丝、获赞数据,采用分层布局提升视觉效果。

3.2.2 核心技术点

  • Stack组件:实现背景图与头像的分层叠加,设置alignContent为Alignment.Bottom定位头像
  • 弹性布局:通过Column+Row组合,配合flexGrow实现数据统计项均匀分布
  • 安全区域适配:expandSafeArea()方法适配设备刘海屏、状态栏区域

    图片适配:objectFit(ImageFit.Cover)保证背景图完整覆盖容器

    3.2.3 完整代码

    typescript
    @Preview
    @Component
    struct mine{
    build() {
    Column() {
    // 图片区域 - 占高度70%
    Stack({
    alignContent: Alignment.Bottom
    }) {
    // 背景大图片
    Image($r('app.media.wave'))
    .width('100%')
    .height('100%')
    .objectFit(ImageFit.Cover)

    // 上层logo
    Image($r('app.media.logo'))
    .width(80)
    .height(80)
    .margin({ bottom: 30 })
    }
    .height('70%')

    // 介绍区域 - 占高度30%
    Column() {
    // 第一行:软件名字
    Text('江上清风')
    .fontSize(20)
    .fontWeight(FontWeight.Bold)
    .fontColor(Color.White)
    .margin({ bottom: 10 })

    // 第二行:用户基本信息
    Text('00后 射手座 河南 播龄:18年')
    .fontSize(14)
    .fontColor(Color.White)
    .opacity(0.8)
    .margin({ bottom: 20 })

    // 第三行:账户信息
    Row() {
    Column() {
    Text('1')
    .fontSize(18)
    .fontWeight(FontWeight.Bold)
    .fontColor(Color.White)
    Text('关注')
    .fontSize(12)
    .fontColor(Color.White)
    .opacity(0.8)
    }
    .flexGrow(1)

    Column() {
    Text('1.2亿')
    .fontSize(18)
    .fontWeight(FontWeight.Bold)
    .fontColor(Color.White)
    Text('粉丝')
    .fontSize(12)
    .fontColor(Color.White)
    .opacity(0.8)
    }
    .flexGrow(1)

    Column() {
    Text('1.67亿')
    .fontSize(18)
    .fontWeight(FontWeight.Bold)
    .fontColor(Color.White)
    Text('赞')
    .fontSize(12)
    .fontColor(Color.White)
    .opacity(0.8)
    }
    .flexGrow(1)
    }.width("60%")
    .justifyContent(FlexAlign.SpaceBetween)
    }
    .height('30%')
    .justifyContent(FlexAlign.Center)

    }
    .width('100%')
    .height('100%')
    .expandSafeArea()
    }
    }
    export default mine

    3.3 moment页面:互动广场与播放播客控制

    3.3.1 功能定位

    用户互动核心页面,展示包含播客关联的用户动态,支持根据全局播客播放播客状态切换播放播客/暂停播客按钮,实现动态点赞、评论、分享操作。

    3.3.2 核心技术点

    • @Local装饰器:声明页面局部状态,存储播客数据和动态列表数据
    • 播客播放播客状态同步:通过对比当前动态播客url与全局playState.url,切换播放播客/暂停播客图标
    • 滚动优化:设置edgeEffect(EdgeEffect.None)、scrollBar(BarState.Off)提升滚动体验
    • 嵌套滚动:nestedScroll配置实现与父组件的滚动协同
    • 文本溢出处理:maxLines+ellipsisMode实现动态内容单行省略

    3.3.3 完整代码

    typescript










    import { GlobalPodcast } from "../../type/GlobalPodcast";
    import { AppStorageV2 } from "@kit.ArkUI";
    import { momentList, podcastpodcastsList } from "../../type/data";
    import { momentListType } from "../../type/momentListType";
    import { PodcastItemType } from "../../type/PodcastItemType";
    import { avPlayerPodcastManage } from "../../ulits/avPlayerPodcast";

    @Preview
    @ComponentV2
    struct moment {
    // 播客数据
    @Local
    podcasts: PodcastItemType[] = podcastpodcastsList
    @Local
    momentList:momentListType[]=momentList
    @Local
    playState: GlobalPodcast = AppStorageV2.connect(GlobalPodcast, "GlobalPodcast", () => new GlobalPodcast())!

    build() {
    Scroll() {
    Column() {
    // 标题
    Text('互动广场')
    .fontSize(24)
    .fontWeight(FontWeight.Bold)
    .fontColor(Color.White)
    .margin({ top: 20, bottom: 20, left: 20 })
    .alignSelf(ItemAlign.Start)

    // 动态列表
    List() {
    ForEach(this.momentList, (item: momentListType) => {
    ListItem() {
    Column() {
    // 用户信息和内容区域
    Row() {
    // 用户头像
    Image(item.avatar)
    .width(48)
    .height(48)
    .borderRadius(24)
    .margin({ right: 12 })
    .objectFit(ImageFit.Cover)

    // 用户信息和内容
    Column() {
    // 用户名
    Text(item.author)
    .fontSize(16)
    .fontWeight(FontWeight.Medium)
    .fontColor(Color.White)
    .alignSelf(ItemAlign.Start)
    .margin({ bottom: 8 })

    // 内容
    Text(item.content)
    .width("80%")
    .maxLines(1)
    .ellipsisMode(EllipsisMode.END)
    .textOverflow({ overflow: TextOverflow.Ellipsis })
    .fontSize(16)
    .fontColor(Color.White)
    .alignSelf(ItemAlign.Start)
    .margin({ bottom: 12 })
    .lineHeight(24)

    // 播客信息卡片
    Row() {
    Image(item.song.img)
    .width(48)
    .height(48)
    .borderRadius(4)
    .objectFit(ImageFit.Cover)

    Column() {
    Text(item.song.name)
    .fontSize(14)
    .fontColor(Color.White)
    .fontWeight(FontWeight.Medium)
    .alignSelf(ItemAlign.Start)
    .lineHeight(20)

    Text(item.song.author)
    .fontSize(12)
    .fontColor(Color.Gray)
    .alignSelf(ItemAlign.Start)
    .lineHeight(18)
    }

    // 播放播客按钮文本
    Image(item.song.url===this.playState.url&&
    this.playState.isPlay?$r('app.media.ic_paused'):$r('app.media.ic_play'))
    .width(20) .margin({ left: 'auto' })
    .onClick(()=>{
    if (item.song.url===this.playState.url) {
    avPlayerPodcastManage.stopOrContinuePodcast()
    }else {
    avPlayerPodcastManage.playPodcastResources(item.song)
    }
    })
    } .width("65%")
    .justifyContent(FlexAlign.SpaceBetween)
    .backgroundColor('#2A2A2A')
    .borderRadius(8)
    .padding(8)
    .margin({ bottom: 12 })
    }
    .alignItems(HorizontalAlign.Start)
    }
    .justifyContent(FlexAlign.SpaceBetween)
    .alignItems(VerticalAlign.Top)

    // 操作按钮区域
    Row() {
    // 分享按钮
    Row() {
    Text('↗ 分享')
    .fontSize(14)
    .fontColor(Color.White)
    }
    .margin({ right: 24 })

    // 评论按钮
    Row() {
    Text('�� ' + item.comment.toString())
    .fontSize(14)
    .fontColor(Color.White)
    }
    .margin({ right: 24 })

    // 点赞按钮
    Row() {
    Text('❤️ ' + item.like.toString())
    .fontSize(14)
    .fontColor(Color.White)
    }
    }
    .margin({left:10})
    .alignSelf(ItemAlign.Start)
    }
    .width("100%")
    }.margin({ bottom: 5, top: 5 })
    }, (item: momentListType) => item.author)
    }
    .edgeEffect(EdgeEffect.None)
    .scrollBar(BarState.Off)
    .nestedScroll({
    scrollForward: NestedScrollMode.PARENT_FIRST,
    scrollBackward: NestedScrollMode.SELF_FIRST
    })
    .divider({ strokeWidth: 1, color: "#ff343434" })
    .width('100%')
    .height('100%')
    .padding({ top: 10, left: 10, right: 10 })
    .scrollBar(BarState.Off)
    }
    }.scrollBar(BarState.Off)
    .width('100%')
    .height('100%')
    .expandSafeArea()
    }
    }

    export default moment

    3.4 recommend页面:内容推荐与搜索

    3.4.1 功能定位

    应用首页,集成轮播图广告、每日推荐内容、推荐播客单展示及搜索功能,为用户提供内容发现入口。

    3.4.2 核心技术点

    • @Builder装饰器:封装naviRow方法,实现标题栏+更多按钮的组件复用
    • 生命周期方法:aboutToAppear()在页面出现时初始化推荐数据
    • Swiper组件:实现自动轮播(autoPlay(true)),展示Banner图
    • 横向列表:设置listDirection(Axis.Horizontal)实现每日推荐、播客单横向滚动
    • 搜索栏布局:Flex+TextInput+Image组合,实现带图标的搜索输入框

    3.4.3 完整代码

    typescript

    import { dailyRecommend, recommendList } from "../../type/data"
    import recommendDailyType from "../../type/recommendDailyType"
    import recommendListType from "../../type/recommendListType"

    @Preview
    @Component
    struct recommend {
    // 轮播图数据
    swiperList: string[] = [
    "https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner1.png",
    "https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner2.png",
    "https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner3.png",
    "https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner4.png",
    "https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner5.png"
    ]
    @State dailyRecommend: recommendDailyType[] = []
    @State recommendList: recommendListType[] = []

    aboutToAppear(): void {
    this.dailyRecommend = dailyRecommend
    this.recommendList = recommendList
    }

    @Builder
    naviRow(title: string) {
    Flex({ justifyContent: FlexAlign.SpaceBetween }) {
    Text(title).fontColor("#fff6f5f5").fontSize(18).fontWeight(FontWeight.Bold)
    Image($r("app.media.ic_more")).height(20).fillColor("#ffd6d6d6")
    }.margin(10)
    }

    build() {
    Column() {
    Flex({ justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.Center }) {
    Image($r("app.media.ic_search")).height(20).fillColor("#ffa5a5a5")
    TextInput({ placeholder: "基尼太美��" }).fontColor("##fff").placeholderColor("#FF696969")
    Image($r("app.media.ic_code")).height(20).fillColor("#ffa5a5a5")
    }
    .backgroundColor("#ff2b2b2b")
    .margin({ left: 10, right: 10, bottom: 10 })
    .padding({ left: 10, right: 10 })
    .borderRadius("50%")

    Swiper() {
    ForEach(this.swiperList, ((item: string) => {
    Image(item).width("100%").height("25%").borderRadius("3%")
    }))
    }.margin(10).autoPlay(true)

    this.naviRow("每日推荐")

    List() {
    ForEach(dailyRecommend, ((item: recommendDailyType) => {
    ListItem() {
    Column() {
    Text(item.type)
    .height("15%")
    .width("100%")
    .backgroundColor(item.top)
    .fontColor(Color.White)
    .fontSize(14)
    .fontWeight(FontWeight.Bold)
    .padding({ left: 5 })
    .borderRadius({ topLeft: 5, topRight: 5 })

    Image(item.img).height("65%").width("100%")

    Text(item.title)
    .height("20%")
    .width("100%")
    .backgroundColor(item.bottom)
    .fontColor(Color.White)
    .fontSize(13)
    .maxLines(2)
    .textOverflow({ overflow: TextOverflow.Ellipsis })
    .ellipsisMode(EllipsisMode.END)
    .padding({ left: 5 })
    .borderRadius({ bottomLeft: 5, bottomRight: 5 })

    }.width("40%").height("100%")
    }.margin({ left: 10 })
    }))
    }.scrollBar(BarState.Off)
    .width("100%")
    .height("30%")
    .listDirection(Axis.Horizontal)

    this.naviRow("推荐播客单")

    List() {
    ForEach(this.recommendList, ((item: recommendListType) => {
    ListItem() {
    Column() {
    Stack() {
    Image(item.img).width(100).height(100).borderRadius(10)
    Text(item.count).fontColor(Color.White).fontSize(12).fontWeight(FontWeight.Bold)
    .padding(10).position({top:0})
    }.width("30%")

    Text(item.title)
    .fontColor("#ffc8c8c8")
    .fontSize(12)
    .padding({ left: 5 })
    .width("30%")
    .maxLines(2)
    .textOverflow({ overflow: TextOverflow.Ellipsis })
    .ellipsisMode(EllipsisMode.END)
    .margin({top:5})
    }
    }
    }))
    }
    .listDirection(Axis.Horizontal)
    .width("100%")
    .height("30%")
    }
    .width("100%")
    .height("100%")
    }
    }

    export default recommend

    3.5核心功能清单

    功能模块

    具体实现

    对应页面

    播客播客播放管理

    播客列表展示、播放播客/暂停播客控制、播客播放播客页跳转

    find页面

    个人信息展示

    用户昵称、标签、关注/粉丝/赞数据统计

    mine页面

    用户互动

    动态列表、播客关联播放播客、点赞/评论/分享

    moment页面

    内容推荐

    轮播图、每日推荐、推荐播客单、搜索功能

    recommend页面

    4. 关键技总结与扩展方向

    4.1 核心技术亮点

    • 声明式UI开发:ArkUI的Component/ComponentV2组件化开发,简化布局与交互绑定,提升开发效率
    • 全局状态管理:AppStorageV2实现跨页面状态共享,统一维护播客播放播客状态、页面栈等核心数据
    • 组件复用:通过@Builder封装通用组件,减少重复代码,提升代码可维护性
    • 多布局适配:灵活运用Stack、Flex、Column、Row等布局组件,适配不同页面视觉需求

    4.2 后续扩展方向

    • 功能扩展:基于现有创新功能,可增加播客单编辑、多账号登录、播客分享到社交平台、播放速度调节等功能
    • 性能优化:实现数据懒加载、图片缓存,提升列表滚动流畅度
    • 多设备适配:针对手机、平板、智慧屏等不同设备,优化界面布局与交互逻辑
    • 数据持久化:集成鸿蒙数据管理能力,实现播客播放播客历史、收藏列表本地存储
    • 网络请求:对接后端接口,实现真实播客数据、用户动态的获取与展示,同时支持用户上传自制播客
    版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
    网站建设 2025/12/20 20:57:24

    视频帧检索响应延迟高?3步完成Dify索引深度优化

    第一章&#xff1a;视频帧检索响应延迟高&#xff1f;3步完成Dify索引深度优化在处理大规模视频分析任务时&#xff0c;Dify平台常用于构建智能检索系统。然而&#xff0c;当视频帧数据量激增&#xff0c;原始索引策略往往导致检索响应延迟显著上升。通过针对性的索引优化&…

    作者头像 李华
    网站建设 2025/12/24 12:44:42

    视频帧提取的Dify存储优化(百万级帧处理核心技术曝光)

    第一章&#xff1a;视频帧提取的 Dify 存储优化在高并发视频处理场景中&#xff0c;视频帧提取的效率与存储管理直接影响系统整体性能。Dify 作为支持 AI 工作流编排的平台&#xff0c;其存储机制在处理大量临时帧文件时面临 I/O 压力与资源浪费问题。通过优化存储路径、引入缓…

    作者头像 李华
    网站建设 2025/12/20 10:37:11

    Dify项目进展大公开,加密PDF解析痛点全解析

    第一章&#xff1a;加密 PDF 解析的 Dify 进度跟踪在构建自动化文档处理系统时&#xff0c;解析加密 PDF 文件是一项常见但具有挑战性的任务。Dify 作为一个低代码 AI 应用开发平台&#xff0c;提供了灵活的工作流机制来集成自定义解析逻辑&#xff0c;从而实现对加密 PDF 的进…

    作者头像 李华
    网站建设 2025/12/20 17:44:55

    嵌入式和软件系统中常见通信协议

    1. 引言 本文重点关注嵌入式系统和软件设计中常见的通信协议。这些协议涵盖了多种应用场景&#xff0c;包括&#xff1a; FPGA 内部各个核心&#xff08;硬件模块&#xff09;之间的通信电路板上微控制器与其他 IC 之间的通信同一产品中两块电路板之间的通信以及相距较远的两…

    作者头像 李华
    网站建设 2025/12/20 10:55:12

    AutoGPT入门指南:本地安装与使用详解

    AutoGPT入门指南&#xff1a;本地安装与使用详解 在AI技术飞速演进的今天&#xff0c;我们正从“被动响应式助手”迈向一个全新的阶段——自主智能体时代。当你只需说一句“帮我写一份学习计划”&#xff0c;AI就能自己上网查资料、整理框架、生成文档并保存结果时&#xff0c…

    作者头像 李华
    网站建设 2025/12/21 7:58:07

    LobeChat如何处理长上下文会话?上下文管理机制剖析

    LobeChat的上下文管理机制深度解析 在构建现代AI聊天应用时&#xff0c;一个常被低估却至关重要的挑战浮出水面&#xff1a;如何让大语言模型&#xff08;LLM&#xff09;在长时间、多轮次的对话中依然“记得”之前发生了什么。尽管像GPT-4这样的模型拥有强大的语义理解能力&am…

    作者头像 李华