10 KiB
10 KiB
小程序导览接口对接说明
统一维护约定:本文档是小程序对接的固定主文档。后续新增小程序 API、展示、播放、讲解词、异常处理和联调说明时,统一修订本文档,不再按单个功能新建小程序对接文档。
0. 快速接入
小程序导览页使用 3 个接口:
| 场景 | 接口 | 用途 |
|---|---|---|
| 进入讲解页 | stop-info |
获取标题、简介、图片、绑定展品、当前语言音频/正文状态 |
| 点击播放 | play-info |
获取唯一可播放 playUrl |
| 展开正文 | text-info |
按需获取讲解词全文 |
推荐顺序:
- 页面进入先调
stop-info。 - 根据
stop-info.audioStatus决定播放按钮是否可点。 - 用户点击播放时再调
play-info。 - 用户展开正文时再调
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。 - 不要传
standard、extended、businessId、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-info、text-info 时推荐使用的目标 |
hasAudio |
是否存在任一语言音频 |
supportedLanguages |
有音频的语言列表 |
audioStatus |
当前请求语言是否可播放:READY / MISSING |
hasText |
当前语言是否有讲解词正文 |
reason |
不可用原因 |
图片规则:
imageStatus=READY:使用coverImageUrl和galleryUrls渲染讲解点图片。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. 小程序本地缓存建议
播放信息:
- key:
targetType + targetId + lang - 语言切换后清理旧语言缓存。
- 播放失败、403、404 或 URL 过期时,重新请求一次
play-info。
讲解词正文:
- key:
targetType + targetId + lang - value:
text + textHash - 再次请求后如果
textHash变化,替换本地正文。 - 不建议长期永久缓存正文。
8. 联调检查清单
- 不传
lang:三个接口默认按zh-CN返回。 - 进入讲解页:先调
stop-info,不要用play-info承担图片、简介、绑定展品展示。 - 图片存在:
imageStatus=READY,使用讲解点图片渲染。 - 图片缺失:
imageStatus=MISSING,展示占位或隐藏图片区。 - 当前语言可播放:
audioStatus=READY,播放按钮可点。 - 只有其他语言音频:
hasAudio=true且audioStatus=MISSING,当前语言播放按钮不可点。 - 点击播放:
play-info.playable=true时设置audio.src=playUrl。 - 英文缺音频:返回
NO_PUBLISHED_AUDIO,不自动播放中文。 - 展开正文:
text-info.available=true时渲染正文。 - 英文缺正文:返回
NO_TEXT,不影响音频播放。 - 展品未绑定讲解点:返回
NO_GUIDE_STOP。 - 播放地址失效:重新请求一次
play-info。