// pages/message/message.js
|
const app = getApp()
|
const { graphqlRequest, formatDate, formatRelativeTime } = require('../../lib/utils')
|
|
Page({
|
data: {
|
loading: false,
|
refreshing: false,
|
loadingMore: false,
|
hasMore: true,
|
|
// 消息列表
|
messages: [],
|
|
// 分页参数
|
pagination: {
|
page: 1,
|
limit: 20,
|
total: 0
|
},
|
|
// 筛选条件
|
filter: {
|
type: 'ALL', // ALL, SYSTEM, ACTIVITY, JUDGE, ORGANIZER
|
status: 'ALL' // ALL, READ, UNREAD
|
},
|
|
// 筛选选项
|
typeOptions: [
|
{ value: 'ALL', label: '全部消息' },
|
{ value: 'SYSTEM', label: '系统通知' },
|
{ value: 'ACTIVITY', label: '活动消息' },
|
{ value: 'JUDGE', label: '评审消息' },
|
{ value: 'ORGANIZER', label: '主办方消息' }
|
],
|
|
statusOptions: [
|
{ value: 'ALL', label: '全部状态' },
|
{ value: 'UNREAD', label: '未读' },
|
{ value: 'READ', label: '已读' }
|
],
|
|
// 显示筛选面板
|
showFilter: false,
|
|
// 统计数据
|
stats: {
|
total: 0,
|
unread: 0
|
},
|
|
// 选择模式
|
selectMode: false,
|
selectedMessages: [],
|
|
// 消息类型图标映射
|
typeIcons: {
|
'SYSTEM': '🔔',
|
'ACTIVITY': '🎯',
|
'JUDGE': '⚖️',
|
'ORGANIZER': '👥',
|
'REGISTRATION': '📝',
|
'RESULT': '🏆',
|
'REMINDER': '⏰'
|
}
|
},
|
|
onLoad() {
|
this.loadMessages()
|
this.loadMessageStats()
|
},
|
|
onShow() {
|
// 页面显示时刷新未读数量
|
this.loadMessageStats()
|
// 初始化自定义 tabbar
|
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
this.getTabBar().init()
|
}
|
},
|
|
onPullDownRefresh() {
|
this.refreshMessages()
|
},
|
|
onReachBottom() {
|
if (this.data.hasMore && !this.data.loadingMore) {
|
this.loadMoreMessages()
|
}
|
},
|
|
// 加载消息列表
|
async loadMessages(reset = true) {
|
try {
|
if (reset) {
|
this.setData({
|
loading: true,
|
pagination: { ...this.data.pagination, page: 1 }
|
})
|
}
|
|
const { filter, pagination } = this.data
|
|
const query = `
|
query GetMessages($input: MessageQueryInput!) {
|
messages(input: $input) {
|
items {
|
id
|
type
|
title
|
content
|
isRead
|
createdAt
|
data
|
relatedActivity {
|
id
|
title
|
}
|
}
|
pagination {
|
total
|
page
|
limit
|
hasMore
|
}
|
}
|
}
|
`
|
|
const input = {
|
type: filter.type === 'ALL' ? null : filter.type,
|
status: filter.status === 'ALL' ? null : filter.status,
|
page: pagination.page,
|
limit: pagination.limit
|
}
|
|
const result = await graphqlRequest(query, { input })
|
|
if (result && result.messages) {
|
const { items, pagination: newPagination } = result.messages
|
|
// 为每个消息添加选中状态
|
const processedItems = items.map(item => ({
|
...item,
|
isSelected: this.data.selectedMessages.indexOf(item.id) > -1
|
}))
|
|
this.setData({
|
messages: reset ? processedItems : [...this.data.messages, ...processedItems],
|
pagination: newPagination,
|
hasMore: newPagination.hasMore
|
})
|
}
|
} catch (error) {
|
console.error('加载消息失败:', error)
|
wx.showToast({
|
title: '加载失败',
|
icon: 'error'
|
})
|
} finally {
|
this.setData({
|
loading: false,
|
refreshing: false,
|
loadingMore: false
|
})
|
wx.stopPullDownRefresh()
|
}
|
},
|
|
// 刷新消息
|
async refreshMessages() {
|
this.setData({ refreshing: true })
|
await this.loadMessages(true)
|
await this.loadMessageStats()
|
},
|
|
// 加载更多消息
|
async loadMoreMessages() {
|
if (!this.data.hasMore || this.data.loadingMore) return
|
|
this.setData({
|
loadingMore: true,
|
pagination: {
|
...this.data.pagination,
|
page: this.data.pagination.page + 1
|
}
|
})
|
|
await this.loadMessages(false)
|
},
|
|
// 加载消息统计
|
async loadMessageStats() {
|
try {
|
const query = `
|
query GetMessageStats {
|
messageStats {
|
total
|
unread
|
}
|
}
|
`
|
|
const result = await graphqlRequest(query)
|
|
if (result && result.messageStats) {
|
this.setData({
|
stats: result.messageStats
|
})
|
|
// 更新底部导航栏的未读数量
|
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
this.getTabBar().setData({
|
unreadCount: result.messageStats.unread
|
})
|
}
|
}
|
} catch (error) {
|
console.error('加载消息统计失败:', error)
|
}
|
},
|
|
// 消息点击
|
async onMessageTap(e) {
|
const { id, index } = e.currentTarget.dataset
|
const message = this.data.messages[index]
|
|
// 如果是选择模式,切换选择状态
|
if (this.data.selectMode) {
|
this.toggleMessageSelection(id)
|
return
|
}
|
|
// 标记为已读
|
if (!message.isRead) {
|
await this.markAsRead(id, index)
|
}
|
|
// 根据消息类型处理跳转
|
this.handleMessageAction(message)
|
},
|
|
// 处理消息动作
|
handleMessageAction(message) {
|
const { type, data, relatedActivity } = message
|
|
switch (type) {
|
case 'ACTIVITY':
|
if (relatedActivity && relatedActivity.id) {
|
wx.navigateTo({
|
url: `/pages/activity/detail?id=${relatedActivity.id}`
|
})
|
}
|
break
|
case 'REGISTRATION':
|
if (data && data.registrationId) {
|
wx.navigateTo({
|
url: `/pages/profile/registration-detail?id=${data.registrationId}`
|
})
|
}
|
break
|
case 'JUDGE':
|
if (data && data.submissionId) {
|
wx.navigateTo({
|
url: `/pages/judge/review?id=${data.submissionId}`
|
})
|
}
|
break
|
case 'ORGANIZER':
|
if (relatedActivity && relatedActivity.id) {
|
wx.navigateTo({
|
url: `/pages/organizer/activity-detail?id=${relatedActivity.id}`
|
})
|
}
|
break
|
default:
|
// 显示消息详情
|
this.showMessageDetail(message)
|
break
|
}
|
},
|
|
// 显示消息详情
|
showMessageDetail(message) {
|
wx.showModal({
|
title: message.title,
|
content: message.content,
|
showCancel: false,
|
confirmText: '知道了'
|
})
|
},
|
|
// 标记为已读
|
async markAsRead(messageId, index) {
|
try {
|
const mutation = `
|
mutation MarkMessageAsRead($id: ID!) {
|
markMessageAsRead(id: $id) {
|
success
|
}
|
}
|
`
|
|
const result = await graphqlRequest(mutation, { id: messageId })
|
|
if (result && result.markMessageAsRead.success) {
|
// 更新本地数据
|
const messages = [...this.data.messages]
|
messages[index].isRead = true
|
|
this.setData({ messages })
|
|
// 更新统计数据
|
this.setData({
|
'stats.unread': Math.max(0, this.data.stats.unread - 1)
|
})
|
}
|
} catch (error) {
|
console.error('标记已读失败:', error)
|
}
|
},
|
|
// 批量标记为已读
|
async markAllAsRead() {
|
try {
|
wx.showLoading({ title: '处理中...' })
|
|
const mutation = `
|
mutation MarkAllMessagesAsRead {
|
markAllMessagesAsRead {
|
success
|
count
|
}
|
}
|
`
|
|
const result = await graphqlRequest(mutation)
|
|
if (result && result.markAllMessagesAsRead.success) {
|
// 刷新消息列表
|
await this.refreshMessages()
|
|
wx.showToast({
|
title: '已全部标记为已读',
|
icon: 'success'
|
})
|
}
|
} catch (error) {
|
console.error('批量标记已读失败:', error)
|
wx.showToast({
|
title: '操作失败',
|
icon: 'error'
|
})
|
} finally {
|
wx.hideLoading()
|
}
|
},
|
|
// 删除消息
|
async deleteMessage(messageId) {
|
try {
|
const mutation = `
|
mutation DeleteMessage($id: ID!) {
|
deleteMessage(id: $id) {
|
success
|
}
|
}
|
`
|
|
const result = await graphqlRequest(mutation, { id: messageId })
|
|
if (result && result.deleteMessage.success) {
|
// 从列表中移除
|
const messages = this.data.messages.filter(msg => msg.id !== messageId)
|
this.setData({ messages })
|
|
wx.showToast({
|
title: '删除成功',
|
icon: 'success'
|
})
|
}
|
} catch (error) {
|
console.error('删除消息失败:', error)
|
wx.showToast({
|
title: '删除失败',
|
icon: 'error'
|
})
|
}
|
},
|
|
// 长按消息
|
onMessageLongPress(e) {
|
const { id } = e.currentTarget.dataset
|
|
wx.showActionSheet({
|
itemList: ['标记为已读', '删除消息'],
|
success: (res) => {
|
switch (res.tapIndex) {
|
case 0:
|
this.markAsRead(id)
|
break
|
case 1:
|
wx.showModal({
|
title: '确认删除',
|
content: '确定要删除这条消息吗?',
|
success: (modalRes) => {
|
if (modalRes.confirm) {
|
this.deleteMessage(id)
|
}
|
}
|
})
|
break
|
}
|
}
|
})
|
},
|
|
// 切换筛选面板
|
onToggleFilter() {
|
this.setData({
|
showFilter: !this.data.showFilter
|
})
|
},
|
|
// 筛选条件改变
|
onFilterChange(e) {
|
const { type, value } = e.currentTarget.dataset
|
|
this.setData({
|
[`filter.${type}`]: value,
|
showFilter: false
|
})
|
|
// 重新加载消息
|
this.loadMessages(true)
|
},
|
|
// 切换选择模式
|
onToggleSelectMode() {
|
this.setData({
|
selectMode: !this.data.selectMode,
|
selectedMessages: []
|
})
|
},
|
|
// 切换消息选择状态
|
toggleMessageSelection(messageId) {
|
const selectedMessages = [...this.data.selectedMessages]
|
const index = selectedMessages.indexOf(messageId)
|
|
if (index > -1) {
|
selectedMessages.splice(index, 1)
|
} else {
|
selectedMessages.push(messageId)
|
}
|
|
// 同时更新消息的isSelected字段
|
const messages = this.data.messages.map(msg => ({
|
...msg,
|
isSelected: selectedMessages.indexOf(msg.id) > -1
|
}))
|
|
this.setData({
|
selectedMessages,
|
messages
|
})
|
},
|
|
// 全选/取消全选
|
onToggleSelectAll() {
|
const { messages, selectedMessages } = this.data
|
const allSelected = selectedMessages.length === messages.length
|
const newSelectedMessages = allSelected ? [] : messages.map(msg => msg.id)
|
|
// 同时更新消息的isSelected字段
|
const updatedMessages = messages.map(msg => ({
|
...msg,
|
isSelected: !allSelected
|
}))
|
|
this.setData({
|
selectedMessages: newSelectedMessages,
|
messages: updatedMessages
|
})
|
},
|
|
// 批量删除选中消息
|
async onDeleteSelected() {
|
const { selectedMessages } = this.data
|
|
if (selectedMessages.length === 0) {
|
wx.showToast({
|
title: '请选择要删除的消息',
|
icon: 'error'
|
})
|
return
|
}
|
|
wx.showModal({
|
title: '确认删除',
|
content: `确定要删除选中的 ${selectedMessages.length} 条消息吗?`,
|
success: async (res) => {
|
if (res.confirm) {
|
try {
|
wx.showLoading({ title: '删除中...' })
|
|
const mutation = `
|
mutation DeleteMessages($ids: [ID!]!) {
|
deleteMessages(ids: $ids) {
|
success
|
count
|
}
|
}
|
`
|
|
const result = await graphqlRequest(mutation, { ids: selectedMessages })
|
|
if (result && result.deleteMessages.success) {
|
// 刷新消息列表
|
await this.refreshMessages()
|
|
this.setData({
|
selectMode: false,
|
selectedMessages: []
|
})
|
|
wx.showToast({
|
title: `已删除 ${result.deleteMessages.count} 条消息`,
|
icon: 'success'
|
})
|
}
|
} catch (error) {
|
console.error('批量删除失败:', error)
|
wx.showToast({
|
title: '删除失败',
|
icon: 'error'
|
})
|
} finally {
|
wx.hideLoading()
|
}
|
}
|
}
|
})
|
},
|
|
// 获取消息类型图标
|
getTypeIcon(type) {
|
return this.data.typeIcons[type] || '📨'
|
},
|
|
// 获取消息类型文本
|
getTypeText(type) {
|
const typeMap = {
|
'SYSTEM': '系统通知',
|
'ACTIVITY': '活动消息',
|
'JUDGE': '评审消息',
|
'ORGANIZER': '主办方消息',
|
'REGISTRATION': '报名消息',
|
'RESULT': '结果通知',
|
'REMINDER': '提醒消息'
|
}
|
return typeMap[type] || '消息'
|
},
|
|
// 格式化时间
|
formatTime(dateString) {
|
const now = new Date()
|
const date = new Date(dateString)
|
const diff = now.getTime() - date.getTime()
|
|
// 一天内显示相对时间
|
if (diff < 24 * 60 * 60 * 1000) {
|
return formatRelativeTime(dateString)
|
}
|
|
// 超过一天显示具体日期
|
return formatDate(dateString, 'MM-DD HH:mm')
|
},
|
|
// 分享页面
|
onShareAppMessage() {
|
return {
|
title: '蓉易创 - 消息中心',
|
path: '/pages/index/index'
|
}
|
}
|
})
|