【OpenHarmony/HarmonyOS】项目实战:分享中心与近场学习报告设计

摘要

分享功能不只是把一段文字发出去。对于学习项目来说,分享可以承载成就感、打卡动力和社交传播。本文结合「英语视界 YingYu」项目,分享如何基于 ShareKit 设计学习报告、成就徽章、生词本等分享内容,并支持碰一碰和隔空传送。📤

相关文件:

entry/src/main/ets/utils/ShareService.ts
entry/src/main/ets/pages/ShareCenter.ets
entry/src/main/ets/pages/ShareGuide.ets
entry/src/main/ets/pages/ProfileContent.ets

一、为什么学习项目需要分享中心?

学习是长期行为,分享能提供外部反馈:

  • 给家长展示学习成果;
  • 和同学互相鼓励;
  • 分享连续打卡;
  • 分享自定义生词;
  • 分享成就徽章;
  • 形成学习仪式感。

「英语视界」的分享中心不是简单调用系统分享,而是先把学习数据整理成可读报告。

二、分享数据模型

学习报告数据:

export interface LearningRecordShareData {
  totalWords: number
  totalDays: number
  consecutiveDays: number
  achievementsCount: number
  achievementsTotal: number
  customWordsCount: number
  reviewDueCount: number
  todayProgress: string
  shareDate: string
}

成就分享数据:

export interface AchievementShareData {
  achievements: Achievement[]
  achievementsCount: number
  totalAchievements: number
  shareDate: string
}

生词本分享数据:

export interface CustomWordsShareData {
  words: CustomWord[]
  totalCount: number
  shareDate: string
}

通过不同数据模型,可以支持多种分享内容。

三、生成学习报告数据

项目通过 generateShareContent() 聚合学习数据:

export function generateShareContent(type: ShareContentType = 'learning_record') {
  const today = new Date()
  const shareDate = `${today.getFullYear()}${today.getMonth() + 1}${today.getDate()}日`

  if (type === 'learning_record') {
    const stats = getStatistics()
    const extendedStats = getExtendedStatistics()
    return {
      totalWords: stats.totalWords,
      totalDays: stats.totalDays,
      consecutiveDays: stats.consecutiveDays,
      achievementsCount: stats.achievementsCount,
      achievementsTotal: 12,
      customWordsCount: extendedStats.customWordsCount,
      reviewDueCount: extendedStats.reviewDueCount,
      todayProgress: `${stats.totalWords} 词 | ${stats.consecutiveDays} 天连续`,
      shareDate: shareDate
    }
  }
}

这里复用了:

  • getStatistics()
  • getExtendedStatistics()
  • getAchievements()
  • getCustomWords()

四、分享文案设计

学习报告文本:

export function generateLearningRecordText(data: LearningRecordShareData): string {
  return `🎓 我的英语学习报告\n\n📅 ${data.shareDate}\n\n` +
    `✨ 已学单词: ${data.totalWords} 个\n` +
    `📅 学习天数: ${data.totalDays} 天\n` +
    `🔥 连续打卡: ${data.consecutiveDays} 天\n` +
    `🏆 获得成就: ${data.achievementsCount}/${data.achievementsTotal}\n` +
    `📚 自定义词: ${data.customWordsCount} 个\n` +
    `🔄 待复习: ${data.reviewDueCount} 个\n\n` +
    `💪 坚持学习,遇见更好的自己!\n` +
    `📱 使用「趣味英语」App 一起学习吧~`
}

好的分享文案应该具备:

  • 数据明确;
  • 情绪积极;
  • 易读;
  • 有传播感;
  • 不暴露隐私。

五、成就分享

成就分享文本:

export function generateAchievementsText(data: AchievementShareData): string {
  const unlockedList = data.achievements.filter(a => a.unlocked)
  let text = `🏆 我的成就徽章\n\n📅 ${data.shareDate}\n\n` +
    `已解锁 ${data.achievementsCount}/${data.totalAchievements} 个成就\n\n`

  if (unlockedList.length > 0) {
    text += `✨ 已获得:\n`
    for (const ach of unlockedList) {
      text += `${ach.icon} ${ach.title}\n`
    }
  }

  text += `\n💪 继续努力,解锁更多成就!`
  return text
}

成就分享适合在用户解锁新徽章后触发。

六、生词本分享

生词本分享支持展示最近添加的词:

export function generateCustomWordsText(data: CustomWordsShareData): string {
  let text = `📚 我的单词本\n\n📅 ${data.shareDate}\n\n` +
    `共收录 ${data.totalCount} 个单词\n\n`

  if (data.words.length > 0) {
    const displayWords = data.words.slice(0, 10)
    text += `✨ 最近添加:\n`
    for (const word of displayWords) {
      text += `• ${word.word}: ${word.translation}\n`
    }
  }

  return text
}

这里限制最多展示 10 个词,是很好的隐私和可读性设计。

七、近场分享监听

碰一碰分享:

export function registerKnockShare(callback: (target: harmonyShare.SharableTarget) => void): void {
  harmonyShare.on('knockShare', (target: harmonyShare.SharableTarget) => {
    console.info('Triggered Knock Share')
    callback(target)
  })
}

隔空传送:

export function registerGesturesShare(callback: (target: harmonyShare.SharableTarget) => void): void {
  harmonyShare.on('gesturesShare', (target: harmonyShare.SharableTarget) => {
    console.info('Triggered Gestures Share')
    callback(target)
  })
}

主页面中注册:

registerShareListeners(): void {
  if (this.isPhone) {
    registerKnockShare((target: harmonyShare.SharableTarget) => {
      handleShareFromKnock(target, 'learning_record')
    })
    registerGesturesShare((target: harmonyShare.SharableTarget) => {
      handleShareFromKnock(target, 'learning_record')
    })
  }
}

八、发起分享

核心分享逻辑:

export async function handleShareFromKnock(
  target: harmonyShare.SharableTarget,
  type: ShareContentType = 'learning_record'
): Promise<boolean> {
  const shareText = generateShareText(type)

  const shareData: systemShare.SharedData = new systemShare.SharedData({
    utd: utd.UniformDataType.TEXT,
    content: shareText
  })

  target.share(shareData)
  return true
}

这里使用文本类型,是因为学习报告最容易在不同 App 间流转。

九、个人中心入口

个人中心中有分享入口:

SymbolGlyph($r('sys.symbol.share'))
  .fontSize(this.isTabletDevice ? 22 : 20)
  .fontColor([$r('app.color.primary_color')])
  .onClick(() => {
    router.pushUrl({ url: 'pages/ShareCenter' })
  })

并提示支持近场分享:

Text('支持隔空传送和碰一碰分享学习记录')
  .fontSize(this.isTabletDevice ? 13 : 11)
  .fontColor($r('app.color.primary_color'))

这能让用户知道分享能力的存在。

十、分享内容的隐私边界

学习报告不应该包含:

  • 用户邮箱;
  • 真实姓名;
  • 学校;
  • 具体错题;
  • 完整学习日志;
  • 未经确认的生词全文。

当前分享内容只包含统计数据和少量生词,非常适合公开传播。

十一、后续扩展方向

可以继续扩展:

  • 生成学习海报;
  • 分享成就卡片图片;
  • 分享每日一句;
  • 分享复习计划;
  • 支持班级学习榜;
  • 分享 AppLink 回到具体页面。

但每次扩展都要控制隐私边界。

十二、小结

本文结合「英语视界 YingYu」项目,拆解了分享中心和近场学习报告设计:

  • 使用结构化数据生成学习报告;
  • 支持学习记录、成就、生词本三类分享;
  • 文案强调成就感和鼓励感;
  • 通过 ShareKit 支持碰一碰和隔空传送;
  • 分享内容控制在统计和摘要层面,避免隐私泄露;
  • 个人中心提供可感知入口。

分享功能的关键不是“能发出去”,而是让用户愿意分享,并且分享得安全、体面、有成就感。✨

img

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐