useCollectOperation.js
3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/**
* 收藏操作 Composable
*
* @description 统一的收藏/取消收藏逻辑,支持乐观更新和错误回滚
* @author Claude Code
* @created 2026-02-05
*/
import { addAPI, delAPI } from '../api/favorite.js'
import Taro from '@tarojs/taro'
import eventBus, { Events } from '@/utils/eventBus'
/**
* 使用收藏操作
*
* @description 提供统一的收藏/取消收藏功能,包含乐观更新和错误处理
* @param {Object} options - 配置选项
* @param {Function} [options.onSuccess] - 成功回调
* @param {Function} [options.onError] - 错误回调
* @returns {Object} 收藏操作方法
*
* @example
* const { toggleCollect } = useCollectOperation()
*
* // 在组件中使用
* const item = ref({ id: 123, collected: false })
*
* await toggleCollect(item, '收藏成功', '已取消收藏')
*/
export function useCollectOperation(options = {}) {
const { onSuccess, onError } = options
/**
* 切换收藏状态
* @description 统一的收藏/取消收藏操作
* @param {Object} item - 资料项(必须包含 collected 和 id/meta_id 字段)
* @param {string} successMsg - 成功提示文案
* @param {string} [errorMsg='操作失败'] - 失败提示文案
* @returns {Promise<boolean>} 操作是否成功
*/
const toggleCollect = async (item, successMsg, errorMsg = '操作失败') => {
try {
// 乐观更新 UI
const newCollectStatus = !item.collected
item.collected = newCollectStatus
// 获取 meta_id(优先使用 meta_id,其次使用 id)
const metaId = item.meta_id || item.id
// 调用 API
const res = newCollectStatus
? await addAPI({ meta_id: metaId }) // 添加收藏
: await delAPI({ meta_id: metaId }) // 取消收藏
if (res.code === 1) {
// API 调用成功,显示提示
Taro.showToast({
title: successMsg || (newCollectStatus ? '已收藏' : '已取消收藏'),
icon: 'success',
duration: 1000
})
// 发送收藏更新事件(通知收藏列表页刷新)
eventBus.emit(Events.FAVORITES_UPDATE, {
metaId,
collected: newCollectStatus,
timestamp: Date.now()
})
// 调用成功回调
onSuccess?.(item, newCollectStatus)
return true
} else {
// API 调用失败,回滚 UI 状态
item.collected = !newCollectStatus
Taro.showToast({
title: res.msg || errorMsg,
icon: 'none',
duration: 2000
})
// 调用错误回调
onError?.(item, res.msg)
return false
}
} catch (err) {
// 发生错误,回滚 UI 状态
item.collected = !item.collected
console.error('[useCollectOperation] 收藏操作失败:', err)
Taro.showToast({
title: '网络错误,请重试',
icon: 'none',
duration: 2000
})
// 调用错误回调
onError?.(item, err.message)
return false
}
}
return {
toggleCollect
}
}