270 lines
7.0 KiB
JavaScript
270 lines
7.0 KiB
JavaScript
const { del, get, post } = require("../../utils/api");
|
||
const { showError } = require("../../utils/page-helpers");
|
||
|
||
function initialOf(name) {
|
||
return String(name || "班").slice(0, 1);
|
||
}
|
||
|
||
function formatTime(value) {
|
||
return String(value || "").replace("T", " ").slice(0, 16);
|
||
}
|
||
|
||
function sameId(left, right) {
|
||
return Number(left) === Number(right);
|
||
}
|
||
|
||
function datasetBoolean(value) {
|
||
return value === true || value === "true" || value === 1 || value === "1";
|
||
}
|
||
|
||
function normalizePost(post, currentUserId = null) {
|
||
if (!post) return null;
|
||
const comments = Array.isArray(post.comments) ? post.comments : [];
|
||
return {
|
||
...post,
|
||
author_initial: initialOf(post.author_name),
|
||
created_at_text: formatTime(post.created_at),
|
||
like_action_text: post.has_liked ? "已赞" : "赞",
|
||
like_action_class: post.has_liked ? "active" : "",
|
||
comments: comments.map((comment) => ({
|
||
...comment,
|
||
created_at_text: formatTime(comment.created_at),
|
||
can_delete: sameId(currentUserId, comment.author_id)
|
||
}))
|
||
};
|
||
}
|
||
|
||
Page({
|
||
data: {
|
||
id: null,
|
||
post: null,
|
||
canDelete: false,
|
||
commentText: "",
|
||
replyToName: "",
|
||
inputPlaceholder: "写评论",
|
||
inputFocus: false,
|
||
keyboardOpen: false,
|
||
loading: false,
|
||
submitting: false
|
||
},
|
||
|
||
onLoad(options) {
|
||
wx.setNavigationBarTitle({ title: "班级圈" });
|
||
this.setData({ id: options.id });
|
||
this.load();
|
||
},
|
||
|
||
async onPullDownRefresh() {
|
||
await this.load();
|
||
wx.stopPullDownRefresh();
|
||
},
|
||
|
||
async load() {
|
||
if (!this.data.id) return;
|
||
this.setData({ loading: true });
|
||
try {
|
||
const postDetail = await get(`/api/timeline/${this.data.id}`);
|
||
const currentUser = getApp().globalData.user || wx.getStorageSync("auth_user") || {};
|
||
this.setData({
|
||
post: normalizePost(postDetail, currentUser.id),
|
||
canDelete: postDetail.author_id === currentUser.id
|
||
});
|
||
} catch (error) {
|
||
showError(error, "加载动态失败");
|
||
} finally {
|
||
this.setData({ loading: false });
|
||
}
|
||
},
|
||
|
||
async toggleLike() {
|
||
if (!this.data.id || this.data.submitting) return;
|
||
this.setData({ submitting: true });
|
||
try {
|
||
const result = await post(`/api/timeline/${this.data.id}/like`);
|
||
this.setData({
|
||
post: normalizePost({
|
||
...this.data.post,
|
||
has_liked: Boolean(result.liked),
|
||
like_count: Number(result.like_count || 0)
|
||
}, (getApp().globalData.user || wx.getStorageSync("auth_user") || {}).id)
|
||
});
|
||
} catch (error) {
|
||
showError(error, "操作失败");
|
||
} finally {
|
||
this.setData({ submitting: false });
|
||
}
|
||
},
|
||
|
||
onCommentInput(event) {
|
||
this.setData({ commentText: event.detail.value });
|
||
},
|
||
|
||
onCommentFocus(event) {
|
||
const height = event.detail.height || 0;
|
||
this.setData({
|
||
keyboardOpen: height > 0,
|
||
inputFocus: true
|
||
});
|
||
},
|
||
|
||
onKeyboardHeightChange(event) {
|
||
const height = event.detail.height || 0;
|
||
this.setData({ keyboardOpen: height > 0 });
|
||
},
|
||
|
||
onCommentBlur() {
|
||
this.setData({
|
||
keyboardOpen: false,
|
||
inputFocus: false
|
||
});
|
||
},
|
||
|
||
previewImage(event) {
|
||
const current = event.currentTarget.dataset.src;
|
||
const urls = this.data.post && this.data.post.image_urls ? this.data.post.image_urls : [];
|
||
if (!current || !urls.length) return;
|
||
wx.previewImage({ current, urls });
|
||
},
|
||
|
||
openActions() {
|
||
wx.showActionSheet({
|
||
itemList: ["删除动态"],
|
||
itemColor: "#b42318",
|
||
success: () => {
|
||
wx.showModal({
|
||
title: "删除动态",
|
||
content: "删除后无法恢复,确认删除这条动态?",
|
||
confirmText: "删除",
|
||
confirmColor: "#b42318",
|
||
success: async (res) => {
|
||
if (!res.confirm) return;
|
||
try {
|
||
await del(`/api/timeline/${this.data.id}`);
|
||
wx.showToast({ title: "已删除", icon: "success" });
|
||
const pages = getCurrentPages();
|
||
const previousPage = pages[pages.length - 2];
|
||
if (previousPage && previousPage.load) previousPage.load();
|
||
setTimeout(() => wx.navigateBack(), 500);
|
||
} catch (error) {
|
||
showError(error, "删除失败");
|
||
}
|
||
}
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
openComment() {
|
||
const post = this.data.post;
|
||
this.setData({
|
||
replyToName: "",
|
||
inputPlaceholder: post ? `评论 ${post.author_name}` : "写评论",
|
||
inputFocus: false
|
||
}, () => {
|
||
this.focusCommentInput();
|
||
});
|
||
},
|
||
|
||
replyComment(event) {
|
||
const commentId = Number(event.currentTarget.dataset.commentId);
|
||
const name = event.currentTarget.dataset.name || "";
|
||
const canDelete = datasetBoolean(event.currentTarget.dataset.canDelete);
|
||
if (canDelete && commentId) {
|
||
this.openOwnCommentActions(commentId, name);
|
||
return;
|
||
}
|
||
this.startReply(name);
|
||
},
|
||
|
||
startReply(name) {
|
||
this.setData({
|
||
replyToName: name,
|
||
inputPlaceholder: name ? `回复 ${name}` : "写评论",
|
||
inputFocus: false
|
||
}, () => {
|
||
this.focusCommentInput();
|
||
});
|
||
},
|
||
|
||
cancelReply() {
|
||
this.setData({
|
||
replyToName: "",
|
||
inputPlaceholder: "写评论",
|
||
inputFocus: false,
|
||
keyboardOpen: false
|
||
});
|
||
},
|
||
|
||
focusCommentInput() {
|
||
const focus = () => {
|
||
if (this.data.post) {
|
||
this.setData({ inputFocus: true });
|
||
}
|
||
};
|
||
if (wx.nextTick) {
|
||
wx.nextTick(() => setTimeout(focus, 120));
|
||
return;
|
||
}
|
||
setTimeout(focus, 120);
|
||
},
|
||
|
||
async submitComment() {
|
||
const text = this.data.commentText.trim();
|
||
if (!text) {
|
||
wx.showToast({ title: "请输入评论", icon: "none" });
|
||
return;
|
||
}
|
||
const content = this.data.replyToName ? `回复 @${this.data.replyToName}:${text}` : text;
|
||
this.setData({ submitting: true });
|
||
try {
|
||
await post(`/api/timeline/${this.data.id}/comments`, { content });
|
||
this.setData({
|
||
commentText: "",
|
||
replyToName: "",
|
||
inputPlaceholder: "写评论",
|
||
inputFocus: false,
|
||
keyboardOpen: false
|
||
});
|
||
await this.load();
|
||
} catch (error) {
|
||
showError(error, "评论失败");
|
||
} finally {
|
||
this.setData({ submitting: false });
|
||
}
|
||
},
|
||
|
||
deleteComment(commentId) {
|
||
wx.showModal({
|
||
title: "删除评论",
|
||
content: "确认删除这条评论?",
|
||
confirmText: "删除",
|
||
confirmColor: "#b42318",
|
||
success: async (res) => {
|
||
if (!res.confirm) return;
|
||
try {
|
||
await del(`/api/timeline/comments/${commentId}`);
|
||
await this.load();
|
||
wx.showToast({ title: "已删除", icon: "success" });
|
||
} catch (error) {
|
||
showError(error, "删除失败");
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
openOwnCommentActions(commentId, name) {
|
||
wx.showActionSheet({
|
||
itemList: ["回复", "删除评论"],
|
||
itemColor: "#6b1f2b",
|
||
success: (res) => {
|
||
if (res.tapIndex === 0) {
|
||
this.startReply(name);
|
||
}
|
||
if (res.tapIndex === 1) {
|
||
this.deleteComment(commentId);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
});
|