diff --git a/back/main.py b/back/main.py index 62b58e9..d7db77e 100644 --- a/back/main.py +++ b/back/main.py @@ -53,23 +53,35 @@ class Submission(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) content = db.Column(db.Text, nullable=False) identity_token = db.Column(db.String(36), nullable=True) - status = db.Column(db.String(20), default='Pending') + status = db.Column(db.String(20), default='Pending', index=True) created_at = db.Column(db.DateTime, default=now_time) updated_at = db.Column(db.DateTime, default=now_time, onupdate=now_time) upvotes = db.Column(db.Integer, default=0) downvotes = db.Column(db.Integer, default=0) comments = db.relationship('Comment', backref='submission', lazy=True, cascade='all, delete-orphan') + hashtags = db.relationship( + 'Hashtag', + primaryjoin="and_(Hashtag.type==0, Hashtag.target_id==Submission.id)", + cascade='all, delete-orphan', + lazy=True + ) class Comment(db.Model): __tablename__ = 'comments' id = db.Column(db.Integer, primary_key=True, autoincrement=True) - submission_id = db.Column(db.Integer, db.ForeignKey('submissions.id'), nullable=False) + submission_id = db.Column(db.Integer, db.ForeignKey('submissions.id'), nullable=False, index=True) nickname = db.Column(db.String(50), default='匿名用户') content = db.Column(db.Text, nullable=False) identity_token = db.Column(db.String(36), nullable=True) created_at = db.Column(db.DateTime, default=now_time) parent_comment_id = db.Column(db.Integer, db.ForeignKey('comments.id'), nullable=True) + hashtags = db.relationship( + 'Hashtag', + primaryjoin="and_(Hashtag.type==1, Hashtag.target_id==Comment.id)", + cascade='all, delete-orphan', + lazy=True + ) class Report(db.Model): __tablename__ = 'reports' @@ -711,10 +723,38 @@ def get_post_info(): @app.route('/api/hot_topics', methods=['GET']) def get_hot_topics(): try: + submission_tags = db.session.query( + Hashtag.name.label('name') + ).join( + Submission, + db.and_(Hashtag.type == 0, Hashtag.target_id == Submission.id) + ).filter( + Submission.status == 'Pass' + ) + + comment_tags = db.session.query( + Hashtag.name.label('name') + ).join( + Comment, + db.and_(Hashtag.type == 1, Hashtag.target_id == Comment.id) + ).join( + Submission, + Comment.submission_id == Submission.id + ).filter( + Submission.status == 'Pass' + ) + + union_subq = submission_tags.union_all(comment_tags).subquery() + rows = db.session.query( - Hashtag.name, - db.func.count(Hashtag.name).label('count') - ).group_by(Hashtag.name).order_by(db.func.count(Hashtag.name).desc()).limit(3).all() + union_subq.c.name, + db.func.count(union_subq.c.name).label('count') + ).group_by( + union_subq.c.name + ).order_by( + db.func.count(union_subq.c.name).desc(), + union_subq.c.name.asc() + ).limit(3).all() data = [{"name": name, "count": int(count)} for name, count in rows] return jsonify({"code": 1000, "data": {"list": data}}) diff --git a/front/src/components/CommentSection.tsx b/front/src/components/CommentSection.tsx index a424a54..9abb8c3 100644 --- a/front/src/components/CommentSection.tsx +++ b/front/src/components/CommentSection.tsx @@ -261,10 +261,14 @@ useEffect(() => { const diffHours = Math.floor(diffMs / 3600000); const sameDay = now.toDateString() === date.toDateString(); if (sameDay) return `${diffHours}小时前`; - const diffDays = Math.floor(diffMs / 86400000); - const diffMonths = Math.floor(diffDays / 30); - if (diffMonths >= 1 && diffMonths < 12) return `${diffMonths}个月前`; - if (diffDays >= 1 && diffMonths < 1) return `${diffDays}天前`; + const todayMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime(); + const dateMidnight = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime(); + const diffDays = Math.max(1, Math.floor((todayMidnight - dateMidnight) / 86400000)); + if (diffDays < 30) return `${diffDays}天前`; + let diffMonths = (now.getFullYear() * 12 + now.getMonth()) - (date.getFullYear() * 12 + date.getMonth()); + if (now.getDate() < date.getDate()) diffMonths -= 1; + if (diffMonths < 1) diffMonths = 1; + if (diffMonths < 12) return `${diffMonths}个月前`; const yyyy = date.getFullYear(); const mm = String(date.getMonth() + 1).padStart(2, '0'); const dd = String(date.getDate()).padStart(2, '0'); @@ -293,13 +297,12 @@ useEffect(() => { a: ({ node, ...props }) => { const href = props.href; if (href && typeof href === 'string' && href.startsWith('/tag/#')) { - const hash = href.slice('/tag/'.length); return ( { e.preventDefault(); - navigate({ pathname: '/tag', hash }); + navigate(href); }} /> ); diff --git a/front/src/components/PostCard.tsx b/front/src/components/PostCard.tsx index e79ad1f..4e53e12 100644 --- a/front/src/components/PostCard.tsx +++ b/front/src/components/PostCard.tsx @@ -252,10 +252,14 @@ const PostCard = ({ const diffHours = Math.floor(diffMs / 3600000); const sameDay = now.toDateString() === date.toDateString(); if (sameDay) return `${diffHours}小时前`; - const diffDays = Math.floor(diffMs / 86400000); - const diffMonths = Math.floor(diffDays / 30); - if (diffMonths >= 1 && diffMonths < 12) return `${diffMonths}个月前`; - if (diffDays >= 1 && diffMonths < 1) return `${diffDays}天前`; + const todayMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime(); + const dateMidnight = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime(); + const diffDays = Math.max(1, Math.floor((todayMidnight - dateMidnight) / 86400000)); + if (diffDays < 30) return `${diffDays}天前`; + let diffMonths = (now.getFullYear() * 12 + now.getMonth()) - (date.getFullYear() * 12 + date.getMonth()); + if (now.getDate() < date.getDate()) diffMonths -= 1; + if (diffMonths < 1) diffMonths = 1; + if (diffMonths < 12) return `${diffMonths}个月前`; const yyyy = date.getFullYear(); const mm = String(date.getMonth() + 1).padStart(2, '0'); const dd = String(date.getDate()).padStart(2, '0'); @@ -275,13 +279,12 @@ const PostCard = ({ a: ({ node, ...props }) => { const href = props.href; if (href && typeof href === 'string' && href.startsWith('/tag/#')) { - const hash = href.slice('/tag/'.length); return ( { e.preventDefault(); - navigate({ pathname: '/tag', hash }); + navigate(href); }} /> );