import css and js
This commit is contained in:
parent
08bb21b8ff
commit
5e858c3c4b
@ -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
|
||||
@ -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
|
||||
@ -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
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
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
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
1
src/static/spectre.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -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 %}
|
||||
|
||||
99
src/templates/user/addbook.html
Normal file
99
src/templates/user/addbook.html
Normal 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 %}
|
||||
64
src/templates/user/addtype.html
Normal file
64
src/templates/user/addtype.html
Normal 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 %}
|
||||
67
src/templates/user/home.html
Normal file
67
src/templates/user/home.html
Normal 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 %}
|
||||
57
src/templates/user/search.html
Normal file
57
src/templates/user/search.html
Normal 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 %}
|
||||
91
src/user.py
91
src/user.py
@ -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)
|
||||
Loading…
Reference in New Issue
Block a user