dd11cfae73
- 后端:新增 t_event_favorite 表(UNIQUE KEY + MyBatis-Plus Entity) - 后端:LifeEventController 新增 /favorite/toggle、/favorite/page、/favorite/check 三个真实端点 - 后端:EventFavoriteService 完整 CRUD,含 toggle/分页/批量查询/状态检查 - 后端:删除旧的 favorite-placeholder mock 端点 - 前端:life-event/detail.vue 从 localStorage 假收藏切换为真实 API + localStorage 缓存防闪烁 - 前端:ScriptLibraryView.vue 从 localFavorites 切换为 checkFavoriteScript 真实 API - 前端:stores/app.js 新增 toggleEventFavorite / checkEventFavorite 方法 - 修复:审核发现的 UNIQUE 约束缺失、未使用 watch 导入、Controller 参数注解遗漏、Controller 委托 Service 构造 Response Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
181 lines
4.2 KiB
JavaScript
181 lines
4.2 KiB
JavaScript
/**
|
|
* 生命事件服务
|
|
* 处理生命事件的增删改查
|
|
*/
|
|
|
|
import { get, post, put, del } from './request.js'
|
|
import { streamAiScene } from './aiRuntime.js'
|
|
|
|
export const getEventList = async () => {
|
|
const response = await get('/lifeEvent/list')
|
|
return response
|
|
}
|
|
|
|
export const getEventPage = async ({ pageNum = 1, pageSize = 10 }) => {
|
|
const response = await get('/lifeEvent/page', { pageNum, pageSize })
|
|
return response
|
|
}
|
|
|
|
export const getEventById = async (id) => {
|
|
const response = await get('/lifeEvent/detail', { id })
|
|
return response
|
|
}
|
|
|
|
export const createEvent = async (eventData) => {
|
|
const requestData = transformToBackendFormat(eventData)
|
|
const response = await post('/lifeEvent/create', requestData)
|
|
return response
|
|
}
|
|
|
|
export const updateEvent = async (eventData) => {
|
|
const requestData = transformToBackendFormat(eventData)
|
|
const response = await put('/lifeEvent/update', requestData)
|
|
return response
|
|
}
|
|
|
|
export const deleteEvent = async (id) => {
|
|
const response = await del('/lifeEvent/delete', { id })
|
|
return response
|
|
}
|
|
|
|
export const assistEventWriting = async (eventData = {}, callbacks = {}) => {
|
|
const result = await streamAiScene({
|
|
sceneCode: 'life_healing',
|
|
inputs: {
|
|
mode: 'life_event_assist',
|
|
prompt: `请帮我优化这段人生事件记录,保留真实细节,让表达更清晰温柔。\n标题:${eventData.title || ''}\n时间:${eventData.time || eventData.eventDateText || ''}\n内容:${eventData.content || ''}`,
|
|
...eventData
|
|
},
|
|
...callbacks
|
|
})
|
|
return {
|
|
data: {
|
|
content: result.output,
|
|
tags: eventData.tags || []
|
|
}
|
|
}
|
|
}
|
|
|
|
export const chatAboutEvent = async (eventData = {}) => {
|
|
return post('/lifeEvent/chat-placeholder', eventData)
|
|
}
|
|
|
|
export const shareEvent = async (eventData = {}) => {
|
|
return post('/lifeEvent/share-placeholder', eventData)
|
|
}
|
|
|
|
/**
|
|
* 切换人生事件收藏状态(收藏/取消收藏)
|
|
* @param {string} eventId 事件ID
|
|
* @returns {Promise<{success: boolean, isFavorited: boolean}>}
|
|
*/
|
|
export const toggleFavoriteEvent = async (eventId) => {
|
|
const res = await post('/lifeEvent/favorite/toggle', { eventId })
|
|
return {
|
|
success: true,
|
|
isFavorited: res.data?.isFavorited ?? false,
|
|
favoriteTime: res.data?.favoriteTime ?? null
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 检查人生事件是否已收藏
|
|
* @param {string} eventId 事件ID
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
export const checkFavoriteEvent = async (eventId) => {
|
|
const res = await get('/lifeEvent/favorite/check', { eventId })
|
|
return res.data?.isFavorited ?? false
|
|
}
|
|
|
|
const transformToBackendFormat = (frontendData) => {
|
|
const {
|
|
id,
|
|
title,
|
|
time,
|
|
timeMode = 'date',
|
|
eventDateText,
|
|
endTime,
|
|
content,
|
|
aiFeedback,
|
|
eventType = 'daily_log',
|
|
emotionType,
|
|
emotionScore,
|
|
tags
|
|
} = frontendData
|
|
|
|
return {
|
|
id,
|
|
title,
|
|
eventDate: time,
|
|
timeMode,
|
|
eventDateText: eventDateText || time,
|
|
eventEndDate: timeMode === 'range' ? endTime : null,
|
|
content,
|
|
aiReply: aiFeedback,
|
|
eventType,
|
|
emotionType,
|
|
emotionScore,
|
|
tags
|
|
}
|
|
}
|
|
|
|
export const transformToFrontendFormat = (backendData) => {
|
|
if (!backendData) return null
|
|
|
|
const {
|
|
id,
|
|
userId,
|
|
title,
|
|
eventDate,
|
|
timeMode,
|
|
eventDateText,
|
|
eventEndDate,
|
|
content,
|
|
aiReply,
|
|
eventType,
|
|
emotionType,
|
|
emotionScore,
|
|
tags,
|
|
createTime
|
|
} = backendData
|
|
|
|
return {
|
|
id,
|
|
userId,
|
|
title: title || '',
|
|
time: eventDate ? eventDate.split('T')[0] : '',
|
|
timeMode: timeMode || 'date',
|
|
eventDateText: eventDateText || (eventDate ? eventDate.split('T')[0] : ''),
|
|
endTime: eventEndDate ? eventEndDate.split('T')[0] : '',
|
|
content: content || '',
|
|
aiFeedback: aiReply || '',
|
|
eventType: eventType || 'daily_log',
|
|
emotionType,
|
|
emotionScore,
|
|
tags: tags || [],
|
|
createTime
|
|
}
|
|
}
|
|
|
|
export const transformListToFrontend = (backendList) => {
|
|
if (!Array.isArray(backendList)) return []
|
|
return backendList.map(transformToFrontendFormat)
|
|
}
|
|
|
|
export default {
|
|
getEventList,
|
|
getEventPage,
|
|
getEventById,
|
|
createEvent,
|
|
updateEvent,
|
|
deleteEvent,
|
|
assistEventWriting,
|
|
chatAboutEvent,
|
|
shareEvent,
|
|
toggleFavoriteEvent,
|
|
checkFavoriteEvent,
|
|
transformToFrontendFormat,
|
|
transformListToFrontend
|
|
}
|