Files
ai_dianshang/miniprogram/pages/points/index.js
2025-11-17 13:32:54 +08:00

421 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
getUserPoints,
getPointsOverview,
getPointsHistory,
getPointsRules,
getPointsExchangeList,
exchangePoints,
getUserExchangeRecords,
dailyCheckin
} from '../../services/points/index';
const weChatAuthService = require('../../services/auth/wechat');
Page({
data: {
userPoints: 0,
pointsOverview: {
total_points: 0,
available_points: 0,
frozen_points: 0,
total_earned: 0,
total_spent: 0,
this_month_earned: 0,
this_month_spent: 0
},
pointsHistory: [],
pointsRules: [],
exchangeItems: [],
exchangeRecords: [],
currentTab: 0,
showExchangeModal: false,
selectedItem: null,
loading: false,
historyPage: 1,
exchangePage: 1,
recordsPage: 1,
hasMoreHistory: true,
hasMoreExchange: true,
hasMoreRecords: true,
tabList: [
{ text: '积分明细', key: 0 },
{ text: '积分规则', key: 1 },
{ text: '积分兑换', key: 2 }
]
},
onLoad() {
this.init();
},
async init() {
console.log('积分页面初始化');
this.setData({ loading: true });
// 检查登录状态
if (!weChatAuthService.isLoggedIn()) {
console.log('用户未登录,跳转到登录页面');
wx.showToast({
title: '请先登录',
icon: 'none'
});
setTimeout(() => {
wx.navigateTo({
url: '/pages/login/index'
});
}, 1500);
this.setData({ loading: false });
return;
}
try {
// 并行加载基础数据
await Promise.all([
this.loadUserPoints(),
this.loadPointsOverview(),
this.loadPointsHistory(),
this.loadPointsRules(),
this.loadExchangeItems()
]);
} catch (error) {
console.error('积分页面初始化失败:', error);
// 检查是否是认证错误
if (error.message && error.message.includes('未授权')) {
wx.showToast({
title: '登录已过期,请重新登录',
icon: 'none'
});
setTimeout(() => {
wx.navigateTo({
url: '/pages/login/index'
});
}, 1500);
} else {
wx.showToast({
title: '加载失败,请重试',
icon: 'none'
});
}
} finally {
this.setData({ loading: false });
}
},
// 加载用户积分
async loadUserPoints() {
try {
console.log('开始获取用户积分...');
const response = await getUserPoints();
console.log('用户积分API响应:', response);
if (response.code === 200) {
const points = response.data.points || 0;
console.log('设置用户积分:', points);
this.setData({
userPoints: points
});
} else {
console.error('获取用户积分失败 - 业务错误:', response.message);
throw new Error(response.message || '获取积分失败');
}
} catch (error) {
console.error('获取用户积分失败:', error);
throw error; // 重新抛出错误,让上层处理
}
},
// 加载积分概览
async loadPointsOverview() {
try {
console.log('开始获取积分概览...');
const response = await getPointsOverview();
console.log('积分概览API响应:', response);
if (response.code === 200) {
console.log('设置积分概览数据:', response.data);
this.setData({
pointsOverview: response.data
});
} else {
console.error('获取积分概览失败 - 业务错误:', response.message);
throw new Error(response.message || '获取积分概览失败');
}
} catch (error) {
console.error('获取积分概览失败:', error);
throw error; // 重新抛出错误,让上层处理
}
},
// 加载积分历史记录
async loadPointsHistory(page = 1, append = false) {
try {
const response = await getPointsHistory({ page, pageSize: 10 });
if (response.code === 200) {
const newHistory = response.data.list.map(item => ({
...item,
type: item.type === 1 ? 'earn' : 'spend', // 转换类型1=获得(earn), 2=消费(spend)
date: this.formatDate(item.created_at),
time: this.formatTime(item.created_at)
}));
this.setData({
pointsHistory: append ? [...this.data.pointsHistory, ...newHistory] : newHistory,
historyPage: page,
hasMoreHistory: newHistory.length === 10
});
}
} catch (error) {
console.error('获取积分历史记录失败:', error);
}
},
// 加载积分规则
async loadPointsRules() {
try {
const response = await getPointsRules();
if (response.code === 200) {
this.setData({
pointsRules: response.data.map(rule => ({
id: rule.id,
title: rule.title, // 后端返回的字段名是title不是name
description: rule.description
}))
});
}
} catch (error) {
console.error('获取积分规则失败:', error);
}
},
// 加载兑换商品
async loadExchangeItems(page = 1, append = false) {
try {
const response = await getPointsExchangeList({ page, pageSize: 10 });
if (response.code === 200) {
// 后端直接返回数组不是包含list的对象
const dataArray = Array.isArray(response.data) ? response.data : (response.data.list || []);
const newItems = dataArray.map(item => ({
id: item.id,
name: item.name,
description: item.description,
points: item.points, // 后端返回的字段名是points不是points_required
image: item.image,
stock: item.stock
}));
this.setData({
exchangeItems: append ? [...this.data.exchangeItems, ...newItems] : newItems,
exchangePage: page,
hasMoreExchange: newItems.length === 10
});
}
} catch (error) {
console.error('获取兑换商品失败:', error);
}
},
// 加载兑换记录
async loadExchangeRecords(page = 1, append = false) {
try {
const response = await getUserExchangeRecords({ page, pageSize: 10 });
if (response.code === 200) {
const newRecords = response.data.list.map(record => ({
...record,
date: this.formatDate(record.created_at)
}));
this.setData({
exchangeRecords: append ? [...this.data.exchangeRecords, ...newRecords] : newRecords,
recordsPage: page,
hasMoreRecords: newRecords.length === 10
});
}
} catch (error) {
console.error('获取兑换记录失败:', error);
}
},
// 格式化日期
formatDate(dateString) {
const date = new Date(dateString);
return date.toISOString().split('T')[0];
},
// 格式化时间
formatTime(dateString) {
const date = new Date(dateString);
return date.toTimeString().split(' ')[0].substring(0, 5); // 返回 HH:MM 格式
},
onTabChange(e) {
const { value } = e.detail;
this.setData({
currentTab: value
});
// 切换到兑换记录标签时加载数据
if (value === 3 && this.data.exchangeRecords.length === 0) {
this.loadExchangeRecords();
}
},
onExchangeItem(e) {
const { item } = e.currentTarget.dataset;
const { userPoints } = this.data;
// 检查积分是否足够
if (userPoints < item.points) {
wx.showToast({
title: '积分不足',
icon: 'none'
});
return;
}
// 检查库存
if (item.stock <= 0) {
wx.showToast({
title: '商品已售罄',
icon: 'none'
});
return;
}
// 显示兑换确认弹窗
wx.showModal({
title: '确认兑换',
content: `确定要用${item.points}积分兑换${item.name}吗?\n\n兑换后积分将立即扣除,请确认操作。`,
confirmText: '确认兑换',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
this.doExchangePoints(item);
}
}
});
},
async doExchangePoints(item) {
try {
wx.showLoading({
title: '兑换中...',
mask: true
});
const response = await exchangePoints(item.id, 1);
if (response.code === 200) {
wx.hideLoading();
// 显示成功提示
wx.showToast({
title: '兑换成功!',
icon: 'success',
duration: 2000
});
// 延迟刷新数据,让用户看到成功提示
setTimeout(async () => {
try {
// 刷新用户积分和相关数据
await Promise.all([
this.loadUserPoints(),
this.loadPointsOverview(),
this.loadPointsHistory(1, false),
this.loadExchangeItems(1, false)
]);
} catch (refreshError) {
console.error('刷新数据失败:', refreshError);
}
}, 1000);
} else {
throw new Error(response.message || '兑换失败');
}
} catch (error) {
console.error('积分兑换失败:', error);
wx.hideLoading();
// 根据错误类型显示不同的提示
let errorMessage = '兑换失败,请重试';
if (error.message.includes('积分不足')) {
errorMessage = '积分不足,无法兑换';
} else if (error.message.includes('库存')) {
errorMessage = '商品库存不足';
} else if (error.message.includes('网络')) {
errorMessage = '网络异常,请检查网络连接';
}
wx.showToast({
title: errorMessage,
icon: 'none',
duration: 3000
});
}
},
// 下拉刷新
async onPullDownRefresh() {
try {
await this.init();
wx.showToast({
title: '刷新成功',
icon: 'success'
});
} catch (error) {
wx.showToast({
title: '刷新失败',
icon: 'none'
});
} finally {
wx.stopPullDownRefresh();
}
},
// 上拉加载更多
onReachBottom() {
const { currentTab } = this.data;
if (currentTab === 0 && this.data.hasMoreHistory) {
// 加载更多积分历史
this.loadPointsHistory(this.data.historyPage + 1, true);
} else if (currentTab === 2 && this.data.hasMoreExchange) {
// 加载更多兑换商品
this.loadExchangeItems(this.data.exchangePage + 1, true);
} else if (currentTab === 3 && this.data.hasMoreRecords) {
// 加载更多兑换记录
this.loadExchangeRecords(this.data.recordsPage + 1, true);
}
},
async onShow() {
// 未登录则不触发签到与刷新
if (!weChatAuthService.isLoggedIn()) {
return;
}
// 每日签到:页面显示时尝试发放当天首次登录积分
try {
const res = await dailyCheckin();
console.log('[积分] 每日签到结果:', res);
} catch (e) {
console.warn('[积分] 每日签到失败或未登录:', e);
}
// 刷新积分相关数据
try {
await Promise.all([
this.loadUserPoints(),
this.loadPointsOverview(),
this.loadPointsHistory(1, false)
]);
} catch (err) {
console.warn('[积分] 刷新数据失败:', err);
}
},
onShareAppMessage() {
return {
title: '我的积分',
path: '/pages/points/index'
};
}
});