Files
frontend-miniapp/docs/miniapp_integration.md
lyf 8fed715235
Some checks failed
CI / verify (push) Has been cancelled
chore: sync latest project updates
2026-07-03 14:42:38 +08:00

10 KiB
Raw Permalink Blame History

小程序导览接口对接说明

统一维护约定:本文档是小程序对接的固定主文档。后续新增小程序 API、展示、播放、讲解词、异常处理和联调说明时统一修订本文档不再按单个功能新建小程序对接文档。

0. 快速接入

小程序导览页使用 3 个接口:

场景 接口 用途
进入讲解页 stop-info 获取标题、简介、图片、绑定展品、当前语言音频/正文状态
点击播放 play-info 获取唯一可播放 playUrl
展开正文 text-info 按需获取讲解词全文

推荐顺序:

  1. 页面进入先调 stop-info
  2. 根据 stop-info.audioStatus 决定播放按钮是否可点。
  3. 用户点击播放时再调 play-info
  4. 用户展开正文时再调 text-info

1. 通用参数

三个接口都使用同一组参数:

参数 是否必填 取值 说明
targetType ITEM / STOP ITEM 表示展品入口,STOP 表示讲解点入口
targetId number 必须和 targetType 匹配
lang zh-CN / en-US 不传默认 zh-CN

调用示例:

GET /app-api/gis/guide/stop/info?targetType=ITEM&targetId=1001&lang=zh-CN
GET /app-api/gis/guide/audio/play-info?targetType=ITEM&targetId=1001&lang=zh-CN
GET /app-api/gis/guide/audio/text-info?targetType=ITEM&targetId=1001&lang=zh-CN

注意:

  • targetType=ITEM 时,targetId 传展品 ID。
  • targetType=STOP 时,targetId 传讲解点 ID。
  • 小程序建议始终显式传 lang,语言切换后所有请求使用新的 lang
  • 不要传 standardextendedbusinessId、MinIO 路径或四通道音频 URL。

2. stop-info讲解页展示信息

GET /app-api/gis/guide/stop/info?targetType=ITEM&targetId=1001&lang=zh-CN

成功响应:

{
  "code": 0,
  "data": {
    "available": true,
    "targetType": "ITEM",
    "targetId": 1001,
    "resolvedStopId": 2001,
    "lang": "zh-CN",
    "title": "青铜神树",
    "description": "本讲解点介绍三星堆出土的青铜神树……",
    "coverImageUrl": "https://cdn.example.com/cover.jpg",
    "galleryUrls": "[\"https://cdn.example.com/a.jpg\",\"https://cdn.example.com/b.jpg\"]",
    "imageStatus": "READY",
    "imageSource": "STOP",
    "linkedExhibits": [
      {
        "id": 1001,
        "name": "青铜神树",
        "nameEn": "Bronze Sacred Tree",
        "exhibitCode": "EX-001",
        "coverImageUrl": "https://cdn.example.com/exhibit-cover.jpg"
      }
    ],
    "playTargetType": "STOP",
    "playTargetId": 2001,
    "hasAudio": true,
    "hasText": true,
    "supportedLanguages": ["zh-CN", "en-US"],
    "audioStatus": "READY",
    "reason": null
  }
}

不可用响应仍返回 code=0

{
  "code": 0,
  "data": {
    "available": false,
    "targetType": "ITEM",
    "targetId": 9999,
    "lang": "zh-CN",
    "imageStatus": "MISSING",
    "imageSource": "NONE",
    "linkedExhibits": [],
    "hasAudio": false,
    "hasText": false,
    "supportedLanguages": [],
    "audioStatus": "MISSING",
    "reason": "NO_GUIDE_STOP"
  }
}

字段说明:

字段 说明
available 是否有可展示的讲解点
resolvedStopId 最终解析到的讲解点 ID
coverImageUrl 讲解点封面图
galleryUrls 讲解点图集JSON 字符串数组,客户端需安全解析
imageStatus READY / MISSING
linkedExhibits 当前讲解点绑定的展品列表
playTargetType / playTargetId 调用 play-infotext-info 时推荐使用的目标
hasAudio 是否存在任一语言音频
supportedLanguages 有音频的语言列表
audioStatus 当前请求语言是否可播放:READY / MISSING
hasText 当前语言是否有讲解词正文
reason 不可用原因

图片规则:

  • imageStatus=READY:使用 coverImageUrlgalleryUrls 渲染讲解点图片。
  • imageStatus=MISSING:展示占位图或隐藏图片区域。
  • 不要用 linkedExhibits[*].coverImageUrl 兜底讲解点主图。

音频按钮规则:

  • 播放按钮以 audioStatus 为准。
  • hasAudio=true 只表示存在任一语言音频,不代表当前语言可播放。
  • 如果 audioStatus=MISSING,当前语言播放按钮置灰。

3. play-info音频播放

GET /app-api/gis/guide/audio/play-info?targetType=STOP&targetId=2001&lang=zh-CN

可播放响应:

{
  "code": 0,
  "data": {
    "playable": true,
    "targetType": "STOP",
    "targetId": 2001,
    "lang": "zh-CN",
    "narrationTier": "STANDARD",
    "audioId": 8912,
    "title": "青铜神树",
    "duration": 120,
    "format": "mp3",
    "playUrl": "https://cdn.museum.com/tts-audio/xxx.mp3",
    "expiresAt": null,
    "subtitleUrl": null,
    "hasText": true,
    "fallback": false,
    "fallbackReason": null,
    "reason": null
  }
}

不可播放响应仍返回 code=0

{
  "code": 0,
  "data": {
    "playable": false,
    "targetType": "STOP",
    "targetId": 2001,
    "lang": "en-US",
    "narrationTier": "STANDARD",
    "hasText": false,
    "fallback": false,
    "reason": "NO_PUBLISHED_AUDIO"
  }
}

字段说明:

字段 说明
playable 是否可播放
playUrl 可直接赋值给小程序音频组件的地址
expiresAt 播放地址过期时间;为空表示当前地址无短期过期限制
duration 音频时长,单位秒
format 音频格式
hasText 是否有同语言讲解词正文
reason 不可播放原因

播放失败处理:

  • playable=false:不启动播放器,按 reason 展示提示。
  • playUrl 播放失败、403、404 或疑似过期:重新请求一次 play-info
  • 请求英文没有音频时,不要自动播放中文音频。

4. text-info讲解词正文

GET /app-api/gis/guide/audio/text-info?targetType=STOP&targetId=2001&lang=zh-CN

可用响应:

{
  "code": 0,
  "data": {
    "available": true,
    "targetType": "STOP",
    "targetId": 2001,
    "lang": "zh-CN",
    "narrationTier": "STANDARD",
    "title": "青铜神树",
    "text": "青铜神树是三星堆遗址出土的重要青铜器...",
    "textLength": 1200,
    "textHash": "0b32a4..."
  }
}

不可用响应仍返回 code=0

{
  "code": 0,
  "data": {
    "available": false,
    "targetType": "STOP",
    "targetId": 2001,
    "lang": "en-US",
    "narrationTier": "STANDARD",
    "reason": "NO_TEXT"
  }
}

字段说明:

字段 说明
available 是否有正文
text 讲解词正文
textLength 正文字数
textHash 正文版本标识,可用于本地缓存判断
reason 不可用原因

正文建议按需加载,不需要在页面进入时强制请求。

5. 页面推荐流程

async function enterGuidePage(targetType: "ITEM" | "STOP", targetId: number) {
  const lang = getGlobalLanguage() || "zh-CN"
  const stopInfo = await api.getGuideStopInfo({ targetType, targetId, lang })

  if (!stopInfo.available) {
    showStopUnavailable(stopInfo.reason)
    return
  }

  renderStopPage({
    title: stopInfo.title,
    description: stopInfo.description,
    cover: stopInfo.coverImageUrl,
    gallery: parseJsonArraySafely(stopInfo.galleryUrls),
    imageStatus: stopInfo.imageStatus,
    linkedExhibits: stopInfo.linkedExhibits
  })

  setPlayButtonEnabled(stopInfo.audioStatus === "READY")

  bindPlayButton(async () => {
    if (stopInfo.audioStatus !== "READY") {
      showToast("当前语言暂无可播放音频")
      return
    }

    const playInfo = await api.getAudioPlayInfo({
      targetType: stopInfo.playTargetType,
      targetId: stopInfo.playTargetId,
      lang
    })

    if (!playInfo.playable || !playInfo.playUrl) {
      showToast(reasonToText(playInfo.reason))
      return
    }

    audioContext.src = playInfo.playUrl
    audioContext.title = playInfo.title || ""
    audioContext.play()
  })

  bindExpandText(async () => {
    if (!stopInfo.hasText) return

    const textInfo = await api.getAudioTextInfo({
      targetType: stopInfo.playTargetType,
      targetId: stopInfo.playTargetId,
      lang
    })

    if (textInfo.available) {
      renderNarrationText(textInfo.text)
    }
  })
}

6. reason 处理建议

reason 建议提示
NO_GUIDE_STOP 该展品暂未配置讲解
NO_GUIDE_CONTENT 该讲解点暂无讲解内容
NO_PUBLISHED_AUDIO 当前语言暂无语音讲解
NO_TEXT 当前语言暂无讲解词
UNSUPPORTED_LANGUAGE 暂不支持该语言
UNSUPPORTED_TARGET_TYPE 暂不支持该目标类型
TARGET_NOT_FOUND 内容不存在或已下架

小程序可根据页面语气调整文案,但不要把以上业务空态当成系统异常弹窗。

7. 小程序本地缓存建议

播放信息:

  • keytargetType + targetId + lang
  • 语言切换后清理旧语言缓存。
  • 播放失败、403、404 或 URL 过期时,重新请求一次 play-info

讲解词正文:

  • keytargetType + targetId + lang
  • valuetext + textHash
  • 再次请求后如果 textHash 变化,替换本地正文。
  • 不建议长期永久缓存正文。

8. 联调检查清单

  • 不传 lang:三个接口默认按 zh-CN 返回。
  • 进入讲解页:先调 stop-info,不要用 play-info 承担图片、简介、绑定展品展示。
  • 图片存在:imageStatus=READY,使用讲解点图片渲染。
  • 图片缺失:imageStatus=MISSING,展示占位或隐藏图片区。
  • 当前语言可播放:audioStatus=READY,播放按钮可点。
  • 只有其他语言音频:hasAudio=trueaudioStatus=MISSING,当前语言播放按钮不可点。
  • 点击播放:play-info.playable=true 时设置 audio.src=playUrl
  • 英文缺音频:返回 NO_PUBLISHED_AUDIO,不自动播放中文。
  • 展开正文:text-info.available=true 时渲染正文。
  • 英文缺正文:返回 NO_TEXT,不影响音频播放。
  • 展品未绑定讲解点:返回 NO_GUIDE_STOP
  • 播放地址失效:重新请求一次 play-info