123 lines
3.2 KiB
Markdown
123 lines
3.2 KiB
Markdown
图片 URL 长相
|
|
真实图片 URL 大概是这种公开 Supabase Storage 地址:
|
|
https://lehwkihwnlqkavhcspel.supabase.co/storage/v1/object/public/elio-schedules/schedules/42/a1b2c3d4.jpg
|
|
前端不用拼 URL,也不用鉴权,后端会直接返回完整 URL。前端只读:
|
|
data.image?.url
|
|
消息接口
|
|
POST https://proapi.banlv-ai.com/api/chat/send
|
|
响应 data 固定字段:
|
|
{
|
|
"reply": "这是我昨天傍晚的照片,那会儿在外面走了走。",
|
|
"audioUrl": "",
|
|
"messageId": "msg_123",
|
|
"timestamp": 1782271808947,
|
|
"isGuest": false,
|
|
"image": {
|
|
"type": "elio_schedule",
|
|
"url": "https://lehwkihwnlqkavhcspel.supabase.co/storage/v1/object/public/elio-schedules/schedules/42/a1b2c3d4.jpg"
|
|
},
|
|
"lockDetail": {
|
|
"locked": false,
|
|
"showContent": true,
|
|
"showUpgrade": false,
|
|
"reason": null,
|
|
"hint": null,
|
|
"detail": null
|
|
}
|
|
}
|
|
前端用法:
|
|
const d = res.data
|
|
|
|
if (d.lockDetail?.showContent !== false && d.reply) {
|
|
renderText(d.reply)
|
|
}
|
|
|
|
if (d.image?.url) {
|
|
renderImage(d.image.url)
|
|
}
|
|
|
|
if (d.audioUrl) {
|
|
renderAudio(d.audioUrl)
|
|
}
|
|
|
|
if (d.lockDetail?.showUpgrade) {
|
|
showVipPaywall(d.lockDetail.hint)
|
|
}
|
|
image.type 目前主要是 elio_schedule,无图时:
|
|
"image": { "type": null, "url": null }
|
|
被限额/需要充值时:
|
|
{
|
|
"reply": "",
|
|
"image": { "type": null, "url": null },
|
|
"lockDetail": {
|
|
"locked": true,
|
|
"showContent": false,
|
|
"showUpgrade": true,
|
|
"reason": "daily_limit",
|
|
"hint": "免费消息额度已用完,开通会员后可以继续聊天。",
|
|
"detail": {
|
|
"type": "daily_msg_limit",
|
|
"usedToday": 3,
|
|
"limit": 3
|
|
}
|
|
}
|
|
}
|
|
历史接口
|
|
GET https://proapi.banlv-ai.com/api/chat/history?limit=50&offset=0
|
|
响应结构:
|
|
{
|
|
"messages": [
|
|
{
|
|
"role": "user",
|
|
"type": "text",
|
|
"content": "你最近在干嘛",
|
|
"id": "msg_1",
|
|
"created_at": "2026-06-24T10:00:00Z",
|
|
"audioUrl": null,
|
|
"image": { "type": null, "url": null },
|
|
"lockDetail": {
|
|
"locked": false,
|
|
"showContent": true,
|
|
"showUpgrade": false,
|
|
"reason": null,
|
|
"hint": null,
|
|
"detail": null
|
|
}
|
|
},
|
|
{
|
|
"role": "assistant",
|
|
"type": "text",
|
|
"content": "",
|
|
"id": "msg_2",
|
|
"created_at": "2026-06-24T10:00:03Z",
|
|
"audioUrl": null,
|
|
"image": { "type": null, "url": null },
|
|
"lockDetail": {
|
|
"locked": true,
|
|
"showContent": false,
|
|
"showUpgrade": true,
|
|
"reason": "private_message",
|
|
"hint": "他好像想说什么悄悄话,解锁会员才能看到…",
|
|
"detail": { "messageId": "msg_2" }
|
|
}
|
|
}
|
|
],
|
|
"total": 200,
|
|
"limit": 50,
|
|
"offset": 0,
|
|
"isVip": false
|
|
}
|
|
历史前端用法:
|
|
for (const m of data.messages) {
|
|
if (m.lockDetail?.showContent === false) {
|
|
renderLockedCard(m.lockDetail.hint)
|
|
if (m.lockDetail?.showUpgrade) showVipEntry()
|
|
continue
|
|
}
|
|
|
|
renderMessage(m.role, m.content)
|
|
|
|
if (m.image?.url) renderImage(m.image.url)
|
|
if (m.audioUrl) renderAudio(m.audioUrl)
|
|
}
|
|
前端不要再读这些旧字段:mode、relationshipStage、currentMood、intimacyChange、newIntimacy、voiceUrl、imageUrl、imageType、privateLocked、privateHint。统一是 audioUrl、image.url、lockDetail。 |