hookehuyr

feat(积分收集): 添加家庭积分收集功能并集成后端API

- 在PointsCollector组件中添加familyId属性用于家庭积分收集
- 新增collectPointAPI接口用于积分收集操作
- 实现单个积分项目收集和一键全部收集功能
- 添加错误处理和用户反馈
1 /* 1 /*
2 * @Date: 2023-12-22 10:29:37 2 * @Date: 2023-12-22 10:29:37
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-09-01 13:53:17 4 + * @LastEditTime: 2025-09-03 18:10:03
5 * @FilePath: /lls_program/src/api/points.js 5 * @FilePath: /lls_program/src/api/points.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -9,6 +9,7 @@ import { fn, fetch } from './fn'; ...@@ -9,6 +9,7 @@ import { fn, fetch } from './fn';
9 9
10 const Api = { 10 const Api = {
11 SYNC_WX_STEP: '/srv/?a=point&t=sync_wx_step', 11 SYNC_WX_STEP: '/srv/?a=point&t=sync_wx_step',
12 + COLLECT_POINT: '/srv/?a=point&t=collect',
12 } 13 }
13 14
14 /** 15 /**
...@@ -16,3 +17,17 @@ const Api = { ...@@ -16,3 +17,17 @@ const Api = {
16 * @returns 17 * @returns
17 */ 18 */
18 export const syncWxStepAPI = (params) => fn(fetch.post(Api.SYNC_WX_STEP, params)); 19 export const syncWxStepAPI = (params) => fn(fetch.post(Api.SYNC_WX_STEP, params));
20 +
21 +/**
22 + * @description: 汇总积分到家庭
23 + * @param {*} params
24 + * @param {string} params.family_id - 家庭ID
25 + * @param {string} params.point_id - 积分ID, 为空时用于一键全积
26 + * @returns {Object} response - 响应对象
27 + * @returns {string} response.code - 响应状态码
28 + * @returns {string} response.msg - 响应消息
29 + * @returns {Object} response.data - 响应数据
30 + * @returns {number} response.data.new_total_points - 最新的家庭积分
31 + */
32 +
33 +export const collectPointAPI = (params) => fn(fetch.post(Api.COLLECT_POINT, params));
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
36 <script setup> 36 <script setup>
37 import { ref, onMounted, defineProps, defineExpose, defineEmits, watch } from 'vue' 37 import { ref, onMounted, defineProps, defineExpose, defineEmits, watch } from 'vue'
38 import Taro, { useDidShow } from '@tarojs/taro' 38 import Taro, { useDidShow } from '@tarojs/taro'
39 +import { collectPointAPI } from '@/api/points'
39 40
40 const emit = defineEmits(['collection-complete']) 41 const emit = defineEmits(['collection-complete'])
41 const props = defineProps({ 42 const props = defineProps({
...@@ -50,6 +51,10 @@ const props = defineProps({ ...@@ -50,6 +51,10 @@ const props = defineProps({
50 totalPoints: { 51 totalPoints: {
51 type: Number, 52 type: Number,
52 default: 0 53 default: 0
54 + },
55 + familyId: {
56 + type: String,
57 + required: true
53 } 58 }
54 }) 59 })
55 60
...@@ -183,13 +188,21 @@ const getItemStyle = (item) => { ...@@ -183,13 +188,21 @@ const getItemStyle = (item) => {
183 /** 188 /**
184 * 收集单个项目 189 * 收集单个项目
185 */ 190 */
186 -const collectItem = (item) => { 191 +const collectItem = async (item) => {
187 if (item.collecting) return; 192 if (item.collecting) return;
188 item.collecting = true; 193 item.collecting = true;
189 194
195 + try {
196 + // 调用收集积分接口
197 + const { code, data } = await collectPointAPI({
198 + family_id: props.familyId,
199 + point_id: item.id
200 + });
201 +
202 + if (code) {
190 setTimeout(() => { 203 setTimeout(() => {
191 - const totalToAdd = item.points; 204 + // 使用接口返回的最新积分总数
192 - const newTotal = props.totalPoints + totalToAdd; 205 + const newTotal = data.new_total_points;
193 animateNumber(animatedTotalPoints.value, newTotal); 206 animateNumber(animatedTotalPoints.value, newTotal);
194 207
195 floatingItems.value = floatingItems.value.filter(i => i.id !== item.id); 208 floatingItems.value = floatingItems.value.filter(i => i.id !== item.id);
...@@ -197,6 +210,23 @@ const collectItem = (item) => { ...@@ -197,6 +210,23 @@ const collectItem = (item) => {
197 emit('collection-complete', newTotal); 210 emit('collection-complete', newTotal);
198 } 211 }
199 }, 800); // 动画时长 212 }, 800); // 动画时长
213 + } else {
214 + // 接口调用失败,恢复状态
215 + item.collecting = false;
216 + Taro.showToast({
217 + title: '收取失败,请重试',
218 + icon: 'none'
219 + });
220 + }
221 + } catch (error) {
222 + // 异常处理,恢复状态
223 + item.collecting = false;
224 + console.error('收集积分失败:', error);
225 + Taro.showToast({
226 + title: '收取失败,请重试',
227 + icon: 'none'
228 + });
229 + }
200 } 230 }
201 231
202 /** 232 /**
...@@ -206,25 +236,49 @@ const collectAll = async () => { ...@@ -206,25 +236,49 @@ const collectAll = async () => {
206 if (isCollecting.value) return; 236 if (isCollecting.value) return;
207 isCollecting.value = true; 237 isCollecting.value = true;
208 238
209 - let totalToAdd = 0; 239 + try {
240 + // 调用一键收取接口(point_id为空)
241 + const { code, data } = await collectPointAPI({
242 + family_id: props.familyId,
243 + point_id: '' // 空值表示一键收取
244 + });
245 +
246 + if (code) {
210 const itemsToCollect = [...floatingItems.value]; 247 const itemsToCollect = [...floatingItems.value];
211 248
212 itemsToCollect.forEach((item, index) => { 249 itemsToCollect.forEach((item, index) => {
213 setTimeout(() => { 250 setTimeout(() => {
214 item.collecting = true; 251 item.collecting = true;
215 }, index * 80); // 依次触发动画 252 }, index * 80); // 依次触发动画
216 - totalToAdd += item.points;
217 }); 253 });
218 254
219 const totalAnimationTime = itemsToCollect.length * 80 + 800; 255 const totalAnimationTime = itemsToCollect.length * 80 + 800;
220 setTimeout(() => { 256 setTimeout(() => {
221 - const newTotal = props.totalPoints + totalToAdd; 257 + // 使用接口返回的最新积分总数
258 + const newTotal = data.new_total_points;
222 animateNumber(animatedTotalPoints.value, newTotal); 259 animateNumber(animatedTotalPoints.value, newTotal);
223 260
224 floatingItems.value = []; 261 floatingItems.value = [];
225 isCollecting.value = false; 262 isCollecting.value = false;
226 emit('collection-complete', newTotal); 263 emit('collection-complete', newTotal);
227 }, totalAnimationTime); 264 }, totalAnimationTime);
265 + } else {
266 + // 接口调用失败
267 + isCollecting.value = false;
268 + Taro.showToast({
269 + title: '一键收取失败,请重试',
270 + icon: 'none'
271 + });
272 + }
273 + } catch (error) {
274 + // 异常处理
275 + isCollecting.value = false;
276 + console.error('一键收取积分失败:', error);
277 + Taro.showToast({
278 + title: '一键收取失败,请重试',
279 + icon: 'none'
280 + });
281 + }
228 } 282 }
229 283
230 /** 284 /**
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
52 height="30vh" 52 height="30vh"
53 :total-points="finalTotalPoints" 53 :total-points="finalTotalPoints"
54 :pending-points="pendingPoints" 54 :pending-points="pendingPoints"
55 + :family-id="family_id"
55 @collection-complete="handleCollectionComplete" 56 @collection-complete="handleCollectionComplete"
56 /> 57 />
57 </template> 58 </template>
......