const { withDataCache } = require('../../utils/page-cache'); const { getLayout } = require('../../utils/layout'); const { api, getImageUrl } = require('../../utils/request'); Page(withDataCache({ noop: function() {}, onResize: function() { this.setData(getLayout()); }, data: { loadError: false, diary: null, loading: true, comments: [], commentPage: 1, hasMoreComments: true, showCommentInput: false, commentText: '', commentInitialText: '', commentLength: 0, commentFocus: false, commentKeyboardHeight: 0, commentEditorHeight: 56, commentSending: false, replyTo: null, coverSwiperIndex: 0, previewImages: [], previewIndex: 0, showPreview: false, myUid: 0 }, onLoad: function(options) { this.setData(getLayout()); var diaryId = options.id; if (!diaryId) { wx.showToast({ title: '参数错误', icon: 'none' }); return; } this.setData({ diaryId: parseInt(diaryId), myUid: wx.getStorageSync('userId') || 0 }); this.loadDiary(); this.loadComments(); }, onShow: function() { if (this.data.diaryId) { this.loadDiary(); this.loadComments(); } }, loadDiary: async function() { if (this._pageLoading) return; this._pageLoading = true; this.setData({loading: !this._hasCachedData, loadError:false}); try { var data = await api.diaryDetail(this.data.diaryId); data = this._formatDiary(data); this.setData({ diary: data, myUid: wx.getStorageSync('userId') || 0, loading: false }); } catch (e) { this.setData({loadError:true}); wx.showToast({ title: '加载失败', icon: 'none' }); this.setData({ loading: false }); } finally { this._pageLoading = false; this.setData({loading:false}); } }, _formatDiary: function(data) { var myUid = wx.getStorageSync('userId') || 0; data.creator_name = data.creator_name || (data.created_by == myUid ? '我' : 'TA'); data.creator_avatar = getImageUrl(data.creator_avatar); data.created_time = data.created_at ? data.created_at.substring(0, 16).replace('T', ' ') : ''; var imgs = data.images || []; if (typeof imgs === 'string') { try { imgs = JSON.parse(imgs); } catch(e) { imgs = []; } } if (!Array.isArray(imgs)) imgs = []; data.imageUrls = imgs.map(function(p) { return getImageUrl(p); }); data.comment_count = data.comment_count || 0; // 地理位置:优先显示地址名称,其次显示经纬度(经纬度为0的不显示) data.location_text = ''; var hasCoord = data.lat && data.lng && parseFloat(data.lat) !== 0 && parseFloat(data.lng) !== 0; if (data.location) { data.location_text = data.location; } else if (hasCoord) { data.location_text = data.lat + ', ' + data.lng; } return data; }, loadComments: async function() { this.setData({ commentsError: false }); try { var data = await api.diaryCommentList({ diary_id: this.data.diaryId }); if (data && data.length > 0) { data.forEach(function(c) { if (c.created_at) { c._time = c.created_at.substring(0, 16).replace('T', ' '); } else if (c.create_time) { c._time = c.create_time.substring(0, 16).replace('T', ' '); } else { c._time = ''; } }); } this.setData({ comments: data || [] }); } catch (e) { this.setData({ commentsError: true }); console.error(e); } }, onShareTap: function() { wx.showActionSheet({ itemList: ['分享给微信好友', '分享到朋友圈', '生成分享海报'], success: function(res) { if (res.tapIndex === 0) { wx.shareAppMessage ? wx.shareAppMessage() : wx.showToast({ title: '请点击右上角分享', icon: 'none' }); } else if (res.tapIndex === 1) { wx.showToast({ title: '请点击右上角分享到朋友圈', icon: 'none' }); } else { wx.showToast({ title: '功能开发中', icon: 'none' }); } } }); }, onCoverSwiperChange: function(e) { this.setData({ coverSwiperIndex: e.detail.current }); }, onImageTap: function(e) { var idx = this.data.coverSwiperIndex; var imgs = this.data.diary.imageUrls || []; this.setData({ showPreview: true, previewIndex: idx, previewImages: imgs }); }, closePreview: function() { this.setData({ showPreview: false }); }, onPreviewSwiperChange: function(e) { this.setData({ previewIndex: e.detail.current }); }, onCommentTap: function() { this.openComment(null); }, onReplyTap: function(e) { var item = e.currentTarget.dataset.item; this.openComment({ id: item.id, user_id: item.user_id, nickname: item.nickname }); }, openComment: function(replyTo) { var sameTarget = (!replyTo && !this.data.replyTo) || (replyTo && this.data.replyTo && replyTo.id === this.data.replyTo.id); var text = sameTarget ? this.data.commentText : ''; this.setData({ showCommentInput: true, replyTo: replyTo, commentText: text, commentInitialText: text, commentLength: text.length, commentFocus: true, commentKeyboardHeight: 0, commentEditorHeight: 56 }); }, onCommentInput: function(e) { // 不把正文反复写回原生输入框,避免中文输入时光标跳动。 this.data.commentText = e.detail.value || ''; this.setData({ commentLength: this.data.commentText.length }); }, onCommentKeyboardHeight: function(e) { var height = Math.max(0, Number(e.detail.height) || 0); if (this.data.showCommentInput) this.setData({ commentKeyboardHeight: height }); }, onCommentLineChange: function(e) { this.setData({ commentEditorHeight: Math.min(160, Math.max(56, Number(e.detail.height) || 56)) }); }, onCommentBlur: function() { this.setData({ commentFocus: false }); }, cancelComment: function() { if (this.data.commentSending) return; this.setData({ showCommentInput: false, commentFocus: false, commentKeyboardHeight: 0 }); wx.hideKeyboard(); }, onHide: function() { this.setData({ showCommentInput: false, commentFocus: false, commentKeyboardHeight: 0 }); }, submitComment: async function() { if (this.data.commentSending) return; var text = this.data.commentText.trim(); if (!text) { wx.showToast({ title: '请输入评论内容', icon: 'none' }); return; } this.setData({ commentSending: true }); try { var params = { diary_id: this.data.diaryId, content: text }; if (this.data.replyTo) { params.parent_id = this.data.replyTo.id; params.reply_to_user_id = this.data.replyTo.user_id; params.reply_to_username = this.data.replyTo.nickname; } var res = await api.diaryCommentAdd(params); if (res.success) { var newComment = res.comment || {}; if (newComment.created_at) { newComment._time = newComment.created_at.substring(0, 16).replace('T', ' '); } else if (newComment.create_time) { newComment._time = newComment.create_time.substring(0, 16).replace('T', ' '); } else { var now = new Date(); newComment._time = now.getFullYear() + '-' + String(now.getMonth()+1).padStart(2,'0') + '-' + String(now.getDate()).padStart(2,'0') + ' ' + String(now.getHours()).padStart(2,'0') + ':' + String(now.getMinutes()).padStart(2,'0'); } var newComments = this.data.comments.slice(); newComments.push(newComment); this.setData({ comments: newComments, showCommentInput: false, replyTo: null, commentText: '', commentInitialText: '', commentLength: 0, commentFocus: false, commentKeyboardHeight: 0, 'diary.comment_count': (this.data.diary.comment_count || 0) + 1 }); wx.hideKeyboard(); wx.showToast({ title: '评论成功', icon: 'success' }); } } catch (e) { wx.showToast({ title: e.error || '评论失败', icon: 'none' }); } finally { this.setData({ commentSending: false }); } }, onCommentLongPress: function(e) { var item = e.currentTarget.dataset.item; if (item.user_id != this.data.myUid) return; var self = this; wx.showModal({ title: '删除评论', content: '确定要删除这条评论吗?', success: async function(res) { if (res.confirm) { try { await api.diaryCommentDelete({ id: item.id }); var list = self.data.comments.filter(function(c) { return c.id != item.id; }); self.setData({ comments: list, 'diary.comment_count': Math.max(0, (self.data.diary.comment_count || 0) - 1) }); wx.showToast({ title: '已删除', icon: 'success' }); } catch (e) { wx.showToast({ title: '删除失败', icon: 'none' }); } } } }); }, onMoreTap: function() { var self = this; wx.showActionSheet({ itemList: ['编辑', '删除'], success: function(res) { if (res.tapIndex === 0) { wx.navigateTo({ url: '/pages/diary_edit/diary_edit?id=' + self.data.diaryId }); } else if (res.tapIndex === 1) { self._deleteDiary(); } } }); }, _deleteDiary: function() { var self = this; wx.showModal({ title: '删除日记', content: '确定要删除这篇日记吗?', success: async function(res) { if (res.confirm) { try { await api.diaryDelete({ id: self.data.diaryId }); wx.showToast({ title: '已删除', icon: 'success' }); setTimeout(function() { wx.navigateBack(); }, 1500); } catch (e) { wx.showToast({ title: e.error || '删除失败', icon: 'none' }); } } } }); }, goBack: function() { wx.navigateBack(); }, goHome: function() { wx.switchTab({ url: '/pages/index/index' }); } }, {"loadDiary": ["diaryDetail"], "loadComments": ["diaryCommentList"]}));