yingsa/miniprogram/pages/match/challenge/index.js
Ethanfly d07ebb735a fix(env): Update API URL and enhance HTML structure
- Change VITE_API_URL in .env from localhost:3000 to localhost:3001 for backend access.
- Update index.html to replace favicon with logo.png and ensure proper HTML structure.
- Add new dependencies for WangEditor in package.json and package-lock.json to support rich text editing features.
2026-02-06 19:04:16 +08:00

368 lines
9.5 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.

const app = getApp();
const util = require("../../../utils/util");
Page({
data: {
userInfo: null,
ladderUser: null,
currentStore: null,
ongoingMatches: [], // 正在进行中的比赛
pendingGames: [], // 待确认的比赛
recentMatches: [], // 最近比赛用于预览前10场
},
onLoad() {
this.initData();
},
onShow() {
this.initData();
},
async onPullDownRefresh() {
try {
await this.initData();
} finally {
wx.stopPullDownRefresh();
}
},
async initData() {
// 检查是否已登录(有 token
if (!app.globalData.token) {
// 未登录,跳转到用户页面进行登录
wx.switchTab({ url: "/pages/user/index" });
return;
}
// 每次显示页面时重新获取门店和天梯信息
try {
await app.getCurrentStore();
// 如果有门店,获取该门店的天梯信息
if (app.globalData.currentStore && app.globalData.currentStore.storeId) {
await app.getLadderUser(app.globalData.currentStore.storeId);
}
} catch (e) {
console.error("获取门店/天梯信息失败:", e);
}
this.refreshData();
},
refreshData() {
this.setData({
userInfo: app.globalData.userInfo,
ladderUser: app.globalData.ladderUser,
currentStore: app.globalData.currentStore,
});
if (app.globalData.ladderUser) {
this.fetchOngoingMatches();
this.fetchPendingGames();
this.fetchRecentMatches();
}
},
// 获取正在进行中的比赛
async fetchOngoingMatches() {
try {
const res = await app.request("/api/match/ongoing", {
store_id: this.data.currentStore
? this.data.currentStore.storeId
: null,
});
this.setData({ ongoingMatches: res.data || [] });
} catch (e) {
console.error("获取进行中比赛失败:", e);
}
},
// 手动刷新天梯信息
async refreshLadderInfo() {
wx.showLoading({ title: "刷新中..." });
try {
// 重新获取门店信息
await app.getCurrentStore();
// 重新获取天梯信息
if (app.globalData.currentStore && app.globalData.currentStore.storeId) {
await app.getLadderUser(app.globalData.currentStore.storeId);
}
this.refreshData();
wx.hideLoading();
if (app.globalData.ladderUser) {
wx.showToast({ title: "已加入天梯", icon: "success" });
} else {
wx.showToast({ title: "暂未开通天梯", icon: "none" });
}
} catch (e) {
wx.hideLoading();
console.error("刷新天梯信息失败:", e);
wx.showToast({ title: "刷新失败", icon: "none" });
}
},
async fetchPendingGames() {
try {
const res = await app.request("/api/match/pending-confirm", {
store_id: this.data.currentStore
? this.data.currentStore.storeId
: null,
});
this.setData({ pendingGames: res.data || [] });
} catch (e) {
console.error("获取待确认比赛失败:", e);
}
},
// 获取最近比赛近7天最多10场用于比赛页预览
async fetchRecentMatches() {
try {
const storeId = this.data.currentStore
? this.data.currentStore.storeId
: null;
const res = await app.request("/api/match/display-list", {
store_id: storeId,
days: 7,
limit: 10,
});
const raw = res.data || [];
const recentMatches = raw.map((item) => {
const time = item.startTime || item.createdAt || item.endTime || null;
const stageName = item.stageName || "";
const statusName = item.statusName || "";
const showStage = !!stageName && stageName !== statusName;
let statusType = "pending";
switch (item.status) {
case 1:
statusType = "ongoing";
break;
case 2:
statusType = "finished";
break;
case 3:
statusType = "cancelled";
break;
default:
statusType = "pending";
}
return Object.assign({}, item, {
timeText: time ? util.formatDate(time) : "",
stageName,
statusName,
showStage,
statusType,
});
});
this.setData({ recentMatches });
} catch (e) {
console.error("获取最近比赛失败:", e);
}
},
startChallenge() {
if (!this.data.ladderUser) {
wx.showToast({ title: "请先加入天梯系统", icon: "none" });
return;
}
if (!this.data.currentStore || !this.data.currentStore.storeId) {
wx.showToast({ title: "请先选择门店", icon: "none" });
wx.navigateTo({ url: "/pages/store/index" });
return;
}
wx.scanCode({
onlyFromCamera: false,
scanType: ["qrCode"],
success: async (res) => {
const memberCode = res.result;
this.checkAndChallenge(memberCode);
},
fail: (err) => {
if (err.errMsg !== "scanCode:fail cancel") {
wx.showToast({ title: "扫码失败", icon: "none" });
}
},
});
},
async checkAndChallenge(memberCode) {
wx.showLoading({ title: "检查中..." });
try {
const res = await app.request(
`/api/match/challenge/check/${memberCode}`,
{
store_id: this.data.currentStore.storeId,
},
);
wx.hideLoading();
if (!res.data.canChallenge) {
wx.showModal({
title: "无法挑战",
content: res.data.reason,
showCancel: false,
});
return;
}
// 显示确认弹窗
const target = res.data.targetUser;
wx.showModal({
title: "确认挑战",
content: `确定要向 ${target.ladderUser.realName}(Lv${target.ladderUser.level}, 战力${target.ladderUser.powerScore}) 发起挑战吗?`,
success: async (modalRes) => {
if (modalRes.confirm) {
await this.createChallenge(memberCode);
}
},
});
} catch (e) {
wx.hideLoading();
console.error("检查挑战失败:", e);
}
},
async createChallenge(memberCode) {
wx.showLoading({ title: "发起挑战中..." });
try {
const res = await app.request(
"/api/match/challenge/create",
{
store_id: this.data.currentStore.storeId,
target_member_code: memberCode,
},
"POST",
);
wx.hideLoading();
wx.showToast({ title: "挑战已发起", icon: "success" });
// 跳转到挑战赛详情页面
if (res.data && res.data.matchId) {
setTimeout(() => {
wx.navigateTo({
url: `/pages/match/challenge-detail/index?id=${res.data.matchId}`,
});
}, 1500);
}
} catch (e) {
wx.hideLoading();
console.error("发起挑战失败:", e);
const errorMsg =
e.message || (e.data && e.data.message) || "发起挑战失败";
wx.showToast({ title: errorMsg, icon: "none", duration: 2000 });
}
},
joinRankingMatch() {
if (!this.data.ladderUser) {
wx.showToast({ title: "请先加入天梯系统", icon: "none" });
return;
}
wx.scanCode({
onlyFromCamera: false,
scanType: ["qrCode"],
success: async (res) => {
const matchCode = res.result;
wx.showLoading({ title: "加入中..." });
try {
const joinRes = await app.request(
"/api/match/ranking/join",
{
match_code: matchCode,
},
"POST",
);
wx.hideLoading();
wx.showToast({ title: "加入成功", icon: "success" });
// 跳转到排位赛详情
wx.navigateTo({
url: `/pages/match/ranking/index?code=${matchCode}`,
});
} catch (e) {
wx.hideLoading();
console.error("加入排位赛失败:", e);
}
},
fail: (err) => {
if (err.errMsg !== "scanCode:fail cancel") {
wx.showToast({ title: "扫码失败", icon: "none" });
}
},
});
},
goToStore() {
wx.navigateTo({ url: "/pages/store/index" });
},
// 跳转到最近比赛列表页
goToRecentMatches() {
wx.navigateTo({ url: "/pages/match/recent/index" });
},
// 跳转到比赛详情
goToMatchDetail(e) {
const match = e.currentTarget.dataset.match;
if (match.type === 1) {
// 挑战赛详情
wx.navigateTo({
url: `/pages/match/challenge-detail/index?id=${match.id}`,
});
} else {
// 排位赛详情
wx.navigateTo({
url: `/pages/match/ranking/index?code=${match.matchCode}`,
});
}
},
confirmGame(e) {
const game = e.currentTarget.dataset.game;
wx.showModal({
title: "确认比分",
content: `确认比分 ${game.myScore} : ${game.opponentScore} 吗?`,
confirmText: "确认",
cancelText: "有争议",
success: async (res) => {
wx.showLoading({ title: "处理中..." });
try {
await app.request(
"/api/match/challenge/confirm-score",
{
game_id: game.id,
confirm: res.confirm,
},
"POST",
);
wx.hideLoading();
wx.showToast({
title: res.confirm ? "确认成功" : "已标记争议",
icon: "success",
});
this.fetchPendingGames();
} catch (e) {
wx.hideLoading();
console.error("确认比分失败:", e);
}
},
});
},
});