uni-app x跨平台开发实战:鸿蒙HarmonyOS电影App个人中心页实现详解

pages/tabBar/mine.uvue 是 iMovie 应用的「个人中心」标签页,主要承担用户信息展示、统计数据概览以及导航到常用功能入口(音乐推荐、影视列表、搜索、设置等)的职责。

该页面基于 uni-app x 的 uvue 单文件结构实现,整体设计遵循「深色卡片 + 极简菜单」风格,同时利用 UTS 强类型和模块级 store 读取播放列表数据,保证跨页面状态的一致性。

该项目的开源地址https://gitcode.com/qq8864/uniappx_imovie

同时支持Android、IOS、HarmonyOS和Web、小程序等平台。

实现效果:

在这里插入图片描述


1. 页面整体结构:滚动容器 + 多卡片布局

个人中心页最外层使用 scroll-view 作为纵向滚动容器,便于在内容较多时保持良好的滚动体验:

<template>
  <scroll-view class="page" direction="vertical">

    <!-- 顶部用户信息卡片 -->
    <view class="profile-header">
      <!-- ...头像、用户名、标签... -->
    </view>

    <!-- 数据统计 -->
    <view class="stats-card">
      <!-- 观看记录 / 收藏影视 / 歌曲列表 三列统计 -->
    </view>

    <!-- 我的内容:音乐 & 影视入口 -->
    <view class="section-title-row">
      <view class="section-bar" />
      <text class="section-label">我的内容</text>
    </view>
    <view class="menu-card">
      <!-- 每日推荐 / 推荐歌单 / 热门影视 / 搜索影视 菜单项 -->
    </view>

    <!-- 设置分区 -->
    <view class="section-title-row">
      <view class="section-bar" />
      <text class="section-label">设置</text>
    </view>
    <view class="menu-card">
      <!-- 关于应用 / 清除缓存 菜单项 -->
    </view>

    <!-- 底部版本信息 -->
    <view class="footer">
      <text class="footer-text">iMovie v1.0.0</text>
      <text class="footer-sub">影视 · 音乐 · 一站体验</text>
    </view>

  </scroll-view>
</template>

这样的结构具有几个优点:

  • 顶层滚动容器:无论后续添加多少模块,都能自然纵向滚动。
  • 功能分区清晰:个人信息、统计数据、「我的内容」菜单、设置菜单和版本信息按区块排列。
  • 易扩展:未来增加「消息中心」「偏好设置」等,只需增加对应分区卡片即可。

2. 顶部用户信息卡片:头像、昵称与标签

顶部的 profile-header 卡片负责展示用户形象和简单介绍:

<!-- 顶部用户信息卡片 -->
<view class="profile-header">
  <view class="avatar-wrap">
    <image class="avatar" src="/static/logo.png" mode="aspectFill" />
    <view class="avatar-ring" />
  </view>
  <text class="username">iMovie 用户</text>
  <text class="user-desc">热爱影视 · 享受音乐</text>
  <view class="tag-row">
    <view class="tag"><text class="tag-text">影视达人</text></view>
    <view class="tag"><text class="tag-text">音乐爱好者</text></view>
  </view>
</view>

对应样式片段:

.profile-header {
  align-items: center;
  padding: 40px 24px 28px 24px;
  background-color: #13132a;
  border-bottom-left-radius: 24px;
  border-bottom-right-radius: 24px;
}

.avatar-wrap {
  position: relative;
  width: 90px;
  height: 90px;
  margin-bottom: 14px;
}

.avatar {
  width: 90px;
  height: 90px;
  border-radius: 45px;
  background-color: #1c1c2e;
}

.avatar-ring {
  position: absolute;
  top: -3px;
  left: -3px;
  width: 96px;
  height: 96px;
  border-radius: 48px;
  border-width: 2px;
  border-style: solid;
  border-color: #e67e22;
}

.username {
  font-size: 20px;
  font-weight: bold;
  color: #ffffff;
  margin-bottom: 6px;
}

.user-desc {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.45);
  margin-bottom: 14px;
}

.tag-row {
  flex-direction: row;
}

.tag {
  background-color: rgba(230, 126, 34, 0.18);
  border-radius: 12px;
  padding: 4px 12px;
  margin-right: 8px;
}

.tag-text {
  font-size: 11px;
  color: #e67e22;
}

设计要点:

  • 使用 avatar-wrap + avatar + avatar-ring 做出「头像 + 高亮边框」效果,增加质感。
  • 用户名和一句话描述居中排布,搭配轻量级标签 影视达人 / 音乐爱好者,塑造个人兴趣画像。
  • 整个卡片采用稍亮的深色背景和底部大圆角,与整体深色主题保持统一。

3. 数据统计卡片:观看记录 / 收藏影视 / 歌曲列表

下方的 stats-card 以内联三列形式展示关键数据:

<!-- 数据统计 -->
<view class="stats-card">
  <view class="stat-item">
    <text class="stat-num">{{ watchCount }}</text>
    <text class="stat-label">观看记录</text>
  </view>
  <view class="stat-divider" />
  <view class="stat-item">
    <text class="stat-num">{{ collectCount }}</text>
    <text class="stat-label">收藏影视</text>
  </view>
  <view class="stat-divider" />
  <view class="stat-item">
    <text class="stat-num">{{ playlistCount }}</text>
    <text class="stat-label">歌曲列表</text>
  </view>
</view>

对应样式:

.stats-card {
  flex-direction: row;
  margin: 16px 16px 0 16px;
  background-color: #1a1a2e;
  border-radius: 14px;
  padding: 20px 0;
}

.stat-item {
  flex: 1;
  align-items: center;
}

.stat-num {
  font-size: 22px;
  font-weight: bold;
  color: #e67e22;
  margin-bottom: 4px;
}

.stat-label {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.4);
}

.stat-divider {
  width: 1px;
  background-color: rgba(255, 255, 255, 0.08);
  margin: 4px 0;
}

数据来源:

  • watchCount / collectCount 当前为模拟数据,用于展示布局和视觉效果;
  • playlistCount 则是动态从音乐播放列表 store 中读取(见第 5 节脚本逻辑)。

4. 我的内容 & 设置菜单:统一菜单卡片组件化思路

页面中两处菜单区域(「我的内容」「设置」)都使用了统一的 menu-card + menu-row 样式,使得多个入口在视觉上有一致的“列表卡片”体验。

4.1 「我的内容」菜单
<!-- 功能菜单:我的内容 -->
<view class="section-title-row">
  <view class="section-bar" />
  <text class="section-label">我的内容</text>
</view>
<view class="menu-card">
  <view class="menu-row" @click="goPage('/pages/music/daily-list')">
    <view class="menu-icon-wrap" style="background-color: rgba(230,126,34,0.15);">
      <text class="menu-icon"></text>
    </view>
    <text class="menu-text">每日推荐</text>
    <text class="menu-arrow"></text>
  </view>
  <view class="menu-sep" />
  <view class="menu-row" @click="goPage('/pages/music/menu-list')">
    <view class="menu-icon-wrap" style="background-color: rgba(155,89,182,0.15);">
      <text class="menu-icon" style="color: #9b59b6;"></text>
    </view>
    <text class="menu-text">推荐歌单</text>
    <text class="menu-arrow"></text>
  </view>
  <view class="menu-sep" />
  <view class="menu-row" @click="goPage('/pages/movie/hotmovie-list')">
    <view class="menu-icon-wrap" style="background-color: rgba(231,76,60,0.15);">
      <text class="menu-icon" style="color: #e74c3c;"></text>
    </view>
    <text class="menu-text">热门影视</text>
    <text class="menu-arrow"></text>
  </view>
  <view class="menu-sep" />
  <view class="menu-row" @click="goPage('/pages/movie/search')">
    <view class="menu-icon-wrap" style="background-color: rgba(52,152,219,0.15);">
      <text class="menu-icon" style="color: #3498db;"></text>
    </view>
    <text class="menu-text">搜索影视</text>
    <text class="menu-arrow"></text>
  </view>
</view>

各入口均使用统一的左图标 + 中标题 + 右箭头布局,通过不同的背景色与图标颜色区分功能类型。

4.2 「设置」菜单
<!-- 设置菜单 -->
<view class="section-title-row">
  <view class="section-bar" />
  <text class="section-label">设置</text>
</view>
<view class="menu-card">
  <view class="menu-row" @click="showAbout">
    <view class="menu-icon-wrap" style="background-color: rgba(46,204,113,0.15);">
      <text class="menu-icon" style="color: #2ecc71;"></text>
    </view>
    <text class="menu-text">关于应用</text>
    <text class="menu-arrow"></text>
  </view>
  <view class="menu-sep" />
  <view class="menu-row" @click="clearCache">
    <view class="menu-icon-wrap" style="background-color: rgba(149,165,166,0.15);">
      <text class="menu-icon" style="color: #95a5a6;"></text>
    </view>
    <text class="menu-text">清除缓存</text>
    <text class="menu-sub">{{ cacheSize }}</text>
  </view>
</view>

清除缓存 一项在右侧使用 menu-sub 显示当前缓存大小,视觉上与其他菜单保持一致但信息更丰富。

对应的公共菜单样式:

.section-title-row {
  flex-direction: row;
  align-items: center;
  padding: 20px 16px 10px 16px;
}

.section-bar {
  width: 3px;
  height: 14px;
  background-color: #e67e22;
  border-radius: 2px;
  margin-right: 8px;
}

.section-label {
  font-size: 14px;
  font-weight: bold;
  color: rgba(255, 255, 255, 0.7);
}

.menu-card {
  margin: 0 16px;
  background-color: #1a1a2e;
  border-radius: 14px;
  overflow: hidden;
}

.menu-row {
  flex-direction: row;
  align-items: center;
  padding: 14px 16px;
}

.menu-icon-wrap {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  align-items: center;
  justify-content: center;
  margin-right: 14px;
  flex-shrink: 0;
}

.menu-icon {
  font-size: 18px;
  color: #e67e22;
}

.menu-text {
  flex: 1;
  font-size: 15px;
  color: #e0e0e0;
}

.menu-sub {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.3);
}

.menu-arrow {
  font-size: 20px;
  color: rgba(255, 255, 255, 0.25);
}

.menu-sep {
  height: 1px;
  background-color: rgba(255, 255, 255, 0.05);
  margin-left: 66px;
}

设计要点:

  • 使用统一的菜单组件化样式,方便后续抽离为可复用组件。
  • menu-sep 通过 margin-left: 66px 让分隔线从图标右侧开始,增强层级感。
  • 不同入口通过少量行内样式调整图标底色和前景色,既统一又有差异化。

5. 脚本逻辑:统计数据与导航交互

mine.uvue 使用 <script setup lang="uts">,逻辑简洁清晰:

<script setup lang="uts">
  import { ref, onMounted } from 'vue'
  import { getPlaylist } from '@/store/playlistStore'

  const watchCount = ref<number>(0)
  const collectCount = ref<number>(0)
  const playlistCount = ref<number>(0)
  const cacheSize = ref<string>('计算中...')

  const goPage = (url : string) => {
    uni.navigateTo({ url })
  }

  const showAbout = () => {
    uni.showModal({
      title: '关于 iMovie',
      content: 'iMovie v1.0.0\n一款集影视浏览与音乐播放于一体的综合娱乐应用。',
      showCancel: false,
      confirmText: '知道了'
    })
  }

  const clearCache = () => {
    uni.showToast({ title: '缓存已清除', icon: 'success', duration: 1500 })
    cacheSize.value = '0 KB'
  }

  onMounted(() => {
    // 从播放列表 store 读取歌曲数
    playlistCount.value = getPlaylist().length
    // 模拟数据
    watchCount.value = 12
    collectCount.value = 5
    cacheSize.value = '2.3 MB'
  })
</script>

核心逻辑说明:

  • 导航 goPage:所有跳转入口统一调用 goPage(url),使用 uni.navigateTo 保持页面跳转一致性。
  • 关于应用 showAbout:通过 uni.showModal 展示应用简介,使用单按钮确认形式,简洁直观。
  • 清除缓存 clearCache:当前实现为示意逻辑,通过 uni.showToast 提示已清除,并将 cacheSize 置为 0 KB,后续可替换为真实缓存清理 API。
  • 统计数据初始化
    • onMounted 生命周期中从 playlistStore 读取当前播放列表长度,填充 playlistCount,体现与音乐模块的联动;
    • watchCount / collectCountcacheSize 目前使用模拟数据,未来可替换为真实后端或本地存储统计。

UTS 强类型(如 ref<number>ref<string>)确保在编译阶段就能发现类型问题,有利于长期维护。


6. 底部版本信息与整体主题

页面底部通过一个简单的 footer 块给出版本和一句 slogan:

<!-- 版本信息 -->
<view class="footer">
  <text class="footer-text">iMovie v1.0.0</text>
  <text class="footer-sub">影视 · 音乐 · 一站体验</text>
</view>
.footer {
  align-items: center;
  padding: 32px 0 24px 0;
}

.footer-text {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.2);
  margin-bottom: 4px;
}

.footer-sub {
  font-size: 11px;
  color: rgba(255, 255, 255, 0.12);
}

整体主题使用深色背景:

.page {
  flex: 1;
  background-color: #0e0e1a;
}

配合各卡片的略浅深色底、主题橙色高亮 #e67e22 和适当的圆角,使整个个人中心页在视觉上统一且不显压抑。


7. 小结与可扩展方向

pages/tabBar/mine.uvue 通过 滚动容器 + 卡片分区 + 统一菜单组件化样式 + 简洁 UTS 逻辑,实现了一个结构清晰、易扩展的个人中心页面:

  • 顶部用户信息突出个性和兴趣,强化应用品牌感;
  • 数据统计和菜单入口将「影视 + 音乐」两大功能线索在个人视角下汇总;
  • 通过 playlistStore 与音乐模块打通,展示当前歌曲列表规模;
  • 设置区提供基础应用信息和缓存管理入口。

未来可以在此基础上扩展:

  • 接入真实用户系统,展示头像、昵称和个性签名;
  • 将观看记录和收藏数据与后端打通,实现数据持久化;
  • 增加主题切换、播放偏好配置等个性化设置,让个人中心真正成为“用户的控制面板”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

特立独行的猫a

您的鼓励是我的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值