fix: 移除损坏的 Claude gitlink 并同步业务与文档更新

- 从索引移除误记录的 .claude/worktrees gitlink(旧绝对路径会导致 git 命令失败)
- 新增根目录 .gitignore 忽略 .claude/worktrees 与 .DS_Store
- 后端:Coze/知识库、ResultAdvice、应用配置
- 前端 uniapp:AI 营养、食物百科等页面与 API
- 更新 README、测试文档与 shop-msh.sql

Made-with: Cursor
This commit is contained in:
panchengyong
2026-03-30 12:46:24 +08:00
parent 3329a2b296
commit 3023115bb0
19 changed files with 671 additions and 166 deletions

View File

@@ -353,6 +353,114 @@ function cozeChat(data) {
})
}
/**
* Coze - 流式对话 (Chat Stream via SSE + enableChunked)
* 使用微信小程序 enableChunked 能力消费 SSE 事件流
* @param {object} data 请求参数(与 cozeChat 一致)
* @returns {object} 控制器 { onMessage, onError, onComplete, abort, getTask }
*/
function cozeChatStream(data) {
let _onMessage = () => {}
let _onError = () => {}
let _onComplete = () => {}
let _buffer = ''
let _task = null
let _gotChunks = false
const controller = {
onMessage(fn) { _onMessage = fn; return controller },
onError(fn) { _onError = fn; return controller },
onComplete(fn) { _onComplete = fn; return controller },
abort() { if (_task) _task.abort() },
getTask() { return _task }
}
const parseSseLines = (text) => {
_buffer += text
const lines = _buffer.split('\n')
_buffer = lines.pop() || ''
for (const line of lines) {
const trimmed = line.trim()
if (!trimmed || trimmed.startsWith(':')) continue
if (trimmed.startsWith('data:')) {
const jsonStr = trimmed.slice(5).trim()
if (!jsonStr) continue
try {
const evt = JSON.parse(jsonStr)
_onMessage(evt)
} catch (e) {
// skip malformed JSON fragments
}
}
}
}
const parseSseResponseBody = (body) => {
if (!body || typeof body !== 'string') return
const lines = body.split('\n')
for (const line of lines) {
const trimmed = line.trim()
if (!trimmed || trimmed.startsWith(':')) continue
if (trimmed.startsWith('data:')) {
const jsonStr = trimmed.slice(5).trim()
if (!jsonStr) continue
try {
const evt = JSON.parse(jsonStr)
_onMessage(evt)
} catch (e) {
// skip malformed JSON fragments
}
}
}
}
const token = uni.getStorageSync('LOGIN_STATUS_TOKEN') || ''
_task = uni.request({
url: `${API_BASE_URL}/api/front/coze/chat/stream`,
method: 'POST',
data: data,
header: {
'Content-Type': 'application/json',
...(token ? { 'Authori-zation': token } : {})
},
enableChunked: true,
responseType: 'text',
success: (res) => {
if (_buffer.trim()) {
parseSseLines('\n')
}
if (!_gotChunks && res && res.data) {
const body = typeof res.data === 'string' ? res.data : JSON.stringify(res.data)
parseSseResponseBody(body)
}
_onComplete()
},
fail: (err) => {
_onError(err)
}
})
if (_task && _task.onChunkReceived) {
_task.onChunkReceived((res) => {
_gotChunks = true
try {
const bytes = new Uint8Array(res.data)
let text = ''
for (let i = 0; i < bytes.length; i++) {
text += String.fromCharCode(bytes[i])
}
text = decodeURIComponent(escape(text))
parseSseLines(text)
} catch (e) {
// chunk decode error, skip
}
})
}
return controller
}
/**
* Coze - 检索对话详情 (Retrieve Chat)
* @param {object} params 请求参数
@@ -471,6 +579,7 @@ export default {
kieaiGeminiChat,
// Coze API
cozeChat,
cozeChatStream,
cozeRetrieveChat,
cozeMessageList,
cozeWorkflowRun,