Add hashtag cascade relations
This commit is contained in:
50
back/main.py
50
back/main.py
@@ -53,23 +53,35 @@ class Submission(db.Model):
|
|||||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
content = db.Column(db.Text, nullable=False)
|
content = db.Column(db.Text, nullable=False)
|
||||||
identity_token = db.Column(db.String(36), nullable=True)
|
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)
|
created_at = db.Column(db.DateTime, default=now_time)
|
||||||
updated_at = db.Column(db.DateTime, default=now_time, onupdate=now_time)
|
updated_at = db.Column(db.DateTime, default=now_time, onupdate=now_time)
|
||||||
upvotes = db.Column(db.Integer, default=0)
|
upvotes = db.Column(db.Integer, default=0)
|
||||||
downvotes = 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')
|
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):
|
class Comment(db.Model):
|
||||||
__tablename__ = 'comments'
|
__tablename__ = 'comments'
|
||||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
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='匿名用户')
|
nickname = db.Column(db.String(50), default='匿名用户')
|
||||||
content = db.Column(db.Text, nullable=False)
|
content = db.Column(db.Text, nullable=False)
|
||||||
identity_token = db.Column(db.String(36), nullable=True)
|
identity_token = db.Column(db.String(36), nullable=True)
|
||||||
created_at = db.Column(db.DateTime, default=now_time)
|
created_at = db.Column(db.DateTime, default=now_time)
|
||||||
parent_comment_id = db.Column(db.Integer, db.ForeignKey('comments.id'), nullable=True)
|
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):
|
class Report(db.Model):
|
||||||
__tablename__ = 'reports'
|
__tablename__ = 'reports'
|
||||||
@@ -711,10 +723,38 @@ def get_post_info():
|
|||||||
@app.route('/api/hot_topics', methods=['GET'])
|
@app.route('/api/hot_topics', methods=['GET'])
|
||||||
def get_hot_topics():
|
def get_hot_topics():
|
||||||
try:
|
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(
|
rows = db.session.query(
|
||||||
Hashtag.name,
|
union_subq.c.name,
|
||||||
db.func.count(Hashtag.name).label('count')
|
db.func.count(union_subq.c.name).label('count')
|
||||||
).group_by(Hashtag.name).order_by(db.func.count(Hashtag.name).desc()).limit(3).all()
|
).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]
|
data = [{"name": name, "count": int(count)} for name, count in rows]
|
||||||
return jsonify({"code": 1000, "data": {"list": data}})
|
return jsonify({"code": 1000, "data": {"list": data}})
|
||||||
|
|||||||
@@ -261,10 +261,14 @@ useEffect(() => {
|
|||||||
const diffHours = Math.floor(diffMs / 3600000);
|
const diffHours = Math.floor(diffMs / 3600000);
|
||||||
const sameDay = now.toDateString() === date.toDateString();
|
const sameDay = now.toDateString() === date.toDateString();
|
||||||
if (sameDay) return `${diffHours}小时前`;
|
if (sameDay) return `${diffHours}小时前`;
|
||||||
const diffDays = Math.floor(diffMs / 86400000);
|
const todayMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
|
||||||
const diffMonths = Math.floor(diffDays / 30);
|
const dateMidnight = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
|
||||||
if (diffMonths >= 1 && diffMonths < 12) return `${diffMonths}个月前`;
|
const diffDays = Math.max(1, Math.floor((todayMidnight - dateMidnight) / 86400000));
|
||||||
if (diffDays >= 1 && diffMonths < 1) return `${diffDays}天前`;
|
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 yyyy = date.getFullYear();
|
||||||
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
const dd = String(date.getDate()).padStart(2, '0');
|
const dd = String(date.getDate()).padStart(2, '0');
|
||||||
@@ -293,13 +297,12 @@ useEffect(() => {
|
|||||||
a: ({ node, ...props }) => {
|
a: ({ node, ...props }) => {
|
||||||
const href = props.href;
|
const href = props.href;
|
||||||
if (href && typeof href === 'string' && href.startsWith('/tag/#')) {
|
if (href && typeof href === 'string' && href.startsWith('/tag/#')) {
|
||||||
const hash = href.slice('/tag/'.length);
|
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
{...props}
|
{...props}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
navigate({ pathname: '/tag', hash });
|
navigate(href);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -252,10 +252,14 @@ const PostCard = ({
|
|||||||
const diffHours = Math.floor(diffMs / 3600000);
|
const diffHours = Math.floor(diffMs / 3600000);
|
||||||
const sameDay = now.toDateString() === date.toDateString();
|
const sameDay = now.toDateString() === date.toDateString();
|
||||||
if (sameDay) return `${diffHours}小时前`;
|
if (sameDay) return `${diffHours}小时前`;
|
||||||
const diffDays = Math.floor(diffMs / 86400000);
|
const todayMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
|
||||||
const diffMonths = Math.floor(diffDays / 30);
|
const dateMidnight = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
|
||||||
if (diffMonths >= 1 && diffMonths < 12) return `${diffMonths}个月前`;
|
const diffDays = Math.max(1, Math.floor((todayMidnight - dateMidnight) / 86400000));
|
||||||
if (diffDays >= 1 && diffMonths < 1) return `${diffDays}天前`;
|
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 yyyy = date.getFullYear();
|
||||||
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
const dd = String(date.getDate()).padStart(2, '0');
|
const dd = String(date.getDate()).padStart(2, '0');
|
||||||
@@ -275,13 +279,12 @@ const PostCard = ({
|
|||||||
a: ({ node, ...props }) => {
|
a: ({ node, ...props }) => {
|
||||||
const href = props.href;
|
const href = props.href;
|
||||||
if (href && typeof href === 'string' && href.startsWith('/tag/#')) {
|
if (href && typeof href === 'string' && href.startsWith('/tag/#')) {
|
||||||
const hash = href.slice('/tag/'.length);
|
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
{...props}
|
{...props}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
navigate({ pathname: '/tag', hash });
|
navigate(href);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user