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,20 +188,45 @@ const getItemStyle = (item) => { ...@@ -183,20 +188,45 @@ 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
190 - setTimeout(() => { 195 + try {
191 - const totalToAdd = item.points; 196 + // 调用收集积分接口
192 - const newTotal = props.totalPoints + totalToAdd; 197 + const { code, data } = await collectPointAPI({
193 - animateNumber(animatedTotalPoints.value, newTotal); 198 + family_id: props.familyId,
194 - 199 + point_id: item.id
195 - floatingItems.value = floatingItems.value.filter(i => i.id !== item.id); 200 + });
196 - if (floatingItems.value.length === 0) { 201 +
197 - emit('collection-complete', newTotal); 202 + if (code) {
203 + setTimeout(() => {
204 + // 使用接口返回的最新积分总数
205 + const newTotal = data.new_total_points;
206 + animateNumber(animatedTotalPoints.value, newTotal);
207 +
208 + floatingItems.value = floatingItems.value.filter(i => i.id !== item.id);
209 + if (floatingItems.value.length === 0) {
210 + emit('collection-complete', newTotal);
211 + }
212 + }, 800); // 动画时长
213 + } else {
214 + // 接口调用失败,恢复状态
215 + item.collecting = false;
216 + Taro.showToast({
217 + title: '收取失败,请重试',
218 + icon: 'none'
219 + });
198 } 220 }
199 - }, 800); // 动画时长 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 {
210 - const itemsToCollect = [...floatingItems.value]; 240 + // 调用一键收取接口(point_id为空)
211 - 241 + const { code, data } = await collectPointAPI({
212 - itemsToCollect.forEach((item, index) => { 242 + family_id: props.familyId,
213 - setTimeout(() => { 243 + point_id: '' // 空值表示一键收取
214 - item.collecting = true; 244 + });
215 - }, index * 80); // 依次触发动画 245 +
216 - totalToAdd += item.points; 246 + if (code) {
217 - }); 247 + const itemsToCollect = [...floatingItems.value];
218 - 248 +
219 - const totalAnimationTime = itemsToCollect.length * 80 + 800; 249 + itemsToCollect.forEach((item, index) => {
220 - setTimeout(() => { 250 + setTimeout(() => {
221 - const newTotal = props.totalPoints + totalToAdd; 251 + item.collecting = true;
222 - animateNumber(animatedTotalPoints.value, newTotal); 252 + }, index * 80); // 依次触发动画
223 - 253 + });
224 - floatingItems.value = []; 254 +
255 + const totalAnimationTime = itemsToCollect.length * 80 + 800;
256 + setTimeout(() => {
257 + // 使用接口返回的最新积分总数
258 + const newTotal = data.new_total_points;
259 + animateNumber(animatedTotalPoints.value, newTotal);
260 +
261 + floatingItems.value = [];
262 + isCollecting.value = false;
263 + emit('collection-complete', newTotal);
264 + }, totalAnimationTime);
265 + } else {
266 + // 接口调用失败
267 + isCollecting.value = false;
268 + Taro.showToast({
269 + title: '一键收取失败,请重试',
270 + icon: 'none'
271 + });
272 + }
273 + } catch (error) {
274 + // 异常处理
225 isCollecting.value = false; 275 isCollecting.value = false;
226 - emit('collection-complete', newTotal); 276 + console.error('一键收取积分失败:', error);
227 - }, totalAnimationTime); 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>
......