feat: 小程序脚本首页重构 + 社交数据导入 + TTS 播放优化

- 后端:新增社交数据导入/审批/洞察生成 API(SocialContent/SocialInsight)
- 后端:优化脚本上下文服务,TTS 服务增强
- 小程序:重构脚本首页布局,新增社交导入页面
- 小程序:新增 useTtsPlayer composable,移除旧 ScriptAudioPlayer 组件
- 小程序:新增社交导入服务,优化请求服务
- SQL:新增社交数据导入建表脚本
- 文档:补充设计文档和实施计划

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-20 07:18:02 +08:00
parent 83cc32999b
commit ee5a6aba5d
50 changed files with 5723 additions and 1246 deletions
+4 -2
View File
@@ -94,7 +94,8 @@ const transformToBackendFormat = (frontendData) => {
isSelected,
character,
events,
plotJson
plotJson,
useSocialInsights
} = frontendData
const scriptTitle = title || theme || '我的人生剧本'
@@ -114,7 +115,8 @@ const transformToBackendFormat = (frontendData) => {
plotJson: plotJson || (content ? { fullContent: content } : null),
isSelected,
characterInfo,
lifeEventsSummary
lifeEventsSummary,
useSocialInsights
}
}
+42
View File
@@ -149,10 +149,52 @@ export const del = (url, params = {}) => {
return request({ url: fullUrl, method: 'DELETE' })
}
export const upload = (url, filePath, formData = {}, name = 'file') => {
const token = uni.getStorageSync('access_token')
const fullUrl = `${API_BASE_URL}${url}`
return new Promise((resolve, reject) => {
uni.uploadFile({
url: fullUrl,
filePath,
name,
formData,
header: token ? { Authorization: `Bearer ${token}` } : {},
timeout: 30000,
success: (res) => {
let data = res.data
try {
data = typeof res.data === 'string' ? JSON.parse(res.data) : res.data
} catch (error) {
reject(createRequestError('Upload response parse failed', { path: url, originalError: error }))
return
}
if (res.statusCode >= 200 && res.statusCode < 300 && (data?.code === 200 || data?.code === 0)) {
resolve(data)
return
}
reject(createRequestError(data?.message || 'Upload failed', {
statusCode: res.statusCode,
code: data?.code,
path: url,
response: data
}))
},
fail: (err) => {
reject(createRequestError(err.errMsg || 'Upload failed', {
path: url,
isNetworkError: true,
originalError: err
}))
}
})
})
}
export default {
get,
post,
put,
del,
upload,
logRuntimeEnv
}
+48
View File
@@ -0,0 +1,48 @@
import { get, post, put, del, upload } from './request.js'
export const manualImport = (payload) => post('/social/content/manual', payload)
export const linkImport = (payload) => post('/social/content/link', payload)
export const screenshotImport = ({ platform, filePath }) => {
return upload('/social/content/screenshot', filePath, { platform })
}
export const listContent = () => get('/social/content/list')
export const updateContentApproval = (id, approvedForAi) => {
return put(`/social/content/${id}/approval`, { approvedForAi })
}
export const deleteContent = (id, keepConfirmedInsights = true) => {
return del(`/social/content/${id}`, { keepConfirmedInsights })
}
export const generateInsights = (sourceItemIds = []) => {
return post('/social/insight/generate', { sourceItemIds })
}
export const listInsights = (status = '') => {
return get('/social/insight/list', status ? { status } : {})
}
export const updateInsight = (id, payload) => {
return put(`/social/insight/${id}`, payload)
}
export const deleteInsight = (id) => {
return del(`/social/insight/${id}`)
}
export default {
manualImport,
linkImport,
screenshotImport,
listContent,
updateContentApproval,
deleteContent,
generateInsights,
listInsights,
updateInsight,
deleteInsight
}