docx.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. from flask import Blueprint, render_template, abort, redirect, url_for, flash, make_response, g, request
  2. from flask_wtf import FlaskForm
  3. from flask_login import login_required, current_user
  4. from wtforms import TextAreaField, StringField, SelectMultipleField, SubmitField, ValidationError
  5. from wtforms.validators import DataRequired, Length
  6. import app
  7. from sql.base import DBBit
  8. from object.blog import BlogArticle, load_blog_by_id
  9. from object.comment import Comment
  10. from object.archive import load_archive_by_id, Archive
  11. docx = Blueprint("docx", __name__)
  12. class WriteBlogForm(FlaskForm):
  13. title = StringField("标题", description="博文主标题",
  14. validators=[
  15. DataRequired(message="必须填写标题"),
  16. Length(1, 20, message="标题长度1-20个字符")])
  17. subtitle = StringField("副标题", description="博文副标题",
  18. validators=[Length(-1, 20, message="副标题长度20个字符以内")])
  19. archive = SelectMultipleField("归档", coerce=int)
  20. context = TextAreaField("博客内容", validators=[DataRequired()])
  21. submit = SubmitField("提交博客")
  22. def __init__(self, **kwargs):
  23. super().__init__(**kwargs)
  24. self.context.data = "# Blog Title\n## Blog subtitle\nHello, World"
  25. archive = Archive.get_archive_list()
  26. self.archive_res = []
  27. self.archive_choices = [(-1, "None")]
  28. for i in archive:
  29. self.archive_res.append(i[0])
  30. self.archive_choices.append((i[0], f"{i[1]} ({i[3]})"))
  31. self.archive.choices = self.archive_choices
  32. def validate_archive(self, field):
  33. if -1 in field.data:
  34. if len(field.data) != 1:
  35. raise ValidationError("归档指定错误(none归档不能和其他归档同时被指定)")
  36. else:
  37. for i in field.data:
  38. if i not in self.archive_res:
  39. raise ValidationError("错误的归档被指定")
  40. class WriteCommentForm(FlaskForm):
  41. context = TextAreaField("", description="评论正文",
  42. validators=[DataRequired(message="请输入评论的内容"),
  43. Length(1, 100, message="请输入1-100个字的评论")])
  44. submit = SubmitField("评论")
  45. def __load_docx_page(page: int, form: WriteBlogForm):
  46. if page < 1:
  47. app.HBlogFlask.print_user_opt_fail_log(f"Load docx list with error page({page})")
  48. abort(404)
  49. return
  50. blog_list = BlogArticle.get_blog_list(limit=20, offset=(page - 1) * 20)
  51. max_page = app.HBlogFlask.get_max_page(BlogArticle.get_blog_count(), 20)
  52. page_list = app.HBlogFlask.get_page("docx.docx_page", page, max_page)
  53. app.HBlogFlask.print_load_page_log(f"docx list (page: {page})")
  54. return render_template("docx/docx.html",
  55. page=page,
  56. blog_list=blog_list,
  57. is_top=DBBit.BIT_1,
  58. page_list=page_list,
  59. form=form,
  60. show_delete=current_user.check_role("DeleteBlog"))
  61. @docx.route('/<int:page>')
  62. def docx_page(page: int = 1):
  63. return __load_docx_page(page, WriteBlogForm())
  64. @docx.route('/<int:archive>/<int:page>')
  65. def archive_page(archive: int, page: int = 1):
  66. if page < 1:
  67. app.HBlogFlask.print_user_opt_fail_log(f"Load archive-docx list with error page({page}) archive: {archive}")
  68. abort(404)
  69. return
  70. blog_list = BlogArticle.get_blog_list(archive_id=archive, limit=20, offset=(page - 1) * 20)
  71. max_page = app.HBlogFlask.get_max_page(BlogArticle.get_blog_count(archive_id=archive), 20)
  72. page_list = app.HBlogFlask.get_page("docx.archive_page", page, max_page)
  73. app.HBlogFlask.print_load_page_log(f"archive-docx list (archive-id: {archive} page: {page})")
  74. return render_template("docx/docx.html",
  75. blog_list=blog_list,
  76. is_top=DBBit.BIT_1,
  77. page_list=page_list,
  78. form=None)
  79. def __load_article_page(blog_id: int, form: WriteCommentForm):
  80. article = load_blog_by_id(blog_id)
  81. if article is None:
  82. app.HBlogFlask.print_user_opt_fail_log(f"Load article with error id({blog_id})")
  83. abort(404)
  84. return
  85. app.HBlogFlask.print_load_page_log(f"article (id: {blog_id})")
  86. return render_template("docx/article.html",
  87. article=article,
  88. archive_list=article.archive,
  89. form=form,
  90. show_delete=current_user.check_role("DeleteComment"),
  91. show_email=current_user.check_role("ReadUserInfo"))
  92. @docx.route('/article/<int:blog_id>')
  93. def article_page(blog_id: int):
  94. return __load_article_page(blog_id, WriteCommentForm())
  95. @docx.route('/down/<int:blog_id>')
  96. def article_down_page(blog_id: int):
  97. article = load_blog_by_id(blog_id)
  98. if article is None:
  99. app.HBlogFlask.print_user_opt_fail_log(f"Download article with error id({blog_id})")
  100. abort(404)
  101. return
  102. response = make_response(article.context)
  103. response.headers["Content-Disposition"] = f"attachment;filename={article.title.encode().decode('latin-1')}.md"
  104. app.HBlogFlask.print_load_page_log(f"download article (id: {blog_id})")
  105. return response
  106. @docx.route('/comment/<int:blog_id>', methods=["POST"])
  107. @login_required
  108. @app.form_required(WriteCommentForm, "write comment", __load_article_page)
  109. @app.role_required("WriteComment", "write comment")
  110. def comment_page(blog_id: int):
  111. form: WriteCommentForm = g.form
  112. context = form.context.data
  113. if Comment(None, blog_id, current_user, context).create():
  114. app.HBlogFlask.print_user_opt_success_log("comment")
  115. flash("评论成功")
  116. else:
  117. app.HBlogFlask.print_user_opt_error_log("comment")
  118. flash("评论失败")
  119. return redirect(url_for("docx.article_page", blog_id=blog_id))
  120. @docx.route('/create-docx', methods=["POST"])
  121. @login_required
  122. @app.form_required(WriteBlogForm, "write blog", lambda form: __load_docx_page(int(request.args.get("page", 1)), form))
  123. @app.role_required("WriteBlog", "write blog")
  124. def create_docx_page():
  125. form: WriteBlogForm = g.form
  126. title = form.title.data
  127. subtitle = form.subtitle.data
  128. archive = []
  129. if -1 not in form.archive.data:
  130. for i in form.archive.data:
  131. i = load_archive_by_id(i)
  132. if i is not None:
  133. archive.append(i)
  134. if BlogArticle(None, current_user, title, subtitle, form.context.data, archive=archive).create():
  135. app.HBlogFlask.print_sys_opt_success_log("write blog")
  136. flash(f"博客 {title} 发表成功")
  137. else:
  138. app.HBlogFlask.print_sys_opt_fail_log("write blog")
  139. flash(f"博客 {title} 发表失败")
  140. return redirect(url_for("docx.docx_page", page=1))
  141. @docx.route("delete/<int:blog_id>")
  142. @login_required
  143. @app.role_required("DeleteBlog", "delete blog")
  144. def delete_blog_page(blog_id: int):
  145. if BlogArticle(blog_id, None, None, None, None).delete():
  146. app.HBlogFlask.print_sys_opt_success_log("delete blog")
  147. flash("博文删除成功")
  148. else:
  149. app.HBlogFlask.print_sys_opt_fail_log("delete blog")
  150. flash("博文删除失败")
  151. return redirect(url_for("docx.docx_page", page=1))
  152. @docx.route("delete_comment/<int:comment_id>")
  153. @login_required
  154. @app.role_required("DeleteComment", "delete comment")
  155. def delete_comment_page(comment_id: int):
  156. if Comment(comment_id, None, None, None).delete():
  157. app.HBlogFlask.print_sys_opt_success_log("delete comment")
  158. flash("博文评论成功")
  159. else:
  160. app.HBlogFlask.print_sys_opt_fail_log("delete comment")
  161. flash("博文评论失败")
  162. return redirect(url_for("docx.docx_page", page=1))
  163. @docx.context_processor
  164. def inject_base():
  165. return {"top_nav": ["", "", "active", "", "", ""]}