| | |
| | | awards: 0 |
| | | }, |
| | | |
| | | // 我的报名记录 |
| | | registrations: [], |
| | | registrationLoading: false, |
| | | |
| | | |
| | | // 用户项目 |
| | | userProjects: [], |
| | | projectsLoading: false, |
| | | |
| | | // 角色相关 |
| | | userRoles: [], |
| | | isJudge: false, |
| | | isOrganizer: false, |
| | | hasPlayer: false, |
| | | |
| | | // 评委相关数据 |
| | | judgeStats: { |
| | | pendingReviews: 0, |
| | | completedReviews: 0, |
| | | totalReviews: 0 |
| | | studentUnReviewedCount: 0 |
| | | }, |
| | | |
| | | // 主办方相关数据 |
| | |
| | | |
| | | this.loadUserInfo() |
| | | this.loadUserStats() |
| | | this.loadRecentRegistrations() |
| | | this.loadUserProjects() |
| | | }, |
| | | |
| | | onShow() { |
| | | // 页面显示时刷新数据 |
| | | this.loadUserInfo() |
| | | this.loadUserStats() |
| | | this.loadRecentRegistrations() |
| | | this.loadUserProjects() |
| | | // 初始化自定义 tabbar |
| | | if (typeof this.getTabBar === 'function' && this.getTabBar()) { |
| | | this.getTabBar().init() |
| | |
| | | |
| | | // 刷新数据 |
| | | async refreshData() { |
| | | this.setData({ loading: true }) |
| | | |
| | | try { |
| | | await Promise.all([ |
| | | this.loadUserInfo(), |
| | | this.loadUserStats(), |
| | | this.loadRecentRegistrations() |
| | | this.loadUserProjects() |
| | | ]) |
| | | } catch (error) { |
| | | console.error('刷新数据失败:', error) |
| | | } finally { |
| | | this.setData({ loading: false }) |
| | | wx.stopPullDownRefresh() |
| | | } |
| | | }, |
| | |
| | | grade |
| | | roles |
| | | createdAt |
| | | player { |
| | | id |
| | | name |
| | | phone |
| | | description |
| | | } |
| | | } |
| | | } |
| | | ` |
| | |
| | | const userRoles = userInfo.roles || [] |
| | | const isJudge = userRoles.includes('JUDGE') |
| | | const isOrganizer = userRoles.includes('ORGANIZER') |
| | | const hasPlayer = userInfo.player && userInfo.player.id |
| | | |
| | | // 处理头像文字 |
| | | const avatarText = (userInfo.name || '用户').substring(0, 1) |
| | |
| | | avatarText, |
| | | userRoles, |
| | | isJudge, |
| | | isOrganizer |
| | | isOrganizer, |
| | | hasPlayer |
| | | }) |
| | | |
| | | // 更新全局用户信息 |
| | |
| | | }, |
| | | |
| | | // 加载最近报名记录 |
| | | async loadRecentRegistrations() { |
| | | // 加载用户项目 |
| | | async loadUserProjects() { |
| | | this.setData({ projectsLoading: true }) |
| | | |
| | | try { |
| | | this.setData({ registrationLoading: true }) |
| | | |
| | | const query = ` |
| | | query GetRecentRegistrations { |
| | | myRegistrations(limit: 5) { |
| | | query GetMyProjects { |
| | | myProjects { |
| | | id |
| | | activity { |
| | | id |
| | | title |
| | | coverImage { |
| | | id |
| | | name |
| | | path |
| | | fullUrl |
| | | fullThumbUrl |
| | | mediaType |
| | | } |
| | | startTime |
| | | status |
| | | } |
| | | projectName |
| | | activityName |
| | | status |
| | | registrationTime |
| | | statusText |
| | | createTime |
| | | submissionFiles { |
| | | id |
| | | name |
| | | path |
| | | fullUrl |
| | | fullThumbUrl |
| | | fileExt |
| | | mediaType |
| | | } |
| | | } |
| | | } |
| | | ` |
| | | |
| | | const result = await graphqlRequest(query) |
| | | |
| | | if (result && result.myRegistrations) { |
| | | // 为每个活动添加标题文字 |
| | | const registrations = result.myRegistrations.map(registration => ({ |
| | | ...registration, |
| | | activity: { |
| | | ...registration.activity, |
| | | titleText: (registration.activity.title || '活动').substring(0, 2) |
| | | if (result && result.myProjects) { |
| | | const projects = result.myProjects.map(project => { |
| | | // 获取项目的第一个媒体文件作为缩略图 |
| | | let thumbnailUrl = '' |
| | | let iconClass = this.getProjectIcon(project.status) |
| | | |
| | | if (project.submissionFiles && project.submissionFiles.length > 0) { |
| | | const firstFile = project.submissionFiles[0] |
| | | |
| | | // 根据文件类型设置缩略图和图标 |
| | | if (firstFile.mediaType === 'IMAGE') { |
| | | thumbnailUrl = firstFile.fullThumbUrl || firstFile.fullUrl |
| | | iconClass = 'ic-image' |
| | | } else if (firstFile.mediaType === 'VIDEO') { |
| | | thumbnailUrl = firstFile.fullThumbUrl || firstFile.fullUrl |
| | | iconClass = 'ic-video' |
| | | } else if (firstFile.fileExt && firstFile.fileExt.toLowerCase() === 'pdf') { |
| | | iconClass = 'ic-pdf' |
| | | } else if (firstFile.fileExt && ['doc', 'docx'].includes(firstFile.fileExt.toLowerCase())) { |
| | | iconClass = 'ic-word' |
| | | } else { |
| | | iconClass = 'ic-file' |
| | | } |
| | | } |
| | | })) |
| | | |
| | | this.setData({ |
| | | registrations |
| | | |
| | | return { |
| | | id: project.id, |
| | | projectName: project.projectName, |
| | | activityName: project.activityName, |
| | | state: project.status, |
| | | statusText: project.statusText || this.getProjectStatusText(project.status), |
| | | statusType: this.getProjectStatusType(project.status), |
| | | icon: iconClass, |
| | | thumbnailUrl: thumbnailUrl, |
| | | createTime: project.createTime |
| | | } |
| | | }) |
| | | |
| | | this.setData({ userProjects: projects }) |
| | | } |
| | | } catch (error) { |
| | | console.error('加载报名记录失败:', error) |
| | | console.error('加载用户项目失败:', error) |
| | | // 不显示错误提示,静默失败 |
| | | } finally { |
| | | this.setData({ registrationLoading: false }) |
| | | this.setData({ projectsLoading: false }) |
| | | } |
| | | }, |
| | | |
| | |
| | | async loadJudgeStats() { |
| | | try { |
| | | const query = ` |
| | | query GetJudgeStats { |
| | | judgeStats { |
| | | pendingReviews |
| | | completedReviews |
| | | totalReviews |
| | | query GetReviewStatistics { |
| | | reviewStatistics { |
| | | unReviewedCount |
| | | reviewedCount |
| | | studentUnReviewedCount |
| | | } |
| | | } |
| | | ` |
| | | |
| | | const result = await graphqlRequest(query) |
| | | |
| | | if (result && result.judgeStats) { |
| | | const judgeStats = result.judgeStats |
| | | if (result && result.reviewStatistics) { |
| | | const stats = result.reviewStatistics |
| | | |
| | | // 转换字段名以匹配现有的数据结构 |
| | | const judgeStats = { |
| | | pendingReviews: stats.unReviewedCount, |
| | | completedReviews: stats.reviewedCount, |
| | | studentUnReviewedCount: stats.studentUnReviewedCount |
| | | } |
| | | |
| | | this.setData({ |
| | | judgeStats, |
| | |
| | | }) |
| | | }, |
| | | |
| | | // 菜单项点击 |
| | | onMenuItemTap(e) { |
| | | const { path } = e.currentTarget.dataset |
| | | |
| | | // 跳转到个人信息页面 |
| | | goToPersonalInfo() { |
| | | wx.navigateTo({ |
| | | url: path |
| | | url: '/pages/profile/personal-info' |
| | | }) |
| | | }, |
| | | |
| | | // 跳转到项目详情页面 |
| | | goToProjectDetail(e) { |
| | | const projectId = e.currentTarget.dataset.projectId |
| | | |
| | | if (!projectId) { |
| | | wx.showToast({ |
| | | title: '项目ID无效', |
| | | icon: 'none' |
| | | }) |
| | | return |
| | | } |
| | | |
| | | // 如果是示例数据,显示提示 |
| | | if (projectId === 'registrations' || projectId === 'achievements') { |
| | | wx.showToast({ |
| | | title: '这是示例项目,请选择真实项目', |
| | | icon: 'none' |
| | | }) |
| | | return |
| | | } |
| | | |
| | | wx.navigateTo({ |
| | | url: `/pages/project/detail?id=${projectId}` |
| | | }) |
| | | }, |
| | | |
| | | // 跳转到评审页面 |
| | | goToReviewPage() { |
| | | wx.navigateTo({ |
| | | url: '/pages/review/index' |
| | | }) |
| | | }, |
| | | |
| | | |
| | | |
| | | // 查看报名详情 |
| | | onRegistrationTap(e) { |
| | |
| | | return formatDate(dateString, 'MM-DD HH:mm') |
| | | }, |
| | | |
| | | // 退出登录 |
| | | onLogout() { |
| | | wx.showModal({ |
| | | title: '确认退出', |
| | | content: '确定要退出登录吗?', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | this.logout() |
| | | } |
| | | } |
| | | }) |
| | | // 获取项目状态文本(支持数字和字符串状态) |
| | | getProjectStatusText(status) { |
| | | // 数字状态映射(与web端保持一致) |
| | | const numericStatusMap = { |
| | | 0: '未审核', |
| | | 1: '审核通过', |
| | | 2: '审核驳回', |
| | | 3: '已结束' |
| | | } |
| | | |
| | | // 字符串状态映射 |
| | | const stringStatusMap = { |
| | | 'SUBMITTED': '已提交', |
| | | 'UNDER_REVIEW': '评审中', |
| | | 'REVIEWED': '已评审', |
| | | 'REJECTED': '已拒绝', |
| | | 'DRAFT': '草稿' |
| | | } |
| | | |
| | | // 优先使用数字状态映射 |
| | | if (typeof status === 'number' && numericStatusMap[status]) { |
| | | return numericStatusMap[status] |
| | | } |
| | | |
| | | return stringStatusMap[status] || '未知状态' |
| | | }, |
| | | |
| | | // 执行退出登录 |
| | | async logout() { |
| | | try { |
| | | wx.showLoading({ title: '退出中...' }) |
| | | |
| | | // 清除本地存储 |
| | | wx.removeStorageSync('token') |
| | | wx.removeStorageSync('userInfo') |
| | | |
| | | // 清除全局数据 |
| | | app.globalData.token = '' |
| | | app.globalData.userInfo = null |
| | | app.globalData.isLoggedIn = false |
| | | |
| | | // 跳转到登录页 |
| | | wx.reLaunch({ |
| | | url: '/pages/login/login' |
| | | }) |
| | | |
| | | wx.showToast({ |
| | | title: '已退出登录', |
| | | icon: 'success' |
| | | }) |
| | | } catch (error) { |
| | | console.error('退出登录失败:', error) |
| | | wx.showToast({ |
| | | title: '退出失败', |
| | | icon: 'error' |
| | | }) |
| | | } finally { |
| | | wx.hideLoading() |
| | | // 获取项目状态类型(用于样式) |
| | | getProjectStatusType(status) { |
| | | // 数字状态类型映射(与web端保持一致) |
| | | const numericTypeMap = { |
| | | 0: 'warning', // 未审核 |
| | | 1: 'success', // 审核通过 |
| | | 2: 'danger', // 审核驳回 |
| | | 3: 'info' // 已结束 |
| | | } |
| | | |
| | | // 字符串状态类型映射 |
| | | const stringTypeMap = { |
| | | 'SUBMITTED': 'primary', |
| | | 'UNDER_REVIEW': 'warning', |
| | | 'REVIEWED': 'success', |
| | | 'REJECTED': 'danger', |
| | | 'DRAFT': 'info' |
| | | } |
| | | |
| | | // 优先使用数字状态映射 |
| | | if (typeof status === 'number' && numericTypeMap[status]) { |
| | | return numericTypeMap[status] |
| | | } |
| | | |
| | | return stringTypeMap[status] || 'info' |
| | | }, |
| | | |
| | | // 获取项目图标 |
| | | getProjectIcon(status) { |
| | | // 数字状态图标映射 |
| | | const numericIconMap = { |
| | | 0: '⏳', // 未审核 |
| | | 1: '✅', // 审核通过 |
| | | 2: '❌', // 审核驳回 |
| | | 3: '📋' // 已结束 |
| | | } |
| | | |
| | | // 字符串状态图标映射 |
| | | const stringIconMap = { |
| | | 'SUBMITTED': '📋', |
| | | 'UNDER_REVIEW': '⏳', |
| | | 'REVIEWED': '✅', |
| | | 'REJECTED': '❌', |
| | | 'DRAFT': '📝' |
| | | } |
| | | |
| | | // 优先使用数字状态映射 |
| | | if (typeof status === 'number' && numericIconMap[status]) { |
| | | return numericIconMap[status] |
| | | } |
| | | |
| | | return stringIconMap[status] || '📋' |
| | | }, |
| | | |
| | | |
| | | |
| | | // 分享页面 |
| | | onShareAppMessage() { |
| | | return { |