mirror of
https://github.com/Kakune55/ComiPy.git
synced 2025-05-06 18:29:26 +08:00
feat:添加评论上传功能 未完全完成
This commit is contained in:
parent
b5c58e1216
commit
c8bae04145
76
db/comments.py
Normal file
76
db/comments.py
Normal file
@ -0,0 +1,76 @@
|
||||
import time
|
||||
import db.util as util
|
||||
|
||||
|
||||
# 查找评论
|
||||
def listByBookid(id: str):
|
||||
"通过bookid查找所有评论"
|
||||
conn = util.getConn()
|
||||
c = conn.cursor()
|
||||
cursor = c.execute("SELECT * FROM Comments WHERE bookid = ? ORDER BY time desc", (id,))
|
||||
out = []
|
||||
for row in cursor:
|
||||
out.append(row)
|
||||
conn.close()
|
||||
return out
|
||||
|
||||
|
||||
# 获取综合评分
|
||||
def getScore(bookid: str):
|
||||
"获取综合评分 返回一个字典 字典有两个key like和dislike分别记录不同评论的个数"
|
||||
conn = util.getConn()
|
||||
c = conn.cursor()
|
||||
cursor = c.execute("SELECT * FROM Comments WHERE bookid = ? ", (bookid,))
|
||||
num={'like':0,'dislike':0}
|
||||
for row in cursor:
|
||||
if row[4] == "like":
|
||||
num["like"]+=1
|
||||
elif row[4] == "dislike":
|
||||
num["dislike"]+=1
|
||||
conn.close()
|
||||
return num
|
||||
|
||||
|
||||
# 查找评论
|
||||
def searchByUid(uid: str):
|
||||
"通过用户查找所有评论"
|
||||
conn = util.getConn()
|
||||
c = conn.cursor()
|
||||
cursor = c.execute("SELECT * FROM Comments WHERE from_uid = ? ORDER BY time desc", (uid,))
|
||||
out = []
|
||||
for row in cursor:
|
||||
out.append(row)
|
||||
conn.close()
|
||||
return out
|
||||
|
||||
|
||||
# 查找评论
|
||||
def searchByAll(uid: str,bookid:str):
|
||||
"通过用户和BookID查找所有评论"
|
||||
conn = util.getConn()
|
||||
c = conn.cursor()
|
||||
cursor = c.execute("SELECT * FROM Comments WHERE from_uid = ? AND bookid= ? ORDER BY time desc", (uid,bookid))
|
||||
out = []
|
||||
for row in cursor:
|
||||
out.append(row)
|
||||
conn.close()
|
||||
return out
|
||||
|
||||
|
||||
# 在数据库中添加一个新的文件记录
|
||||
def new(bookid: str, from_uid: int, score: str, content=""):
|
||||
"添加一条新评论 score字段可选值为[like,none,dislike] content字段非必填"
|
||||
conn = util.getConn()
|
||||
c = conn.cursor()
|
||||
c.execute(
|
||||
"""
|
||||
INSERT INTO Comments
|
||||
(time, bookid, from_uid, score, content)
|
||||
VALUES
|
||||
(?, ?, ?, ?,?);
|
||||
""",
|
||||
(int(time.time()), bookid, from_uid, score, content),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return
|
20
db/user.py
20
db/user.py
@ -33,3 +33,23 @@ def check(username: str, password: int):
|
||||
if cursor.fetchone() is None:
|
||||
return False
|
||||
return True
|
||||
|
||||
def getUid(username: str):
|
||||
"判断用户名是否存在 并获取用户uid 用户不存在则返回None"
|
||||
conn = util.getConn()
|
||||
c = conn.cursor()
|
||||
cursor = c.execute("SELECT * FROM User WHERE username = ?", (username,))
|
||||
out = cursor.fetchone()
|
||||
if out is not None:
|
||||
return out[0]
|
||||
return None
|
||||
|
||||
def getUsername(uid:str):
|
||||
"判断Uid是否存在 并获取用户名 用户不存在则返回None"
|
||||
conn = util.getConn()
|
||||
c = conn.cursor()
|
||||
cursor = c.execute("SELECT * FROM User WHERE uid = ?", (uid,))
|
||||
out = cursor.fetchone()
|
||||
if out is not None:
|
||||
return out[1]
|
||||
return None
|
24
db/util.py
24
db/util.py
@ -31,5 +31,29 @@ def init():
|
||||
);
|
||||
"""
|
||||
)
|
||||
c.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Comments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
time INT NOT NULL,
|
||||
bookid TEXT NOT NULL,
|
||||
from_uid INTEGAR NOT NULL,
|
||||
score INT NOT NULL,
|
||||
content TEXT
|
||||
);
|
||||
"""
|
||||
)
|
||||
c.execute(
|
||||
"""
|
||||
INSERT INTO User (username, password)
|
||||
SELECT ?, ?
|
||||
WHERE NOT EXISTS (SELECT 1 FROM User WHERE username = ?);
|
||||
""",
|
||||
(
|
||||
conf.get("user", "username"),
|
||||
conf.get("user", "password"),
|
||||
conf.get("user", "username"),
|
||||
),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
2
main.py
2
main.py
@ -6,6 +6,7 @@ from flask import *
|
||||
from web.api_Img import api_Img_bp
|
||||
from web.page import page_bp
|
||||
from web.admin_page import admin_page_bp
|
||||
from web.api_comment import comment_api_bp
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@ -20,6 +21,7 @@ def appinit():
|
||||
app.register_blueprint(api_Img_bp)
|
||||
app.register_blueprint(page_bp)
|
||||
app.register_blueprint(admin_page_bp)
|
||||
app.register_blueprint(comment_api_bp)
|
||||
|
||||
if __name__ == "__main__":
|
||||
appinit()
|
||||
|
5
static/js/popper.min.js
vendored
5
static/js/popper.min.js
vendored
File diff suppressed because one or more lines are too long
@ -72,6 +72,36 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="exampleModalLabel">评论</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="comment" action="/api/comment/upload" method="post">
|
||||
<select class="form-select" aria-label="Default select example" name="score">
|
||||
<option value="none">无评价</option>
|
||||
<option value="like">赞👍</option>
|
||||
<option value="dislike">踩👎</option>
|
||||
</select>
|
||||
<div class="input-group" style="margin-top: 10px;" >
|
||||
<span class="input-group-text">评论</span>
|
||||
<textarea class="form-control" name="text" aria-label="With textarea"></textarea>
|
||||
</div>
|
||||
<input type="hidden" name="bookid" value="{{data[0][1]}}"/>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary" onclick="commentSubmit()">提交</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="movie-poster">
|
||||
@ -81,24 +111,51 @@
|
||||
<div class="movie-details">
|
||||
<!-- 详细信息 -->
|
||||
<h1>{{ data[0][2] }}</h1>
|
||||
<h2>时间: {{time}}</h2>
|
||||
<h2>暂无评价</h2>
|
||||
<h3>更新时间: {{time}}</h3>
|
||||
<h2>👍{{socre["like"]}} 👎{{socre["dislike"]}}</h2>
|
||||
<button class="btn btn-primary" onclick="window.location.href='/view/{{ id }}'">在线浏览</button>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">撰写评论</button>
|
||||
<button class="btn btn-danger">删除资源</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="container">
|
||||
<div class="comments-section">
|
||||
<h2>评论区</h2>
|
||||
<!-- 评论 -->
|
||||
{% if not comments%}
|
||||
<p>暂无评论</p>
|
||||
{%endif%}
|
||||
{% for item in comments %}
|
||||
<div class="comment">
|
||||
<p>用户A:Lorem ipsum dolor sit amet consectetur adipisicing elit. Nobis, quam!</p>
|
||||
</div>
|
||||
<div class="comment">
|
||||
<p>用户B:Lorem, ipsum dolor sit amet consectetur adipisicing elit. Aut sunt tempore architecto minus, cum
|
||||
mollitia voluptatibus repellendus aliquid id reprehenderit.</p>
|
||||
<h3>{{item["from"]}}:
|
||||
{%if item["socre"] == "like"%}
|
||||
<small class="text-muted">觉得很赞👍</small>
|
||||
{%endif%}
|
||||
{%if item["socre"] == "dislike"%}
|
||||
<small class="text-muted">点了个踩👎</small>
|
||||
{%endif%}
|
||||
</h3>
|
||||
<h3>{{item["text"]}}</h3>
|
||||
<small class="text-muted">id:{{item["id"]}} {{item["time"]}}</small>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<!-- 在此添加更多评论 -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://unpkg.com/@popperjs/core@2"></script>
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
|
||||
<script>
|
||||
const comment = document.getElementById("comment")
|
||||
function commentSubmit(){
|
||||
comment.submit()
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -50,7 +50,7 @@
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
/* 模糊度可以根据需要调整 */
|
||||
transition: display;
|
||||
z-index: 1;
|
||||
z-index: 10;
|
||||
/* 保证遮罩在页面上方 */
|
||||
pointer-events: none;
|
||||
/* 确保遮罩不影响下方元素的交互 */
|
||||
@ -61,11 +61,21 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="display: flex;">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" id="search_text" placeholder="键入以搜索">
|
||||
<button class="btn btn-secondary" type="button"
|
||||
onclick="window.location.href='/overview/1?search='+document.getElementById('search_text').value">Search</button>
|
||||
</div>
|
||||
<div class="dropdown" style="margin-left: 10px;">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{username}}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item" href="#" onclick="logout()">Log out</button></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div id="gallery">
|
||||
{% for item in list %}
|
||||
@ -98,6 +108,9 @@
|
||||
|
||||
<div id="global-blur" onclick="unshow_global_blur()"></div>
|
||||
|
||||
<script src="https://unpkg.com/@popperjs/core@2"></script>
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
<script>
|
||||
function linkjump(url) {
|
||||
window.open("/book/" + url)
|
||||
@ -124,6 +137,11 @@
|
||||
global_blur.style.pointerEvents = "none";
|
||||
}
|
||||
|
||||
function logout() {
|
||||
document.cookie = "islogin=1; max-age=0"
|
||||
//location.href = "/";
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<script src="/static/js/popper.min.js"></script>
|
||||
<script src="https://unpkg.com/@popperjs/core@2"></script>
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
|
||||
<script>
|
||||
|
@ -58,7 +58,7 @@
|
||||
<img data-src="/api/img/{{ id }}/{{ i }}" loading="lazy" alt="{{ i }}" class="imgs">
|
||||
{% endfor %}
|
||||
<div style="display:flex;justify-content: center; align-items:center;">
|
||||
<img src="/static/loading.gif" id="loadingGIF">
|
||||
<h1>已经到底了哦</h1>
|
||||
</div>
|
||||
<div id="global-blur" onclick="unshow_global_blur()"></div>
|
||||
<script>
|
||||
|
@ -1,7 +1,8 @@
|
||||
from flask import *
|
||||
from flask import Blueprint
|
||||
import time
|
||||
import db.file, file , app_conf
|
||||
import db.user
|
||||
import db.file, file, app_conf
|
||||
|
||||
admin_page_bp = Blueprint("admin_page_bp", __name__)
|
||||
|
||||
@ -9,6 +10,7 @@ conf = app_conf.conf()
|
||||
|
||||
# 管理页
|
||||
|
||||
|
||||
@admin_page_bp.route("/", methods=["GET", "POST"])
|
||||
def login(): # 登录页面
|
||||
if request.method == "GET":
|
||||
@ -16,11 +18,10 @@ def login(): # 登录页面
|
||||
return redirect("/overview/1")
|
||||
return render_template("login.html")
|
||||
elif request.method == "POST":
|
||||
if request.form["username"] == conf.get("user", "username") and request.form[
|
||||
"password"
|
||||
] == conf.get("user", "password"):
|
||||
if db.user.check(request.form["username"], request.form["password"]):
|
||||
resp = make_response(redirect("/overview/1"))
|
||||
resp.set_cookie("islogin", "True")
|
||||
resp.set_cookie("islogin", request.form["username"])
|
||||
resp.set_cookie("uid", str(db.user.getUid(request.form["username"])))
|
||||
return resp
|
||||
else:
|
||||
return redirect("/")
|
27
web/api_comment.py
Normal file
27
web/api_comment.py
Normal file
@ -0,0 +1,27 @@
|
||||
from flask import *
|
||||
from flask import Blueprint
|
||||
import time
|
||||
import db.comments, db.file, app_conf
|
||||
|
||||
comment_api_bp = Blueprint("comment_api_bp", __name__)
|
||||
|
||||
conf = app_conf.conf()
|
||||
|
||||
|
||||
@comment_api_bp.route("/api/comment/upload", methods=["POST"])
|
||||
def comment_api(): # 概览
|
||||
if request.cookies.get("islogin") is None: # 验证登录状态
|
||||
return redirect("/")
|
||||
if request.form["score"] != "none" and request.form["text"].isspace():
|
||||
return "评论不能为空"
|
||||
if len(request.form["text"]) > 200:
|
||||
return "评论过长(需要小于200字)"
|
||||
if db.comments.searchByAll(request.cookies.get("uid"), request.form["bookid"]):
|
||||
return "你已经完成了评论 不可重复提交"
|
||||
db.comments.new(
|
||||
request.form["bookid"],
|
||||
request.cookies.get("uid"),
|
||||
request.form["score"],
|
||||
request.form["text"],
|
||||
)
|
||||
return redirect("/book/" + request.form["bookid"])
|
39
web/page.py
39
web/page.py
@ -1,20 +1,23 @@
|
||||
from flask import *
|
||||
from flask import Blueprint
|
||||
import time
|
||||
import db.file, file , app_conf
|
||||
import db.comments, db.user, db.file, file, app_conf
|
||||
|
||||
page_bp = Blueprint("page_bp", __name__)
|
||||
|
||||
conf = app_conf.conf()
|
||||
|
||||
|
||||
@page_bp.route("/overview/<page>")
|
||||
def overview(page): # 概览
|
||||
page = int(page)
|
||||
if request.cookies.get("islogin") is None: #验证登录状态
|
||||
if request.cookies.get("islogin") is None: # 验证登录状态
|
||||
return redirect("/")
|
||||
metaDataList = db.file.getMetadata((page - 1) * 20, page * 20, request.args.get("search"))
|
||||
metaDataList = db.file.getMetadata(
|
||||
(page - 1) * 20, page * 20, request.args.get("search")
|
||||
)
|
||||
for item in metaDataList:
|
||||
item[2] = item[2][:-4] #去除文件扩展名
|
||||
item[2] = item[2][:-4] # 去除文件扩展名
|
||||
if page <= 3:
|
||||
lastPageList = range(1, page)
|
||||
else:
|
||||
@ -26,12 +29,14 @@ def overview(page): # 概览
|
||||
lastPageList=lastPageList,
|
||||
pagenow=page,
|
||||
nextPageList=nextPageList,
|
||||
aftertime=int(time.time()) - 3 * 86400,
|
||||
username=request.cookies.get("islogin"),
|
||||
)
|
||||
|
||||
|
||||
@page_bp.route("/book/<bookid>")
|
||||
def book(bookid): # 接口
|
||||
if request.cookies.get("islogin") is None: #验证登录状态
|
||||
if request.cookies.get("islogin") is None: # 验证登录状态
|
||||
return redirect("/")
|
||||
data = db.file.searchByid(bookid)
|
||||
if len(data) == 0:
|
||||
@ -40,17 +45,32 @@ def book(bookid): # 接口
|
||||
data[0][2] = data[0][2][0:-4] # 把文件扩展名去掉
|
||||
local_time = time.localtime(float(data[0][4]))
|
||||
|
||||
raw_com = db.comments.listByBookid(bookid)
|
||||
comments = []
|
||||
for i in raw_com:
|
||||
comments.append(
|
||||
{
|
||||
"id": i[0],
|
||||
"time": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(float(i[1]))),
|
||||
"from": db.user.getUsername(i[3]),
|
||||
"socre":i[4],
|
||||
"text":i[5]
|
||||
}
|
||||
)
|
||||
|
||||
return render_template(
|
||||
"book.html",
|
||||
id=bookid,
|
||||
data=data,
|
||||
time=time.strftime("%Y-%m-%d %H:%M:%S",local_time),
|
||||
time=time.strftime("%Y-%m-%d %H:%M:%S", local_time),
|
||||
socre=db.comments.getScore(bookid),
|
||||
comments=comments,
|
||||
)
|
||||
|
||||
|
||||
@page_bp.route("/view/<bookid>")
|
||||
def view(bookid): # 接口
|
||||
if request.cookies.get("islogin") is None: #验证登录状态
|
||||
if request.cookies.get("islogin") is None: # 验证登录状态
|
||||
return redirect("/")
|
||||
data = db.file.searchByid(bookid)
|
||||
if len(data) == 0:
|
||||
@ -60,7 +80,7 @@ def view(bookid): # 接口
|
||||
|
||||
@page_bp.route("/upload", methods=["GET", "POST"]) # 文件上传
|
||||
def upload_file():
|
||||
if request.cookies.get("islogin") is None: #验证登录状态
|
||||
if request.cookies.get("islogin") is None: # 验证登录状态
|
||||
return redirect("/")
|
||||
if request.method == "GET":
|
||||
return render_template("upload.html")
|
||||
@ -71,6 +91,3 @@ def upload_file():
|
||||
fileitem.save(conf.get("file", "inputdir") + "/" + fileitem.filename)
|
||||
file.auotLoadFile()
|
||||
return "success"
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user