import css and js

This commit is contained in:
ridethepig 2022-11-13 09:08:32 +08:00
parent 08bb21b8ff
commit 5e858c3c4b
14 changed files with 425 additions and 11 deletions

View File

@ -1,6 +1,6 @@
import os
from flask import Flask, render_template
from flask import Flask, render_template, g, redirect, url_for
def create_app(test_config=None):
@ -21,9 +21,6 @@ def create_app(test_config=None):
except OSError:
pass
@app.route('/')
def index():
return render_template("index.html")
from . import db
db.init_app(app)
from . import auth
@ -31,4 +28,15 @@ def create_app(test_config=None):
from . import admin
app.register_blueprint(admin.bp)
app.add_url_rule("/admin", endpoint="admin.index")
from . import user
app.register_blueprint(user.bp)
@app.route('/')
def index():
if g.user is not None and 'user_id' in g.user.keys():
if g.user['user_id'] == 0:
return redirect(url_for("admin.index"))
else:
return redirect(url_for("user.home"))
return render_template("index.html")
return app

View File

@ -24,7 +24,7 @@ def loginuser():
if error is None:
session.clear()
session['user_id'] = user['user_id']
return redirect(url_for('index'))
return redirect(url_for('home'))
flash(error)
@ -79,7 +79,8 @@ def login_required(view):
def wrapped_view(**kwargs):
if g.user is None:
return redirect(url_for('auth.login'))
elif g.user['user_id'] == 0:
return redirect(url_for('admin.index'))
return view(**kwargs)
return wrapped_view
@ -88,9 +89,9 @@ def admin_login_required(view):
@functools.wraps(view)
def wrapped_view(**kwargs):
if g.user is None:
return redirect(url_for('auth.loginadmin'))
return redirect(url_for('auth.login'))
elif g.user['user_id'] != 0:
return redirect(url_for('index'))
return redirect(url_for('home'))
return view(**kwargs)
return wrapped_view

View File

@ -40,6 +40,7 @@ book_isbn varchar(100) DEFAULT NULL,
book_publisher varchar(100) DEFAULT NULL,
book_pubdate datetime DEFAULT NULL,
book_lang varchar(100) DEFAULT NULL,
book_author varchar(100) DEFAULT NULL,
user_id int NOT NULL,
CONSTRAINT `fk_book_user_id` FOREIGN KEY (`user_id`) REFERENCES user(`user_id`) ON DELETE RESTRICT
);

2
src/static/axios.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
src/static/spectre-exp.min.css vendored Normal file

File diff suppressed because one or more lines are too long

1
src/static/spectre-icons.min.css vendored Normal file

File diff suppressed because one or more lines are too long

1
src/static/spectre.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,11 @@
<!doctype html>
<title>{% block title %}{% endblock %} - DBProject</title>
<!-- <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> -->
<nav>
<link rel="stylesheet" href="{{ url_for('static', filename='spectre-exp.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='spectre-icons.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='spectre.min.css') }}">
<script src="{{ url_for('static', filename='axios.min.js')}}"></script>
<!-- <nav>
<h1>BookManage</h1>
<ul>
{% if g.user %}
@ -12,7 +16,24 @@
<li><a href="{{ url_for('auth.loginuser') }}">用户登陆</a>
{% endif %}
</ul>
</nav>
</nav> -->
<header class="navbar">
<section class="navbar-section">
<h1>电子书管理系统</h1>
</section>
<section class="navbar-center">
<!-- centered logo or brand -->
</section>
<section class="navbar-section">
{% if g.user %}
<span class="chip">{{ g.user['user_name'] }}</span>
<a class="btn btn-link" href="{{ url_for('auth.logout') }}">登出</a>
{% else %}
<a class="btn btn-link" href="{{ url_for('auth.loginadmin') }}">管理员登陆</a>
<a class="btn btn-link" href="{{ url_for('auth.loginuser') }}">用户登陆</a>
{% endif %}
</section>
</header>
<section class="content">
<header>
{% block header %}{% endblock %}

View File

@ -0,0 +1,99 @@
{% extends 'base.html' %}
{% block header %}
<style>
.maindiv {
height: 100%;
width: 100%;
position: fixed;
z-index: 1;
top: 20;
left: 0;
overflow-x: hidden;
padding-left: 1.2rem;
padding-right: 2rem;
}
.sidenav {
height: 100%;
max-width: 160px;
z-index: 1;
overflow-x: hidden;
}
</style>
<script>
var typelist = {};
function switch_type(typename) {
if (typelist.hasOwnProperty(typename)) {
delete typelist[typename];
} else {
typelist[typename] = 1;
}
let typeinput = document.getElementById("booktype");
let typestr = "";
for (let typekey in typelist) {
typestr += typekey + ";";
}
typeinput.value = typestr;
}
function create_type_button(typename) {
}
</script>
{% endblock %}
{% block content %}
<div class="container maindiv">
<div class="columns">
<div class="column col-3">
<ul class="nav">
<li class="nav-item">
<a href="/home">主页</a>
</li>
<li class="nav-item">
<a href="/search">搜索</a>
</li>
<li class="nav-item">
<a href="/addbook">增加</a>
</li>
<li class="nav-item">
<a href="/tags">分类</a>
</li>
</ul>
</div>
<div class="column col-9 panel">
<div class="panel-header">
<h2>新建图书</h2>
</div>
<div class="panel-body">
<form method="post" class="form-group">
<label class="form-label" for="bookname">书名*</label>
<input class="form-input" name="bookname" id="bookname" required>
<label class="form-label" for="bookisbn">ISBN</label>
<input class="form-input" name="bookisbn" id="bookisbn">
<label class="form-label" for="bookpublisher">出版社</label>
<input class="form-input" name="bookpublisher" id="bookpublisher">
<label class="form-label" for="bookauthor">作者</label>
<input class="form-input" name="bookauthor" id="bookauthor">
<label class="form-label" for="booklang">语言</label>
<select class="form-select" name="booklang" id="booklang">
<option selected>CN</option>
<option>EN</option>
<option>Other</option>
</select>
<label class="form-label" for="booktype">分类</label>
<input class="form-input" name="booktype" id="booktype">
<div>
{% for atype in typelist%}
<span class="chip btn" onclick={{"switch_type(" ~ atype ~ ")"}}>{{atype}}</span>
{% endfor %}
</div>
<input class="btn btn-primary input-group-btn p-centered" type="submit" value="提交">
</form>
</div>
<div class="panel-footer">
Rendered @ {{cur_time}}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,64 @@
{% extends 'base.html' %}
{% block header %}
<style>
.maindiv {
height: 100%;
width: 100%;
position: fixed;
z-index: 1;
top: 20;
left: 0;
overflow-x: hidden;
padding-left: 1.2rem;
padding-right: 2rem;
}
.sidenav {
height: 100%;
max-width: 160px;
z-index: 1;
overflow-x: hidden;
}
</style>
{% endblock %}
{% block content %}
<div class="container maindiv">
<div class="columns">
<div class="column col-3">
<ul class="nav">
<li class="nav-item">
<a href="/home">主页</a>
</li>
<li class="nav-item">
<a href="/search">搜索</a>
</li>
<li class="nav-item">
<a href="/addbook">增加</a>
</li>
<li class="nav-item">
<a href="/tags">分类</a>
</li>
</ul>
</div>
<div class="column col-9 panel">
<div class="panel-header">
<div class="panel-title">图书分类</div>
</div>
<div class="panel-body">
<ul>
{% for atype in typelist%}
<li>
TID:{{ atype['type_id'] }}, 类型名: {{ user['user_name'] }}
<a href={{"/addtype/removeuser?uid=" ~ user['user_id']}}>删除</a>
</li>
{% endfor %}
</ul>
</div>
<div class="panel-footer">
Rendered @ {{cur_time}}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,67 @@
{% extends 'base.html' %}
{% block header %}
<style>
.maindiv {
height: 100%;
width: 100%;
position: fixed;
z-index: 1;
top: 20;
left: 0;
overflow-x: hidden;
padding-left: 1.2rem;
padding-right: 2rem;
}
.sidenav {
height: 100%;
max-width: 160px;
z-index: 1;
overflow-x: hidden;
}
</style>
{% endblock %}
{% block content %}
<div class="container maindiv">
<div class="columns">
<div class="column col-3">
<ul class="nav">
<li class="nav-item">
<a href="/home">主页</a>
</li>
<li class="nav-item">
<a href="/search">搜索</a>
</li>
<li class="nav-item">
<a href="/addbook">增加</a>
</li>
<li class="nav-item">
<a href="/tags">分类</a>
</li>
</ul>
</div>
<div class="column col-9 panel">
<div class="panel-header">
<div class="panel-title">统计信息</div>
</div>
<div class="panel-body">
<dl>
<dt> 当前占用的空间 </dt>
<dd> {{user_stat['user_usedspace'] / 1024}}MB /
{{user_stat['user_limit'] / 1024 / 1024}}GB</dd>
<dt> 图书数量 </dt>
<dd> {{user_stat['user_bookcount']}}本</dd>
<dt> 文件数量 </dt>
<dd> {{user_stat['user_doccount']}}个</dd>
<dt> 笔记数量 </dt>
<dd> {{user_stat['user_notecount']}}篇</dd>
</dl>
</div>
<div class="panel-footer">
Rendered @ {{cur_time}}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,57 @@
{% extends 'base.html' %}
{% block header %}
<style>
.maindiv {
height: 100%;
width: 100%;
position: fixed;
z-index: 1;
top: 20;
left: 0;
overflow-x: hidden;
padding-left: 1.2rem;
padding-right: 2rem;
}
.sidenav {
height: 100%;
max-width: 160px;
z-index: 1;
overflow-x: hidden;
}
</style>
{% endblock %}
{% block content %}
<div class="container maindiv">
<div class="columns">
<div class="column col-3">
<ul class="nav">
<li class="nav-item">
<a href="/home">主页</a>
</li>
<li class="nav-item">
<a href="/search">搜索</a>
</li>
<li class="nav-item">
<a href="/addbook">增加</a>
</li>
<li class="nav-item">
<a href="/tags">分类</a>
</li>
</ul>
</div>
<div class="column col-9 panel">
<div class="panel-header">
<div class="panel-title">搜索图书</div>
</div>
<div class="panel-body">
</div>
<div class="panel-footer">
Rendered @ {{cur_time}}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,91 @@
from flask import (
Blueprint, flash, g, redirect, render_template, request, url_for
)
import re
from werkzeug.exceptions import abort
from werkzeug.security import generate_password_hash
from src.auth import login_required
from src.db import get_db
import sqlite3
import datetime
bp = Blueprint('user', __name__)
@bp.route("/home")
@login_required
def home():
db = get_db()
user_stat = db.execute(
"select * from user_stat where user_id = ?", (g.user['user_id'],)
).fetchone()
return render_template("user/home.html", user_stat=user_stat, cur_time=datetime.datetime.now())
@bp.route("/addbook", methods=('GET', 'POST'))
@login_required
def addbook():
db = get_db()
if request.method == 'GET':
typelist = db.execute("select type_name from typetable").fetchall()
return render_template("user/addbook.html", typelist=typelist)
elif request.method == 'POST':
bookname = request.form['bookname']
bookisbn = request.form['bookisbn']
bookpublisher = request.form['bookpublisher']
booklang = request.form['booklang']
bookauthor = request.form['bookauthor']
booktype = request.form['booktype']
error = None
if len(bookname) == 0:
error = "书名不能为空"
if len(bookisbn) == 0:
bookisbn = None
if len(bookpublisher) == 0:
bookpublisher = None
if len(booklang) == 0:
booklang = None
if len(bookauthor) == 0:
booklang = None
if len(booktype) == 0:
booktype = None
db.execute(
"insert into book (`book_name`, `book_isbn`"
", `book_publisher`, `book_lang`, `book_author`, `user_id`) "
"values (?,?,?,?,?,?,?)",
(bookname, bookisbn, bookpublisher, booklang, bookauthor, g.user['user_id'],))
bookid = db.execute("select max(book_id) from book").fetchone()
db.commit()
error = None
if booktype is not None:
booktypes = booktype.split(";")
booktypes.remove("")
print(booktypes)
for booktype in booktypes:
typeid = db.execute("select type_id from typetable where type_name=?",
(booktype,)).fetchone()
if typeid is None:
db.execute("insert into typetable(`type_name`) values (?)",
(booktype,))
typeid = db.execute("select type_id from typetable where type_name=?",
(booktype,)).fetchone()
try:
db.execute("insert into book_type values(?,?)",
(bookid, typeid))
db.commit()
except sqlite3.Error as _e:
error = "未知错误: %s" % (_e)
db.rollback()
if error is not None:
flash(error)
else:
return render_template("user/addbook.html", success=True)
return render_template("user/addbook.html")
@bp.route("/addtype", methods=('GET', 'POST', 'PUT'))
@login_required
def addtype():
if request.method == 'POST':
db = get_db()
typelist = db.execute("select * from typetable").fetchall()
return render_template("user/addtype.html", typelist=typelist)

Binary file not shown.