fuck lining, from sqlite to mysql

This commit is contained in:
ridethepig 2022-12-11 21:43:19 +08:00
parent 018499d722
commit 9f93aa854b
17 changed files with 462 additions and 338 deletions

View File

@ -4,3 +4,6 @@ python -m venv venv
pip install flask
flask --app main run
```
使用之前需要新整一个mysql服务器然后在里面建立一个数据库bigwork并保证该数据库被授权给了指定的用户。
在config里面修改对应的用户、密码、服务器地址

View File

@ -1,111 +1,134 @@
drop database if exists bigwork;
create database bigwork;
use bigwork;
drop table if exists `admin`;
drop table if exists user_stat;
drop table if exists book_type;
drop table if exists book_author;
drop table if exists author;
drop table if exists typetable;
drop table if exists record;
drop table if exists note;
drop table if exists document;
drop table if exists book;
drop table if exists user;
create table `admin`
(
passwd varchar(100) NOT NULL
passwd varchar(200) NOT NULL
);
insert into `admin` (`passwd`) values('');
-- insert into `admin` (`passwd`) values('');
create table user
(
user_id int PRIMARY KEY AUTO_INCREMENT,
user_name varchar(100) NOT NULL,
user_mail varchar(100) NOT NULL,
user_passwd varchar(100) NOT NULL,
user_limit int NOT NULL,
user_regtime datetime NOT NULL
user_id int PRIMARY KEY AUTO_INCREMENT,
user_name varchar(100) NOT NULL UNIQUE,
user_mail varchar(100) NOT NULL UNIQUE,
user_passwd varchar(200) NOT NULL,
user_limit int NOT NULL,
user_regtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table book
(
book_id int PRIMARY KEY AUTO_INCREMENT,
book_name varchar(100) NOT NULL,
book_isbn varchar(100) DEFAULT NULL,
book_publisher varchar(100) DEFAULT NULL,
book_pubdate datetime DEFAULT NULL,
book_lang varchar(100) DEFAULT NULL,
user_id int NOT NULL,
CONSTRAINT `fk_book_user_id` FOREIGN KEY (`user_id`) REFERENCES user(`user_id`)
book_id int PRIMARY KEY AUTO_INCREMENT,
book_name varchar(100) NOT NULL,
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 CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table document
(
doc_id int PRIMARY KEY AUTO_INCREMENT,
doc_name varchar(100) NOT NULL,
doc_url varchar(100) NOT NULL,
doc_size int NOT NULL,
doc_date datetime NOT NULL,
doc_type varchar(100) NOT NULL,
book_id int NOT NULL,
user_id int NOT NULL,
CONSTRAINT `fk_document_user_id` FOREIGN KEY (`user_id`) REFERENCES user(`user_id`),
CONSTRAINT `fk_document_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`),
INDEX (doc_name(10)),
INDEX (doc_date)
doc_id int PRIMARY KEY AUTO_INCREMENT,
doc_name varchar(100) NOT NULL,
doc_url varchar(100) NOT NULL,
doc_size int NOT NULL,
doc_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
doc_type varchar(100) NOT NULL,
book_id int NOT NULL,
user_id int NOT NULL,
CONSTRAINT `fk_document_user_id` FOREIGN KEY (`user_id`) REFERENCES user(`user_id`) ON DELETE CASCADE,
CONSTRAINT `fk_document_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create index `idx_doc_name` on document(doc_name);
create table note
(
note_id int PRIMARY KEY AUTO_INCREMENT,
note_name varchar(100) NOT NULL,
note_date datetime NOT NULL,
note_content mediumtext NOT NULL DEFAULT '',
book_id int NOT NULL,
user_id int NOT NULL,
CONSTRAINT `fk_note_user_id` FOREIGN KEY (`user_id`) REFERENCES user(`user_id`),
CONSTRAINT `fk_note_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`),
INDEX (note_name(10))
note_id int PRIMARY KEY AUTO_INCREMENT,
note_name varchar(100) NOT NULL,
note_date datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
note_content text NOT NULL,
book_id int NOT NULL,
user_id int NOT NULL,
CONSTRAINT `fk_note_user_id` FOREIGN KEY (`user_id`) REFERENCES user(`user_id`) ON DELETE CASCADE,
CONSTRAINT `fk_note_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create index `idx_note_name` on note(note_name);
create table record
(
record_time timestamp PRIMARY KEY,
record_type varchar(10) NOT NULL,
doc_URL varchar(100) NOT NULL,
user_id int NOT NULL,
INDEX (record_type)
record_time timestamp PRIMARY KEY DEFAULT CURRENT_TIMESTAMP,
record_type varchar(10) NOT NULL,
doc_URL varchar(100) NOT NULL,
user_id int NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table typetable
(
type_id int PRIMARY KEY AUTO_INCREMENT,
type_name varchar(20) NOT NULL,
UNIQUE (type_name)
type_id int PRIMARY KEY AUTO_INCREMENT,
type_name varchar(20) NOT NULL UNIQUE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table author
(
author_id int PRIMARY KEY AUTO_INCREMENT,
author_name varchar(50) NOT NULL,
INDEX (author_name(10))
author_id int PRIMARY KEY AUTO_INCREMENT,
author_name varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create index `idx_author_name` on author(author_name);
create table book_author
(
author_id int NOT NULL,
book_id int NOT NULL,
PRIMARY KEY (`author_id`, `book_id`),
CONSTRAINT `fk_ba_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`),
CONSTRAINT `fk_ba_author_id` FOREIGN KEY (`author_id`) REFERENCES author(`author_id`)
author_id int NOT NULL,
book_id int NOT NULL,
PRIMARY KEY (`author_id`, `book_id`),
CONSTRAINT `fk_ba_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`) ON DELETE RESTRICT,
CONSTRAINT `fk_ba_author_id` FOREIGN KEY (`author_id`) REFERENCES author(`author_id`) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table book_type
(
type_id int NOT NULL,
book_id int NOT NULL,
PRIMARY KEY (`type_id`, `book_id`),
CONSTRAINT `fk_bt_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`),
CONSTRAINT `fk_bt_type_id` FOREIGN KEY (`type_id`) REFERENCES typetable(`type_id`)
type_id int NOT NULL,
book_id int NOT NULL,
PRIMARY KEY (`type_id`, `book_id`),
CONSTRAINT `fk_bt_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`) ON DELETE CASCADE,
CONSTRAINT `fk_bt_type_id` FOREIGN KEY (`type_id`) REFERENCES typetable(`type_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table user_stat
(
user_id int PRIMARY KEY,
user_usedspace int NOT NULL DEFAULT 0,
user_bookcount int NOT NULL DEFAULT 0,
user_doccount int NOT NULL DEFAULT 0,
user_typecount int NOT NULL DEFAULT 0,
CONSTRAINT `fk_user_stat_user` FOREIGN KEY REFERENCES user(`user_id`)
user_id int PRIMARY KEY,
user_limit int NOT NULL,
user_usedspace int NOT NULL DEFAULT 0,
user_bookcount int NOT NULL DEFAULT 0,
user_doccount int NOT NULL DEFAULT 0,
user_notecount int NOT NULL DEFAULT 0,
CONSTRAINT `fk_user_stat_user` FOREIGN KEY (`user_id`) REFERENCES user(`user_id`) ON DELETE CASCADE,
CONSTRAINT `ck_usedspace` CHECK (user_usedspace <= user_limit)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
drop view if exists `v_book_to_types`;
create view `v_book_to_types` as
select book_id, typetable.type_id as type_id, type_name from book_type natural join typetable;
drop view if exists `v_type_to_book`;
create view `v_type_to_book` as
select book_id,
book_name,
book_isbn,
book_publisher,
book_lang,
book_author,
user_id,
type_id,
type_name
from book natural join book_type natural join typetable;

View File

@ -1,3 +1,22 @@
use bigwork;
DELIMITER ##
drop trigger if exists `trig_create_user_stat`;
create trigger `trig_create_user_stat`
after insert on user
for each row begin
insert into user_stat (`user_id`, `user_limit`) values(NEW.user_id, NEW.user_limit);
end ##
DELIMITER ;
DELIMITER ##
drop trigger if exists `trig_delete_user_stat`;
create trigger `trig_delete_user_stat`
after delete on user
for each row begin
delete from user_stat where user_id=OLD.user_id;
end ##
DELIMITER ;
drop trigger if exists `trig_update_stat_book_ins`;
DELIMITER ##
create trigger `trig_update_stat_book_ins`
@ -36,20 +55,20 @@ create trigger `trig_update_stat_doc_del`
end ##
DELIMITER ;
drop trigger if exists `trig_update_stat_type_ins`;
drop trigger if exists `trig_update_stat_note_ins`;
DELIMITER ##
create trigger `trig_update_stat_type_ins`
after insert on typetable
create trigger `trig_update_stat_note_ins`
after insert on note
for each row begin
update user_stat set user_typecount=user_typecount+1 where user_stat.user_id=NEW.user_id;
update user_stat set user_notecount=user_notecount+1 where user_stat.user_id=NEW.user_id;
end ##
DELIMITER ;
drop trigger if exists `trig_update_stat_type_del`;
drop trigger if exists `trig_update_stat_note_del`;
DELIMITER ##
create trigger `trig_update_stat_type_del`
after delete on typetable
create trigger `trig_update_stat_note_del`
after delete on note
for each row begin
update user_stat set user_typecount=user_typecount-1 where user_stat.user_id=OLD.user_id;
update user_stat set user_notecount=user_notecount-1 where user_stat.user_id=OLD.user_id;
end ##
DELIMITER ;

View File

@ -8,7 +8,11 @@ def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'dbproj.db'),
# DATABASE=os.path.join(app.instance_path, 'dbproj.db'),
DATABASE='bigwork',
DATABASE_USER='root',
DATABASE_HOST='localhost',
DATABASE_PASS='lil0,.lil0',
)
if test_config is None:

View File

@ -7,7 +7,7 @@ from werkzeug.security import generate_password_hash
from src.auth import admin_login_required
from src.db import get_db
import sqlite3
import pymysql
bp = Blueprint('admin', __name__, url_prefix='/admin')
@ -20,10 +20,12 @@ def validateEmail(email):
@bp.route('/')
@admin_login_required
def index():
db = get_db()
users = db.execute(
cur = get_db().cursor()
cur.execute(
'select * from user'
).fetchall()
)
users = cur.fetchall()
cur.close()
return render_template("admin/index.html", users=users)
@bp.route('/adduser', methods=("GET", "POST"))
@ -39,22 +41,27 @@ def adduser():
error = '用户空间必须是整数GB'
elif not validateEmail(usermail):
error = 'email格式不合法'
userlimi = int(userlimi)
userlimi = float(userlimi)
userlimi *= 1024 * 1024 # userlimit is stored and measured by KB
userlimi = int(userlimi)
if error is None:
db = get_db()
cur = db.cursor()
try:
db.execute(
'insert into user(`user_name`, `user_mail`, `user_passwd`, `user_limit`) values (?,?,?,?)',
cur.execute(
'insert into user(`user_name`, `user_mail`, `user_passwd`, `user_limit`) values (%s,%s,%s,%s)',
(username, usermail, generate_password_hash(password), userlimi,)
)
db.commit()
except sqlite3.IntegrityError as _e:
except pymysql.IntegrityError as _e:
error = "用户名或邮箱已经存在 %s" % (_e)
db.rollback()
except sqlite3.Error as _e:
except pymysql.Error as _e:
error = "未知错误 %s" % (_e)
db.rollback()
finally:
cur.close()
if error is None:
return redirect(url_for('admin.index'))
flash(error)
@ -69,18 +76,21 @@ def removeuser():
uid_to_del = request.args.get("uid")
if uid_to_del is not None and uid_to_del.isdecimal:
db = get_db()
cur = db.cursor()
rowcnt = 0
try:
rowcnt = db.execute(
"delete from user where user.user_id=?", (uid_to_del, )
).rowcount
rowcnt = cur.execute(
"delete from user where user.user_id=%s", (uid_to_del, )
)
db.commit()
except sqlite3.IntegrityError as _e:
except pymysql.IntegrityError as _e:
error = "用户未做好被删除的准备:%s" % (_e)
db.rollback()
except sqlite3.Error as _e:
except pymysql.Error as _e:
error = "删除发生未知错误: %s" %(_e)
db.rollback()
finally:
cur.close()
if error is None:
if rowcnt != 0:
error = "删除uid为%s的用户成功!" % uid_to_del

View File

@ -11,20 +11,22 @@ def loginuser():
username = request.form['username']
password = request.form['password']
db = get_db()
cur = db.cursor()
error = None
user = db.execute(
'SELECT * FROM user WHERE user_name = ?', (username,)
).fetchone()
cur.execute(
'SELECT * FROM user WHERE user_name = %s', (username,)
)
user = cur.fetchone()
cur.close()
if user is None:
error = '用户名不存在'
elif not check_password_hash(user['user_passwd'], password):
error = '密码错误'
if error is None:
if error is None and user is not None:
session.clear()
session['user_id'] = user['user_id']
return redirect(url_for('home'))
return redirect(url_for('user.home'))
flash(error)
@ -35,8 +37,10 @@ def loginadmin():
if request.method == 'POST':
password = request.form['password']
db = get_db()
cur = db.cursor()
error = None
admin = db.execute('SELECT * FROM admin limit 1').fetchone()
cur.execute('SELECT * FROM admin limit 1')
admin = cur.fetchone()
if admin is None:
error = '用户名不存在'
@ -64,9 +68,9 @@ def load_logged_in_user():
g.user = {'user_id':0, 'user_name': 'admin'}
# use id=0 to refer to admin
else:
g.user = get_db().execute(
'SELECT * FROM user WHERE user_id = ?', (user_id,)
).fetchone()
cur = get_db().cursor()
cur.execute('SELECT * FROM user WHERE user_id = %s', (user_id,))
g.user = cur.fetchone()
@bp.route('/logout')
def logout():
@ -91,7 +95,7 @@ def admin_login_required(view):
if g.user is None:
return redirect(url_for('auth.login'))
elif g.user['user_id'] != 0:
return redirect(url_for('home'))
return redirect(url_for('user.home'))
return view(**kwargs)
return wrapped_view

View File

@ -1,15 +1,21 @@
import sqlite3
# import sqlite3
import pymysql
import click
from flask import current_app, g
from werkzeug.security import generate_password_hash
def get_db():
if 'db' not in g:
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
# g.db = sqlite3.connect(
# current_app.config['DATABASE'],
# detect_types=sqlite3.PARSE_DECLTYPES
# )
# g.db.row_factory = sqlite3.Row
g.db = pymysql.connect(
host=current_app.config['DATABASE_HOST'],
user=current_app.config['DATABASE_USER'],
password=current_app.config['DATABASE_PASS'],
database=current_app.config['DATABASE'], cursorclass=pymysql.cursors.DictCursor)
return g.db
@ -23,14 +29,16 @@ def close_db(e=None):
@click.command('init-db')
def init_db():
db = get_db()
click.echo("Initializing database schema...")
with current_app.open_resource('sql/db_create_sqlite.sql') as f:
db.executescript(f.read().decode('utf8'))
click.echo("Initializing database triggers...")
with current_app.open_resource('sql/trigger_sqlite.sql') as f:
db.executescript(f.read().decode('utf8'))
click.echo("PyMySQL do not support script execution...")
# click.echo("Initializing database schema...")
# with current_app.open_resource('sql/db_create_sqlite.sql') as f:
# db.executescript(f.read().decode('utf8'))
# click.echo("Initializing database triggers...")
# with current_app.open_resource('sql/trigger_sqlite.sql') as f:
# db.executescript(f.read().decode('utf8'))
click.echo("Initializing admin passwd...")
db.execute("insert into admin (passwd) values (?)", (generate_password_hash("lolicon"),))
print(len(generate_password_hash("lolicon")))
db.cursor().execute("insert into admin (passwd) values (%s)", (generate_password_hash("lolicon")))
db.commit()
click.echo("Initialized database.")

View File

@ -1,111 +0,0 @@
drop database if exists bigwork;
create database bigwork;
create table `admin`
(
passwd varchar(100) NOT NULL
);
insert into `admin` (`passwd`) values('');
create table user
(
user_id int PRIMARY KEY AUTO_INCREMENT,
user_name varchar(100) NOT NULL,
user_mail varchar(100) NOT NULL,
user_passwd varchar(100) NOT NULL,
user_limit int NOT NULL,
user_regtime datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table book
(
book_id int PRIMARY KEY AUTO_INCREMENT,
book_name varchar(100) NOT NULL,
book_isbn varchar(100) DEFAULT NULL,
book_publisher varchar(100) DEFAULT NULL,
book_pubdate datetime DEFAULT NULL,
book_lang varchar(100) DEFAULT NULL,
user_id int NOT NULL,
CONSTRAINT `fk_book_user_id` FOREIGN KEY (`user_id`) REFERENCES user(`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table document
(
doc_id int PRIMARY KEY AUTO_INCREMENT,
doc_name varchar(100) NOT NULL,
doc_url varchar(100) NOT NULL,
doc_size int NOT NULL,
doc_date datetime NOT NULL,
doc_type varchar(100) NOT NULL,
book_id int NOT NULL,
user_id int NOT NULL,
CONSTRAINT `fk_document_user_id` FOREIGN KEY (`user_id`) REFERENCES user(`user_id`),
CONSTRAINT `fk_document_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`),
INDEX (doc_name(10)),
INDEX (doc_date)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table note
(
note_id int PRIMARY KEY AUTO_INCREMENT,
note_name varchar(100) NOT NULL,
note_date datetime NOT NULL,
note_content mediumtext NOT NULL DEFAULT '',
book_id int NOT NULL,
user_id int NOT NULL,
CONSTRAINT `fk_note_user_id` FOREIGN KEY (`user_id`) REFERENCES user(`user_id`),
CONSTRAINT `fk_note_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`),
INDEX (note_name(10))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table record
(
record_time timestamp PRIMARY KEY,
record_type varchar(10) NOT NULL,
doc_URL varchar(100) NOT NULL,
user_id int NOT NULL,
INDEX (record_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table typetable
(
type_id int PRIMARY KEY AUTO_INCREMENT,
type_name varchar(20) NOT NULL,
UNIQUE (type_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table author
(
author_id int PRIMARY KEY AUTO_INCREMENT,
author_name varchar(50) NOT NULL,
INDEX (author_name(10))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table book_author
(
author_id int NOT NULL,
book_id int NOT NULL,
PRIMARY KEY (`author_id`, `book_id`),
CONSTRAINT `fk_ba_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`),
CONSTRAINT `fk_ba_author_id` FOREIGN KEY (`author_id`) REFERENCES author(`author_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table book_type
(
type_id int NOT NULL,
book_id int NOT NULL,
PRIMARY KEY (`type_id`, `book_id`),
CONSTRAINT `fk_bt_book_id` FOREIGN KEY (`book_id`) REFERENCES book(`book_id`),
CONSTRAINT `fk_bt_type_id` FOREIGN KEY (`type_id`) REFERENCES typetable(`type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
create table user_stat
(
user_id int PRIMARY KEY,
user_usedspace int NOT NULL DEFAULT 0,
user_bookcount int NOT NULL DEFAULT 0,
user_doccount int NOT NULL DEFAULT 0,
user_typecount int NOT NULL DEFAULT 0,
CONSTRAINT `fk_user_stat_user` FOREIGN KEY REFERENCES user(`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

View File

@ -1,55 +0,0 @@
drop trigger if exists `trig_update_stat_book_ins`;
DELIMITER ##
create trigger `trig_update_stat_book_ins`
after insert on book
for each row begin
update user_stat set user_bookcount=user_bookcount+1 where user_stat.user_id=NEW.user_id;
end ##
DELIMITER ;
drop trigger if exists `trig_update_stat_book_del`;
DELIMITER ##
create trigger `trig_update_stat_book_del`
after delete on book
for each row begin
update user_stat set user_bookcount=user_bookcount-1 where user_stat.user_id=OLD.user_id;
end ##
DELIMITER ;
drop trigger if exists `trig_update_stat_doc_ins`;
DELIMITER ##
create trigger `trig_update_stat_doc_ins`
after insert on document
for each row begin
update user_stat set user_doccount=user_doccount+1 where user_stat.user_id=NEW.user_id;
update user_stat set user_usedspace=user_usedspace+NEW.doc_size where user_stat.user_id=NEW.user_id;
end ##
DELIMITER ;
drop trigger if exists `trig_update_stat_doc_del`;
DELIMITER ##
create trigger `trig_update_stat_doc_del`
after delete on document
for each row begin
update user_stat set user_doccount=user_doccount-1 where user_stat.user_id=OLD.user_id;
update user_stat set user_usedspace=user_usedspace-OLD.doc_size where user_stat.user_id=OLD.user_id;
end ##
DELIMITER ;
drop trigger if exists `trig_update_stat_type_ins`;
DELIMITER ##
create trigger `trig_update_stat_type_ins`
after insert on typetable
for each row begin
update user_stat set user_typecount=user_typecount+1 where user_stat.user_id=NEW.user_id;
end ##
DELIMITER ;
drop trigger if exists `trig_update_stat_type_del`;
DELIMITER ##
create trigger `trig_update_stat_type_del`
after delete on typetable
for each row begin
update user_stat set user_typecount=user_typecount-1 where user_stat.user_id=OLD.user_id;
end ##
DELIMITER ;

View File

@ -9,7 +9,7 @@
z-index: 1;
top: 20;
left: 0;
overflow-x: hidden;
padding-left: 1.2rem;
padding-right: 2rem;
}
@ -17,7 +17,7 @@
height: 100%;
max-width: 160px;
z-index: 1;
overflow-x: hidden;
}
</style>
<script>
@ -42,7 +42,7 @@
{% endblock %}
{% block content %}
<div class="container maindiv">
<div class="container">
<div class="columns">
<div class="column col-3">
<ul class="nav">

View File

@ -9,7 +9,7 @@
z-index: 1;
top: 20;
left: 0;
overflow-x: hidden;
padding-left: 1.2rem;
padding-right: 2rem;
}
@ -17,13 +17,13 @@
height: 100%;
max-width: 160px;
z-index: 1;
overflow-x: hidden;
}
</style>
{% endblock %}
{% block content %}
<div class="container maindiv">
<div class="container">
<div class="columns">
<div class="column col-3">
<ul class="nav">

View File

@ -9,7 +9,6 @@
z-index: 1;
top: 20;
left: 0;
overflow-x: hidden;
padding-left: 1.2rem;
padding-right: 2rem;
}
@ -17,13 +16,12 @@
height: 100%;
max-width: 160px;
z-index: 1;
overflow-x: hidden;
}
</style>
{% endblock %}
{% block content %}
<div class="container maindiv">
<div class="container">
<div class="columns">
<div class="column col-3">
<ul class="nav">
@ -43,12 +41,57 @@
</div>
<div class="column col-9 panel">
<div class="panel-header">
<div class="panel-title h4">{{book['book_name']}}</div>
</div>
<div class="panel-body">
<div class="panel-title h3">{{book['book_name']}}</div>
{%if booktype|length > 0 %}
<div>
<mark>分类标签:</mark>
{% for atype in booktype %}
<span class="chip"> {{atype['type_name']}}</span>
{% endfor %}
</div>
{%endif%}
{%if book['book_author']%}
<div class="py-1">
<mark>作者:</mark><span class="px-2">{{book['book_author']}}</span>
</div>
{% endif %}
{%if book['book_publisher']%}
<div class="py-1">
<mark>出版社:</mark><span class="px-2">{{book['book_publisher']}}</span>
</div>
{% endif %}
{%if book['book_isbn']%}
<div class="py-1">
<mark>ISBN</mark><span class="px-2">{{book['book_isbn']}}</span>
</div>
{% endif %}
{%if book['book_lang']%}
<div class="py-1">
<mark>语言:</mark><span class="px-2">{{book['book_lang']}}</span>
</div>
{% endif %}
<div>
<a href="/book/update/{{book['book_id']}}/" class="btn btn-primary">编辑图书信息</a>
</div>
</div>
<div class="panel-body">
<div id="book-docs" class="card">
<div class="card-header">
<div class="card-title h5">文档1</div>
<div class="card-subtitle">
<span>大小:</span>
<span>日期:</span>
<div class="float-right">
<button class="btn btn-primary">下载</button>
<button class="btn">删除</button>
</div>
</div>
</div>
</div>
<div class="divider"></div>
<div id = "book-notes" class="card">
</div>
</div>
<div class="panel-footer">
Rendered @ {{cur_time}}

View File

@ -9,7 +9,7 @@
z-index: 1;
top: 20;
left: 0;
overflow-x: hidden;
padding-left: 1.2rem;
padding-right: 2rem;
}
@ -17,13 +17,13 @@
height: 100%;
max-width: 160px;
z-index: 1;
overflow-x: hidden;
}
</style>
{% endblock %}
{% block content %}
<div class="container maindiv">
<div class="container">
<div class="columns">
<div class="column col-3">
<ul class="nav">

View File

@ -9,7 +9,6 @@
z-index: 1;
top: 20;
left: 0;
overflow-x: hidden;
padding-left: 1.2rem;
padding-right: 2rem;
}
@ -17,13 +16,12 @@
height: 100%;
max-width: 160px;
z-index: 1;
overflow-x: hidden;
}
</style>
{% endblock %}
{% block content %}
<div class="container maindiv">
<div class="container">
<div class="columns">
<div class="column col-3">
<ul class="nav">

View File

@ -9,7 +9,6 @@
z-index: 1;
top: 20;
left: 0;
overflow-x: hidden;
padding-left: 1.2rem;
padding-right: 2rem;
}
@ -17,13 +16,12 @@
height: 100%;
max-width: 160px;
z-index: 1;
overflow-x: hidden;
}
</style>
{% endblock %}
{% block content %}
<div class="container maindiv">
<div class="container">
<div class="columns">
<div class="column col-3">
<ul class="nav">

View File

@ -0,0 +1,85 @@
{% extends 'base.html' %}
{% block header %}
<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">
<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">
{%if error%}
<div class="toast">
{{error}}
</div>
{% endif %}
<form method="post" class="form-group">
<label class="form-label" for="bookname">书名</label>
<input class="form-input" name="bookname" id="bookname" value="{{book['book_name']}}" required>
<label class="form-label" for="bookisbn">ISBN</label>
<input class="form-input" name="bookisbn" id="bookisbn" value="{{book['book_isbn']}}">
<label class="form-label" for="bookpublisher">出版社</label>
<input class="form-input" name="bookpublisher" id="bookpublisher" value="{{book['book_publisher']}}">
<label class="form-label" for="bookauthor">作者</label>
<input class="form-input" name="bookauthor" id="bookauthor" value="{{book['book_author']}}">
<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" value="{{booktype}}">
<div>
{% for atype in typelist%}
<span class="chip btn" onclick="switch_type('{{atype['type_name']}}')">{{atype['type_name']}}</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

@ -7,7 +7,7 @@ from werkzeug.security import generate_password_hash
from src.auth import login_required
from src.db import get_db
import sqlite3
import pymysql
import datetime
bp = Blueprint('user', __name__)
@ -15,16 +15,20 @@ 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()
cur = get_db().cursor()
cur.execute(
"select * from user_stat where user_id = %s", (g.user['user_id'],)
)
user_stat = cur.fetchone()
print(user_stat)
cur.close()
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()
cur = db.cursor()
error = None
if request.method == 'POST':
bookname = request.form['bookname']
@ -46,40 +50,43 @@ def addbook():
booklang = None
if len(booktype) == 0:
booktype = None
db.execute(
cur.execute(
"insert into book (`book_name`, `book_isbn`"
", `book_publisher`, `book_lang`, `book_author`, `user_id`) "
"values (?,?,?,?,?,?)",
"values (%s,%s,%s,%s,%s,%s)",
(bookname, bookisbn, bookpublisher, booklang, bookauthor, g.user['user_id'],))
db.commit()
bookid = db.execute("select max(book_id) from book").fetchone()
cur.execute("select max(book_id) from book")
bookid = cur.fetchone()
bookid = bookid['max(book_id)']
error = None
if booktype is not None:
booktype = booktype.strip()
if booktype[-1] != ';':
booktype += ';'
booktypes = booktype.split(";")
booktypes.remove("")
print(booktypes)
for booktype in booktypes:
typeid = db.execute("select type_id from typetable where type_name=?",
(booktype,)).fetchone()
cur.execute("select type_id from typetable where type_name=%s", (booktype,))
typeid = cur.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()
cur.execute("insert into typetable(`type_name`) values (%s)", (booktype,))
cur.execute("select type_id from typetable where type_name=%s", (booktype,))
typeid = cur.fetchone()
typeid = typeid['type_id']
try:
db.execute("insert into book_type values(?,?)",
(typeid, bookid))
cur.execute("insert into book_type values(%s,%s)",(typeid, bookid))
db.commit()
except sqlite3.Error as _e:
except pymysql.Error as _e:
error = "未知错误: %s" % (_e)
db.rollback()
if error is None:
error = "新建图书《%s》完成" % (bookname)
# else:
# return render_template("user/addbook.html", success=True)
typelist = db.execute("select type_name from typetable").fetchall()
cur.execute("select type_name from typetable")
typelist = cur.fetchall()
return render_template("user/addbook.html", typelist=typelist, error=error,
cur_time=datetime.datetime.now())
@ -87,6 +94,7 @@ def addbook():
@login_required
def tags():
db = get_db()
cur = db.cursor()
error = None
if request.method == 'POST':
typename = request.form['typename']
@ -95,13 +103,12 @@ def tags():
rowcount = 0
if error is None:
try:
rowcount = db.execute("insert into typetable(`type_name`) values(?)",
(typename,)).rowcount
rowcount = cur.execute("insert into typetable(`type_name`) values(%s)", (typename,))
db.commit()
except sqlite3.IntegrityError:
except pymysql.IntegrityError:
error = "类型名称已经存在: %s" % (typename)
db.rollback()
except sqlite3.Error as _e:
except pymysql.Error as _e:
error = "未知错误: %s" % (_e)
db.rollback()
if error is None:
@ -109,7 +116,8 @@ def tags():
error = "新建可能失败,再次检查是否完成"
else:
error = "新建类型\"%s\"完成" % (typename)
typelist = db.execute("select * from typetable").fetchall()
cur.execute("select * from typetable")
typelist = cur.fetchall()
return render_template("user/addtype.html", typelist=typelist, error=error,
cur_time=datetime.datetime.now())
@ -117,6 +125,7 @@ def tags():
@login_required
def removetype():
db = get_db()
cur = db.cursor()
tid_to_del = request.args.get("tid")
error = None
if tid_to_del is None or not tid_to_del.isnumeric():
@ -124,9 +133,9 @@ def removetype():
rowcnt = 0
if error is None:
try:
rowcnt = db.execute("delete from typetable where type_id=?", (tid_to_del,)).rowcount
rowcnt = cur.execute("delete from typetable where type_id=%s", (tid_to_del,))
db.commit()
except sqlite3.Error as _e:
except pymysql.Error as _e:
error = "删除失败:%s" % (_e)
db.rollback()
if error is None:
@ -134,6 +143,7 @@ def removetype():
error = "删除可能失败,再次检查是否完成"
else:
error = "删除(type_id=%s)完成" % tid_to_del
cur.close()
return render_template("user/result.html", opname="删除分类",
opresult=error, cur_time=datetime.datetime.now())
@ -143,6 +153,7 @@ def search():
attr_dict = {"书名":"book_name", "ISBN":"book_isbn",
"作者": "book_author", "出版社":"book_publisher", "分类": "specail1"}
db = get_db()
cur = db.cursor()
page = request.args.get('page')
page_lim = 10
page_off = 0
@ -169,20 +180,22 @@ def search():
bookattr=""
if error is None:
if queryval is None or len(queryval) == 0:
querystring = "select * from book where user_id=%d" % (g.user['user_id'])
querystring = "select * from book where user_id=%s" % (g.user['user_id'])
queryval = ""
elif bookattr == "分类":
querystring = "SELECT * from v_type_to_book WHERE user_id=%d AND type_name LIKE \'%%%s%%\'" % (g.user['user_id'], queryval)
querystring = "SELECT * from v_type_to_book WHERE user_id=%s AND type_name LIKE \'%%%s%%\'" % (g.user['user_id'], queryval)
else:
querystring = "select * from book where user_id=%d and %s like \'%%%s%%\'" % (g.user['user_id'], queryattr, queryval)
querystring = "select * from book where user_id=%s and %s like \'%%%s%%\'" % (g.user['user_id'], queryattr, queryval)
querystring += " limit %d offset %d" % (page_lim, page_off)
# print(querystring)
queryresult = db.execute(querystring).fetchall()
cur.execute(querystring)
queryresult = cur.fetchall()
page_last = False
if len(queryresult) < page_lim:
page_last = True
next_page_link = "/search?bookname=%s&bookattr=%s&page=%d" %(queryval, bookattr, page + 1)
prev_page_link = "/search?bookname=%s&bookattr=%s&page=%d" %(queryval, bookattr, page - 1)
next_page_link = "/search?bookname=%s&bookattr=%s&page=%s" %(queryval, bookattr, page + 1)
prev_page_link = "/search?bookname=%s&bookattr=%s&page=%s" %(queryval, bookattr, page - 1)
# print(prev_page_link, next_page_link)
return render_template("user/search.html",
cur_time=datetime.datetime.now(), error=error, queryresult=queryresult,
@ -193,8 +206,90 @@ def search():
@login_required
def book(id):
db = get_db()
book = db.execute("select * from book where book_id=?", (id,)).fetchone()
booktype = db.execute("select * from v_book_to_types where book_id=?", (book['book_id'], )).fetchall()
cur = db.cursor()
cur.execute("select * from book where book_id=%s", (id,))
book = cur.fetchone()
cur.execute("select * from v_book_to_types where book_id=%s", (book['book_id'], ))
booktype = cur.fetchall()
return render_template("/user/book.html",
book=book, booktype=booktype,
cur_time=datetime.datetime.now())
@bp.route("/book/update/<int:id>/", methods=("GET", "POST"))
@login_required
def book_update(id):
db = get_db()
cur = db.cursor()
error = None
if 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
cur.execute('update book set `book_name`=%s where `book_id`=%s', (bookname, id))
cur.execute('update book set `book_isbn`=%s where `book_id`=%s', (bookisbn, id))
cur.execute('update book set `book_publisher`=%s where `book_id`=%s', (bookpublisher, id))
cur.execute('update book set `book_lang`=%s where `book_id`=%s', (booklang, id))
cur.execute('update book set `book_author`=%s where `book_id`=%s', (bookauthor, id))
db.commit()
error = None
if booktype is not None:
booktype = booktype.strip()
if booktype[-1] != ';':
booktype += ';'
booktypes = booktype.split(";")
booktypes.remove("")
print(booktypes)
for booktype in booktypes:
cur.execute("select type_id from typetable where type_name=%s", (booktype,))
typeid = cur.fetchone()
if typeid is None:
cur.execute("insert into typetable(`type_name`) values (%s)", (booktype,))
cur.execute("select type_id from typetable where type_name=%s", (booktype,))
typeid = cur.fetchone()
typeid = typeid['type_id']
try:
cur.execute("insert into book_type values(%s,%s)",(typeid, id))
db.commit()
except pymysql.IntegrityError:
db.rollback()
except pymysql.Error as _e:
error = "未知错误: %s" % (_e)
db.rollback()
if error is None:
cur.close()
return redirect(url_for("user.book", id=id))
cur.execute("select * from book where book_id=%s", (id,))
bookinfo = cur.fetchone()
assert(bookinfo is not None)
cur.execute("select * from v_book_to_types where book_id=%s", (bookinfo['book_id'], ))
booktype = cur.fetchall()
cur.execute("select type_name from typetable")
typelist = cur.fetchall()
cur.close()
for k in bookinfo:
if bookinfo[k] is None:
bookinfo[k] = ''
booktypestr = ""
print(booktype)
for k in booktype:
booktypestr += k['type_name'] + ';'
return render_template("/user/updatebook.html",
book=bookinfo, booktype=booktypestr, typelist=typelist,
cur_time=datetime.datetime.now())