docx.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. from flask import Flask, Blueprint, render_template, abort, redirect, url_for, flash, make_response
  2. from flask_wtf import FlaskForm
  3. from flask_pagedown.fields import PageDownField
  4. from flask_login import login_required, current_user
  5. from wtforms import TextAreaField, StringField, SubmitField
  6. from wtforms.validators import DataRequired, Length
  7. import bleach
  8. from markdown import markdown
  9. import app
  10. from sql.base import DBBit
  11. from object.blog import BlogArticle, load_blog_by_id
  12. from object.user import User
  13. from object.comment import Comment
  14. from object.archive import load_archive_by_name
  15. docx = Blueprint("docx", __name__)
  16. allow_tag = ['a', 'abbr', 'acronym', 'b', 'br', 'blockquote', 'code', 'em', 'i', 'li', 'ol', 'pre', 'strong', 'small',
  17. 'ul', 'h1', 'h2', 'h3', 'h4', 'h5' 'h6', 'p']
  18. class WriteBlogForm(FlaskForm):
  19. title = StringField("标题", validators=[DataRequired(), Length(1, 10)])
  20. subtitle = StringField("副标题", validators=[DataRequired(), Length(1, 10)])
  21. archive = StringField("归档", validators=[DataRequired(), Length(1, 10)])
  22. context = PageDownField("博客内容", validators=[DataRequired()])
  23. submit = SubmitField("提交博客")
  24. class WriteCommentForm(FlaskForm):
  25. context = TextAreaField(validators=[DataRequired()])
  26. submit = SubmitField("评论")
  27. @docx.route('/<int:page>')
  28. def docx_page(page: int = 1):
  29. if page < 1:
  30. app.HBlogFlask.print_user_opt_fail_log(f"Load docx list with error page({page})")
  31. abort(404)
  32. return
  33. blog_list = BlogArticle.get_blog_list(limit=20, offset=(page - 1) * 20)
  34. max_page = app.HBlogFlask.get_max_page(BlogArticle.get_blog_count(), 20)
  35. page_list = app.HBlogFlask.get_page("docx.docx_page", page, max_page)
  36. app.HBlogFlask.print_load_page_log(f"docx list (page: {page})")
  37. return render_template("docx/docx.html",
  38. blog_list=blog_list,
  39. is_top=DBBit.BIT_1,
  40. page_list=page_list,
  41. form=WriteBlogForm(),
  42. show_delete=current_user.check_role("DeleteBlog"))
  43. @docx.route('/<int:archive>/<int:page>')
  44. def archive_page(archive: int, page: int = 1):
  45. if page < 1:
  46. app.HBlogFlask.print_user_opt_fail_log(f"Load archive-docx list with error page({page}) archive: {archive}")
  47. abort(404)
  48. return
  49. blog_list = BlogArticle.get_blog_list(archive_id=archive, limit=20, offset=(page - 1) * 20)
  50. max_page = app.HBlogFlask.get_max_page(BlogArticle.get_blog_count(archive_id=archive), 20)
  51. page_list = app.HBlogFlask.get_page("docx.archive_page", page, max_page)
  52. app.HBlogFlask.print_load_page_log(f"archive-docx list (archive-id: {archive} page: {page})")
  53. return render_template("docx/docx.html",
  54. blog_list=blog_list,
  55. is_top=DBBit.BIT_1,
  56. page_list=page_list,
  57. form=None)
  58. @docx.route('/article/<int:blog_id>')
  59. def article_page(blog_id: int):
  60. article = load_blog_by_id(blog_id)
  61. if article is None:
  62. app.HBlogFlask.print_user_opt_fail_log(f"Load article with error id({blog_id})")
  63. abort(404)
  64. return
  65. app.HBlogFlask.print_load_page_log(f"article (id: {blog_id})")
  66. return render_template("docx/article.html",
  67. article=article,
  68. archive_list=article.archive,
  69. form=WriteCommentForm(),
  70. show_delete=current_user.check_role("DeleteComment"),
  71. show_email=current_user.check_role("ReadUserInfo"))
  72. @docx.route('/down/<int:blog_id>')
  73. def article_down_page(blog_id: int):
  74. article = load_blog_by_id(blog_id)
  75. if article is None:
  76. app.HBlogFlask.print_user_opt_fail_log(f"Download article with error id({blog_id})")
  77. abort(404)
  78. return
  79. response = make_response(article.context)
  80. response.headers["Content-Disposition"] = f"attachment;filename={article.title.encode().decode('latin-1')}.html"
  81. app.HBlogFlask.print_load_page_log(f"download article (id: {blog_id})")
  82. return response
  83. @docx.route('/comment/<int:blog>', methods=["POST"])
  84. @login_required
  85. def comment_page(blog: int):
  86. form = WriteCommentForm()
  87. if form.validate_on_submit():
  88. auth: User = current_user
  89. if not auth.check_role("WriteComment"): # 检查是否具有权限
  90. app.HBlogFlask.print_user_not_allow_opt_log("comment")
  91. abort(403)
  92. return
  93. context = form.context.data
  94. if Comment(None, blog, auth, context).create():
  95. app.HBlogFlask.print_user_opt_success_log("comment")
  96. flash("评论成功")
  97. else:
  98. app.HBlogFlask.print_user_opt_error_log("comment")
  99. flash("评论失败")
  100. return redirect(url_for("docx.article_page", blog_id=blog))
  101. app.HBlogFlask.print_form_error_log("comment")
  102. abort(404)
  103. @docx.route('/create-docx', methods=["POST"])
  104. @login_required
  105. def create_docx_page():
  106. form = WriteBlogForm()
  107. if form.validate_on_submit():
  108. auth: User = current_user
  109. if not auth.check_role("WriteBlog"): # 检查是否具有写入权限
  110. app.HBlogFlask.print_user_not_allow_opt_log("write blog")
  111. abort(403)
  112. return
  113. title = form.title.data
  114. subtitle = form.subtitle.data
  115. archive = set(str(form.archive.data).replace(" ", "").split(";"))
  116. archive_list = []
  117. for f in archive:
  118. f_ = load_archive_by_name(f)
  119. if f_ is not None:
  120. archive_list.append(f_)
  121. context = bleach.linkify(
  122. bleach.clean(
  123. markdown(form.context.data, output_format='html'), tags=allow_tag, strip=True))
  124. if BlogArticle(None, current_user, title, subtitle, context, archive=archive_list).create():
  125. app.HBlogFlask.print_sys_opt_success_log("write blog")
  126. flash(f"博客 {title} 发表成功")
  127. else:
  128. app.HBlogFlask.print_sys_opt_fail_log("write blog")
  129. flash(f"博客 {title} 发表失败")
  130. return redirect(url_for("docx.docx_page", page=1))
  131. app.HBlogFlask.print_form_error_log("write blog")
  132. abort(404)
  133. @docx.route("delete/<int:blog_id>")
  134. @login_required
  135. def delete_blog_page(blog_id: int):
  136. if not current_user.check_role("DeleteBlog"):
  137. app.HBlogFlask.print_user_not_allow_opt_log("delete blog")
  138. abort(403)
  139. return
  140. if BlogArticle(blog_id, None, None, None, None).delete():
  141. app.HBlogFlask.print_sys_opt_success_log("delete blog")
  142. flash("博文删除成功")
  143. else:
  144. app.HBlogFlask.print_sys_opt_fail_log("delete blog")
  145. flash("博文删除失败")
  146. return redirect(url_for("docx.docx_page", page=1))
  147. @docx.route("delete_comment/<int:comment_id>")
  148. @login_required
  149. def delete_comment_page(comment_id: int):
  150. if not current_user.check_role("DeleteComment"):
  151. app.HBlogFlask.print_user_not_allow_opt_log("delete comment")
  152. abort(403)
  153. return
  154. if Comment(comment_id, None, None, None).delete():
  155. app.HBlogFlask.print_sys_opt_success_log("delete comment")
  156. flash("博文评论成功")
  157. else:
  158. app.HBlogFlask.print_sys_opt_fail_log("delete comment")
  159. flash("博文评论失败")
  160. return redirect(url_for("docx.docx_page", page=1))
  161. @docx.context_processor
  162. def inject_base():
  163. return {"top_nav": ["", "", "active", "", "", ""]}