From 6109202a26e666b38f9907a45c7d89864d48c635 Mon Sep 17 00:00:00 2001 From: Peanut Date: Sun, 28 Jun 2026 18:23:13 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20request.js=20=E5=AF=BC=E5=87=BA=20API?= =?UTF-8?q?=5FBASE=5FURL=20=E5=92=8C=20getAuthHeader?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mini-program/src/services/epicScript.js | 9 ++- mini-program/src/services/message.js | 13 ++++ mini-program/src/services/request.js | 7 ++ mini-program/src/services/scriptChat.js | 92 +++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 mini-program/src/services/message.js create mode 100644 mini-program/src/services/scriptChat.js diff --git a/mini-program/src/services/epicScript.js b/mini-program/src/services/epicScript.js index c3e9bd3..93c313e 100644 --- a/mini-program/src/services/epicScript.js +++ b/mini-program/src/services/epicScript.js @@ -148,7 +148,9 @@ export const transformToFrontendFormat = (backendData) => { plotJson, isSelected, createTime, - updateTime + updateTime, + conversationId, + currentVersionMessageId } = backendData let content = '' @@ -182,11 +184,12 @@ export const transformToFrontendFormat = (backendData) => { date: createTime ? String(createTime).slice(0, 10) : new Date().toLocaleDateString(), mode: plotJson?.mode || 'custom', prompt: plotJson?.prompt || '', - conversationId: plotJson?.conversationId || '', + conversationId: conversationId || plotJson?.conversationId || '', parentScriptId: plotJson?.parentScriptId || '', revisionIndex: plotJson?.currentRevisionIndex || plotJson?.revisionIndex || 0, revisionOf: plotJson?.revisionOf || '', - wordCount: content ? content.length : 0 + wordCount: content ? content.length : 0, + currentVersionMessageId: currentVersionMessageId || '' } } diff --git a/mini-program/src/services/message.js b/mini-program/src/services/message.js new file mode 100644 index 0000000..02cfe4c --- /dev/null +++ b/mini-program/src/services/message.js @@ -0,0 +1,13 @@ +import { get, post, del } from './request.js' + +export const createMessage = async (payload) => { + return post('/message/create', payload) +} + +export const getMessageById = async (id) => { + return get('/message/detail', { id }) +} + +export const deleteMessage = async (id) => { + return del('/message/delete', { id }) +} diff --git a/mini-program/src/services/request.js b/mini-program/src/services/request.js index 0315a3a..546aa26 100644 --- a/mini-program/src/services/request.js +++ b/mini-program/src/services/request.js @@ -266,6 +266,13 @@ export const upload = (url, filePath, formData = {}, name = 'file') => { }) } +export const getApiBaseUrl = () => API_BASE_URL + +export const getAuthHeader = () => { + const token = uni.getStorageSync('access_token') + return token ? { Authorization: `Bearer ${token}` } : {} +} + export default { get, post, diff --git a/mini-program/src/services/scriptChat.js b/mini-program/src/services/scriptChat.js new file mode 100644 index 0000000..39ee318 --- /dev/null +++ b/mini-program/src/services/scriptChat.js @@ -0,0 +1,92 @@ +import { get, post, put, del } from './request.js' +import { getApiBaseUrl, getAuthHeader } from './request.js' + +export const createScriptWithDialogue = async (payload) => { + return post('/epicScript/createWithDialogue', payload) +} + +export const streamScriptChat = async ({ operationType, conversationId, messageId, userMessageId, content, scriptId, onDelta, onDone, onError }) => { + const requestTask = uni.request({ + url: `${getApiBaseUrl()}/chat/stream`, + method: 'POST', + data: { operationType, conversationId, messageId, userMessageId, content, scriptId }, + header: { + 'Content-Type': 'application/json', + ...getAuthHeader() + }, + enableChunked: true, + timeout: 300000, + success: (res) => { + if (res.statusCode >= 400) { + onError?.(res.data?.message || '流式请求失败') + return + } + if (typeof res.data === 'string' && res.data) { + consumeSseText(res.data, onDelta, onDone, onError) + } + }, + fail: (error) => { + onError?.(error.errMsg || '流式请求失败') + } + }) + + requestTask?.onChunkReceived?.((res) => { + try { + const text = decodeChunk(res.data) + consumeSseText(text, onDelta, onDone, onError) + } catch (error) { + onError?.(error.message || '流式解析失败') + } + }) +} + +export const listMessagesByConversation = async ({ conversationId, includeVersions = false }) => { + return get('/message/listByConversation', { conversationId, includeVersions }) +} + +export const listMessageVersions = async (messageId) => { + return get('/message/versions', { messageId }) +} + +export const switchVersion = async ({ scriptId, messageId }) => { + return put('/epicScript/switchVersion', { scriptId, messageId }) +} + +export const deleteVersion = async (messageId) => { + return del('/message/deleteVersion', { id: messageId }) +} + +function decodeChunk(chunk) { + if (typeof chunk === 'string') return chunk + const decoder = new TextDecoder('utf-8') + return decoder.decode(new Uint8Array(chunk)) +} + +function consumeSseText(text, onDelta, onDone, onError) { + const lines = text.split(/\r?\n/) + let eventName = '' + let dataBuffer = '' + lines.forEach((line) => { + if (line.startsWith('event:')) { + eventName = line.slice(6).trim() + } else if (line.startsWith('data:')) { + dataBuffer += line.slice(5).trim() + } else if (line === '' && dataBuffer) { + try { + if (eventName === 'delta') { + onDelta?.(dataBuffer) + } else if (eventName === 'metadata') { + onDone?.({ type: 'metadata', data: JSON.parse(dataBuffer) }) + } else if (eventName === 'done') { + onDone?.({ type: 'done', data: JSON.parse(dataBuffer) }) + } else if (eventName === 'error') { + onError?.(dataBuffer) + } + } catch (e) { + onError?.(e.message) + } + eventName = '' + dataBuffer = '' + } + }) +}