Browse Source

first commit

master
fghrsh 2 years ago
commit
386ce0b3de
  1. 19255
      assets/css/default.css
  2. 19
      assets/img/category-default.svg
  3. 19
      assets/img/home-default.svg
  4. 19
      assets/img/logo.svg
  5. 19
      assets/img/profile-default.svg
  6. 22
      assets/img/wishlist-default.svg
  7. 5074
      assets/js/bundle.js
  8. 13
      config.php
  9. 15
      index.php
  10. 26
      src/autoload.php
  11. 204
      src/controller/admin.php
  12. 55
      src/controller/default.php
  13. 99
      src/controller/user.php
  14. 63
      src/model/books.php
  15. 39
      src/model/categories.php
  16. 146
      src/model/database.php
  17. 71
      src/model/records.php
  18. 75
      src/model/stock.php
  19. 14
      src/model/template.php
  20. 54
      src/model/users.php
  21. 109
      src/router.php
  22. 49
      src/template/admins/add_book.php
  23. 24
      src/template/admins/add_category.php
  24. 59
      src/template/admins/add_stock.php
  25. 51
      src/template/admins/add_user.php
  26. 63
      src/template/admins/books.php
  27. 56
      src/template/admins/categories.php
  28. 41
      src/template/admins/delete_book.php
  29. 35
      src/template/admins/delete_category.php
  30. 54
      src/template/admins/delete_stock.php
  31. 40
      src/template/admins/delete_user.php
  32. 15
      src/template/admins/page_switch.php
  33. 68
      src/template/admins/stock.php
  34. 47
      src/template/admins/update_book.php
  35. 22
      src/template/admins/update_category.php
  36. 56
      src/template/admins/update_stock.php
  37. 45
      src/template/admins/update_user.php
  38. 64
      src/template/admins/users.php
  39. 65
      src/template/defaults/book.php
  40. 42
      src/template/defaults/index.php
  41. 42
      src/template/defaults/lists.php
  42. 17
      src/template/defaults/page_switch.php
  43. 44
      src/template/defaults/search.php
  44. 41
      src/template/defaults/user_profile.php
  45. 16
      src/template/example/example-popup.php
  46. 43
      src/template/example/example-user_profile.php
  47. 251
      src/template/example/example.php
  48. 5
      src/template/footer.php
  49. 71
      src/template/header.php
  50. 67
      src/template/side_nav.php
  51. 47
      src/template/users/info.php
  52. 27
      src/template/users/login.php
  53. 65
      src/template/users/record.php
  54. 33
      src/template/users/register.php
  55. 32
      src/template/users/update.php

19255
assets/css/default.css

File diff suppressed because it is too large

19
assets/img/category-default.svg

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
<title>Icon</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M19.00025,34 L10.00025,34 C9.73525,34 9.48025,34.106 9.29325,34.293 L0.29325,43.293 C-0.09775,43.684 -0.09775,44.316 0.29325,44.707 L9.29325,53.707 C9.48825,53.902 9.74425,54 10.00025,54 C10.25625,54 10.51225,53.902 10.70725,53.707 L19.70725,44.707 C19.89525,44.52 20.00025,44.265 20.00025,44 L20.00025,35 C20.00025,34.448 19.55225,34 19.00025,34 L19.00025,34 Z M10.00025,51.586 L2.41425,44 L4.00025,42.414 L11.58625,50 L10.00025,51.586 Z M18.00025,43.586 L13.00025,48.586 L5.41425,41 L10.41425,36 L18.00025,36 L18.00025,43.586 Z M15.00025,40.0001 C15.55225,40.0001 16.00025,39.5521 16.00025,39.0001 C16.00025,38.4481 15.55225,38.0001 15.00025,38.0001 C14.44825,38.0001 14.00025,38.4481 14.00025,39.0001 C14.00025,39.5521 14.44825,40.0001 15.00025,40.0001" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Desktop---Library" transform="translate(-42.000000, -124.000000)">
<g id="side-nav" transform="translate(42.000000, 90.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Icon" fill="#919EAB" xlink:href="#path-1"></use>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

19
assets/img/home-default.svg

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
<title>Icon</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M15.9999836,18.0002 L13.9999836,18.0002 L13.9999836,13.0002 C13.9999836,12.4482 13.5519836,12.0002 12.9999836,12.0002 L6.99998362,12.0002 C6.44798362,12.0002 5.99998362,12.4482 5.99998362,13.0002 L5.99998362,18.0002 L3.99998362,18.0002 L3.99998362,7.6712 L9.99998362,2.3382 L15.9999836,7.6712 L15.9999836,18.0002 Z M3.99998362,2.0002 L5.99998362,2.0002 L5.99998362,3.2172 L3.99998362,4.9952 L3.99998362,2.0002 Z M19.6649836,8.2522 L10.6649836,0.2522 C10.2859836,-0.0838 9.71398362,-0.0838 9.33498362,0.2522 L7.99998362,1.4392 L7.99998362,1.0002 C7.99998362,0.4482 7.55198362,0.0002 6.99998362,0.0002 L2.99998362,0.0002 C2.44798362,0.0002 1.99998362,0.4482 1.99998362,1.0002 L1.99998362,6.7732 L0.334983616,8.2522 C-0.0770163836,8.6202 -0.114016384,9.2512 0.251983616,9.6652 C0.619983616,10.0782 1.24998362,10.1142 1.66498362,9.7482 L1.99998362,9.4492 L1.99998362,19.0002 C1.99998362,19.5522 2.44798362,20.0002 2.99998362,20.0002 L6.99998362,20.0002 C7.55198362,20.0002 7.99998362,19.5522 7.99998362,19.0002 L7.99998362,14.0002 L11.9999836,14.0002 L11.9999836,19.0002 C11.9999836,19.5522 12.4479836,20.0002 12.9999836,20.0002 L16.9999836,20.0002 C17.5519836,20.0002 17.9999836,19.5522 17.9999836,19.0002 L17.9999836,9.4492 L18.3349836,9.7482 C18.5259836,9.9172 18.7629836,10.0002 18.9999836,10.0002 C19.2749836,10.0002 19.5499836,9.8872 19.7479836,9.6652 C20.1139836,9.2512 20.0769836,8.6202 19.6649836,8.2522 L19.6649836,8.2522 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Desktop---Library" transform="translate(-42.000000, -90.000000)">
<g id="side-nav" transform="translate(42.000000, 90.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Icon" fill="#919EAB" xlink:href="#path-1"></use>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

19
assets/img/logo.svg

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="200px" height="20px" viewBox="0 0 200 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
<title>logo</title>
<desc>白云图书馆</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Desktop---Library" transform="translate(-43.000000, -18.000000)" fill="#FFFFFF">
<g id="top-nav" transform="translate(-2.000000, 0.000000)">
<g id="logo" transform="translate(45.000000, 15.000000)">
<text id="Libre" font-family="Microsoft YaHei" font-size="22" font-weight="300">
<tspan x="21" y="20">白云图书馆</tspan>
</text>
<path d="M8,20 C12.418278,20 16,16.418278 16,12 C16,7.581722 12.418278,12 8,12 C3.581722,12 0,7.581722 0,12 C0,16.418278 3.581722,20 8,20 Z" id="Oval-2"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

19
assets/img/profile-default.svg

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="20px" viewBox="0 0 16 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
<title>Icon</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M17.7073,258.293 C17.9753,258.561 18.0683,258.957 17.9483,259.316 L16.9483,262.316 C16.8123,262.725 16.4303,263 16.0003,263 L4.0003,263 C3.5693,263 3.1873,262.725 3.0513,262.316 L2.0513,259.316 C1.9313,258.957 2.0253,258.561 2.2933,258.293 C2.4273,258.158 5.6353,255 10.0003,255 C14.3643,255 17.5723,258.158 17.7073,258.293 Z M15.2793,261 L15.8413,259.313 C14.9213,258.561 12.6863,257 10.0003,257 C7.2973,257 5.0733,258.558 4.1573,259.31 L4.7203,261 L15.2793,261 Z M10,245 C11.654,245 13,246.346 13,248 C13,249.654 11.654,251 10,251 C8.346,251 7,249.654 7,248 C7,246.346 8.346,245 10,245 Z M10,253 C12.757,253 15,250.757 15,248 C15,245.243 12.757,243 10,243 C7.243,243 5,245.243 5,248 C5,250.757 7.243,253 10,253" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Desktop---Library" transform="translate(-44.000000, -333.000000)">
<g id="side-nav" transform="translate(42.000000, 90.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Icon" fill="#919EAB" xlink:href="#path-1"></use>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

22
assets/img/wishlist-default.svg

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M19,11 L12,11 C11.447,11 11,11.447 11,12 L11,19 C11,19.553 11.447,20 12,20 L19,20 C19.553,20 20,19.553 20,19 L20,12 C20,11.447 19.553,11 19,11 L19,11 Z M8,11 L1,11 C0.447,11 0,11.447 0,12 L0,19 C0,19.553 0.447,20 1,20 L8,20 C8.553,20 9,19.553 9,19 L9,12 C9,11.447 8.553,11 8,11 L8,11 Z M8,0 L1,0 C0.447,0 0,0.447 0,1 L0,8 C0,8.553 0.447,9 1,9 L8,9 C8.553,9 9,8.553 9,8 L9,1 C9,0.447 8.553,0 8,0 L8,0 Z M2,18 L7,18 L7,13 L2,13 L2,18 Z M2,7 L7,7 L7,2 L2,2 L2,7 Z M13,18 L13,13 L18,13 L18,18 L13,18 Z M12,6 C11.447,6 11,5.553 11,5 C11,4.447 11.447,4 12,4 L14,4 L14,2 C14,1.447 14.447,1 15,1 C15.553,1 16,1.447 16,2 L16,4 L18,4 C18.553,4 19,4.447 19,5 C19,5.553 18.553,6 18,6 L16,6 L16,8 C16,8.553 15.553,9 15,9 C14.447,9 14,8.553 14,8 L14,6 L12,6 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Desktop---Picks" transform="translate(-41.000000, -366.000000)">
<g id="Group" transform="translate(41.000000, 366.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Icon" fill="#919EAB" xlink:href="#path-1"></use>
<g id="⌘/🌈/Gray" mask="url(#mask-2)" fill="#919EAB">
<rect id="Rectangle-2" x="0" y="0" width="23" height="20"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

5074
assets/js/bundle.js

File diff suppressed because one or more lines are too long

13
config.php

@ -0,0 +1,13 @@
<?php
$GLOBALS['config'] = [
'name' => '白云图书馆',
'database' => [
'host' => 'mysql',
'database' => 'books',
'username' => 'books_user',
'password' => 'JVjZ*34%C#FdH!Tz'
],
'salt' => 'Baiyun Library Management System: ',
'timezone' => 'Asia/Shanghai',
'environment' => 'development'
];

15
index.php

@ -0,0 +1,15 @@
<?php
date_default_timezone_set($GLOBALS['config']['timezone']);
session_set_cookie_params(24 * 3600);
session_start();
require('src/autoload.php');
define('APP_ROOT', dirname(__FILE__));
//if ($GLOBALS['config']['environment'] == 'development') {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(-1);
//}
new autoload();
new router();

26
src/autoload.php

@ -0,0 +1,26 @@
<?php
class autoload {
public function __construct() {
require(APP_ROOT.'/config.php');
require(APP_ROOT.'/src/router.php');
$this->auto_require_files(APP_ROOT.'/src/model');
$this->auto_require_files(APP_ROOT.'/src/controller');
}
private function auto_require_files($dir) {
foreach ($this->scan_dir_files($dir) as $file) require($file);
}
private function scan_dir_files($dir) {
foreach (scandir($dir) as $item) {
if ($item != '..' && $item != '.') {
if (is_dir($dir.'/'.$item)) {
$files = array_merge($files, $this->scan_dir_files($dir.'/'.$item));
} else $files[] = $dir.'/'.$item;
}
}
return $files;
}
}

204
src/controller/admin.php

@ -0,0 +1,204 @@
<?php
use model\books;
use model\users;
use model\stock;
use model\records;
use model\template;
use model\categories;
class admin_controller {
public function books() {
$page = $_GET['page'] ?? 1;
foreach ($books = books::list_books($page) as $k => $v)
$books[$k]['stock'] = stock::count_in_stock_by_bid($v['bid']).'/'.stock::count_stock_by_bid($v['bid']);
$this->template('书籍管理', 'books', ['books' => $books, 'page' => $page, 'count' => books::count_books(), 'stock' => stock::count_stock()]);
}
public function users() {
$page = $_GET['page'] ?? 1;
$users = users::list_users($page);
$this->template('用户管理', 'users', ['users' => $users, 'page' => $page, 'count' => users::count_users(), 'stock' => stock::count_out_stock()]);
}
public function stock() {
$page = $_GET['page'] ?? 1;
if (isset($_GET['bid']) && is_numeric($_GET['bid'])) {
$books = stock::list_stock_by_bid($_GET['bid'], $page);
$count = stock::count_stock_by_bid($_GET['bid']);
$stock = stock::count_in_stock_by_bid($_GET['bid']);
} else {
$books = stock::list_stock($page);
$count = stock::count_stock();
$stock = stock::count_in_stock();
} $this->template('库存管理', 'stock', ['books' => $books, 'page' => $page, 'count' => $count, 'stock' => $stock]);
}
public function categories() {
$page = $_GET['page'] ?? 1;
$categories = categories::list_categories($page);
$this->template('分类管理', 'categories', ['categories' => $categories, 'page' => $page, 'count' => categories::count_categories(), 'stock' => stock::count_stock()]);
}
public function add_user() {
$this->template('添加用户', 'add_user');
}
public function update_user() {
if (isset($_GET['uid']) && is_numeric($_GET['uid'])) {
$this->template('更新用户', 'update_user', ['user' => users::get_user_by_id($_GET['uid'])]);
} else header('Location: /admin/users');
}
public function delete_user() {
if (isset($_GET['uid']) && is_numeric($_GET['uid'])) {
$this->template('删除用户', 'delete_user', ['user' => users::get_user_by_id($_GET['uid'])]);
} else header('Location: /admin/users');
}
public function add_book() {
$categories = categories::get_categories();
$this->template('添加书籍', 'add_book', ['categories' => $categories]);
}
public function update_book() {
if (isset($_GET['bid']) && is_numeric($_GET['bid'])) {
$this->template('更新书籍', 'update_book', ['book' => books::get_book_by_id($_GET['bid']), 'categories' => categories::get_categories()]);
} else header('Location: /admin/books');
}
public function delete_book() {
if (isset($_GET['bid']) && is_numeric($_GET['bid'])) {
$this->template('删除书籍', 'delete_book', ['book' => books::get_book_by_id($_GET['bid']), 'categories' => categories::get_categories()]);
} else header('Location: /admin/books');
}
public function add_stock() {
if (isset($_GET['bid']) && is_numeric($_GET['bid'])) {
$this->template('添加库存', 'add_stock', ['book' => books::get_book_by_id($_GET['bid']), 'categories' => categories::get_categories()]);
} else header('Location: /admin/stock');
}
public function update_stock() {
if (isset($_GET['sid']) && is_numeric($_GET['sid'])) {
$this->template('更新库存', 'update_stock', ['book' => stock::get_stock_by_id($_GET['sid']), 'categories' => categories::get_categories()]);
} else header('Location: /admin/stock');
}
public function delete_stock() {
if (isset($_GET['sid']) && is_numeric($_GET['sid'])) {
$this->template('删除库存', 'delete_stock', ['book' => stock::get_stock_by_id($_GET['sid']), 'categories' => categories::get_categories()]);
} else header('Location: /admin/stock');
}
public function add_category() {
$this->template('添加分类', 'add_category');
}
public function update_category() {
if (isset($_GET['cid']) && is_numeric($_GET['cid'])) {
$this->template('更新分类', 'update_category', ['category' => categories::get_category_by_id($_GET['cid'])]);
} else header('Location: /admin/categories');
}
public function delete_category() {
if (isset($_GET['cid']) && is_numeric($_GET['cid'])) {
$this->template('删除分类', 'delete_category', ['category' => categories::get_category_by_id($_GET['cid']), 'categories' => categories::get_categories()]);
} else header('Location: /admin/categories');
}
public function do_add_user() {
$username = $_POST['username'];
if (!(strlen($username) <= 30 && preg_match('/^[a-zA-Z_][a-zA-Z0-9_]+$/u', $username)))
exit(header('Location: /admin/add-user?page='.$_GET['page'].'&error=用户名不合规'));
$password = $_POST['password'];
if ($password != $_POST['confirm'])
exit(header('Location: /admin/add-user?page='.$_GET['page'].'&error=两次输入密码不一致'));
header('Location: ' . (users::add_user($username, $password, $_POST['sex'], $_POST['birthday'], $_POST['id_card'], $_POST['borrow_num'], $_POST['type']) ?
'/admin/users?page='.$_GET['page'] : '/admin/add-user?page='.$_GET['page'].'&error=数据库错误'));
}
public function do_update_user() {
if (isset($_GET['uid']) && is_numeric($_GET['uid'])) {
if (empty($password = $_POST['password']))
$password = null;
elseif ($password != $_POST['confirm'])
exit(header('Location: /admin/update-user?page='.$_GET['page'].'&uid='.$_GET['uid'].'&error=两次输入密码不一致'));
header('Location: ' . (users::update_user($_GET['uid'], $password, $_POST['sex'], $_POST['birthday'], $_POST['id_card'], $_POST['borrow_num'], $_POST['type']) ?
'/admin/users?page='.$_GET['page'] : '/admin/update-user?page='.$_GET['page'].'&uid='.$_GET['uid'].'&error=数据库错误'));
} else header('Location: /admin/users?page='.$_GET['page']);
}
public function do_delete_user() {
if (isset($_GET['uid']) && is_numeric($_GET['uid'])) {
header('Location: ' . (users::del_user_by_id($_GET['uid']) ?
'/admin/users?page='.$_GET['page'] : '/admin/delete-user?page='.$_GET['page'].'&uid='.$_GET['uid'].'&error=数据库错误'));
} else header('Location: /admin/users?page='.$_GET['page']);
}
public function do_add_book() {
header('Location: ' . (books::add_book($_POST['name'], $_POST['author'], $_POST['publish'], $_POST['isbn'], $_POST['cover'], $_POST['type'], $_POST['lang']) ?
'/admin/books?page='.$_GET['page'] : '/admin/add-book?page='.$_GET['page'].'&error=数据库错误'));
}
public function do_update_book() {
if (isset($_GET['bid']) && is_numeric($_GET['bid'])) {
header('Location: ' . (books::update_book($_GET['bid'], $_POST['name'], $_POST['author'], $_POST['publish'], $_POST['isbn'], $_POST['cover'], $_POST['type'], $_POST['lang']) ?
'/admin/books?page='.$_GET['page'] : '/admin/update-book?page='.$_GET['page'].'&bid='.$_GET['bid'].'&error=数据库错误'));
} else header('Location: /admin/books?page='.$_GET['page']);
}
public function do_delete_book() {
if (isset($_GET['bid']) && is_numeric($_GET['bid'])) {
header('Location: ' . (books::del_book_by_id($_GET['bid']) ?
'/admin/books?page='.$_GET['page'] : '/admin/delete-book?page='.$_GET['page'].'&bid='.$_GET['bid'].'&error=数据库错误'));
} else header('Location: /admin/books?page='.$_GET['page']);
}
public function do_add_stock() {
if (isset($_GET['bid']) && is_numeric($_GET['bid'])) {
header('Location: ' . (stock::add_stock($_GET['bid'], $_POST['place'], $_POST['health'], $_POST['state']) ?
'/admin/stock?bid='.$_GET['bid'] : '/admin/add-stock?page='.$_GET['page'].'%bid='.$_GET['bid'].'&error=数据库错误'));
} else header('Location: /admin/stock?bid='.$_GET['bid'].'&page='.$_GET['page']);
}
public function do_update_stock() {
if (isset($_GET['sid']) && isset($_GET['bid']) && is_numeric($_GET['sid']) && is_numeric($_GET['bid'])) {
header('Location: ' . (stock::update_stock($_GET['sid'], $_GET['bid'], $_POST['place'], $_POST['health'], $_POST['state']) ?
'/admin/stock?page='.$_GET['page'] : '/admin/update-stock?page='.$_GET['page'].'&sid='.$_GET['sid'].'&bid='.$_GET['bid'].'&error=数据库错误'));
} else header('Location: /admin/stock?page='.$_GET['page']);
}
public function do_delete_stock() {
if (isset($_GET['sid']) && is_numeric($_GET['sid'])) {
header('Location: ' . (stock::del_stock_by_id($_GET['sid']) ?
'/admin/stock?page='.$_GET['page'] : '/admin/delete-stock?page='.$_GET['page'].'&sid='.$_GET['sid'].'&error=数据库错误'));
} else header('Location: /admin/stock?page='.$_GET['page']);
}
public function do_add_category() {
header('Location: ' . (categories::add_category($_POST['name']) ?
'/admin/categories?page='.$_GET['page'] : '/admin/add-categories?page='.$_GET['page'].'&error=数据库错误'));
}
public function do_update_category() {
if (isset($_GET['cid']) && is_numeric($_GET['cid'])) {
header('Location: ' . (categories::update_category($_GET['cid'], $_POST['name']) ?
'/admin/categories?page='.$_GET['page'] : '/admin/update-category?page='.$_GET['page'].'&cid='.$_GET['cid'].'&error=数据库错误'));
} else header('Location: /admin/categories?page='.$_GET['page']);
}
public function do_delete_category() {
if (isset($_GET['cid']) && is_numeric($_GET['cid'])) {
header('Location: ' . (books::update_book_category($_GET['cid'], $_POST['category']) && categories::del_category_by_id($_GET['cid']) ?
'/admin/categories?page='.$_GET['page'] : '/admin/delete-category?page='.$_GET['page'].'&cid='.$_GET['cid'].'&error=数据库错误'));
} else header('Location: /admin/categories?page='.$_GET['page']);
}
private function template($title, $name, $parameters = []) {
template::render('admins', $name, array_merge(['title' => $title], $parameters));
}
}

55
src/controller/default.php

@ -0,0 +1,55 @@
<?php
use model\books;
use model\stock;
use model\records;
use model\template;
use model\categories;
class default_controller {
public function index() {
$page = $_GET['page'] ?? 1;
$count = records::count_hot_records();
$books = records::list_hot_records($page);
$categories = categories::get_categories();
$records = isset($_SESSION['user']) ? records::get_in_records_by_uid($_SESSION['user']['uid']) : null;
$records_count = isset($_SESSION['user']) ? records::count_in_records_by_uid($_SESSION['user']['uid']) : 0;
$this->template('首页', 'index', ['books' => $books, 'page' => $page, 'count' => $count, 'categories' => $categories, 'records' => $records, 'records_count' => $records_count]);
}
public function lists() {
$page = $_GET['page'] ?? 1;
$count = books::count_books();
$books = books::list_books($page);
$categories = categories::get_categories();
$records = isset($_SESSION['user']) ? records::get_in_records_by_uid($_SESSION['user']['uid']) : null;
$records_count = isset($_SESSION['user']) ? records::count_in_records_by_uid($_SESSION['user']['uid']) : 0;
$this->template('书籍列表', 'lists', ['books' => $books, 'page' => $page, 'count' => $count, 'categories' => $categories, 'records' => $records, 'records_count' => $records_count]);
}
public function search() {
$page = $_GET['page'] ?? 1;
if (isset($_GET['s']) && !empty($_GET['s'])) {
$word = $_GET['s'] ?? '';
$books = books::find_books($word, $page);
$count = books::count_find_books($word);
$categories = categories::get_categories();
} else $word = $books = $count = $categories = null;
$records = isset($_SESSION['user']) ? records::get_in_records_by_uid($_SESSION['user']['uid']) : null;
$records_count = isset($_SESSION['user']) ? records::count_in_records_by_uid($_SESSION['user']['uid']) : 0;
$this->template('馆存查询', 'search', ['books' => $books, 'page' => $page, 'count' => $count, 'categories' => $categories, 'records' => $records, 'records_count' => $records_count]);
}
public function book($bid) {
$page = $_GET['page'] ?? 1;
$count = stock::count_stock_by_bid($bid);
$stock = stock::count_in_stock_by_bid($bid);
$books = stock::list_stock_by_bid($bid, $page);
$this->template('库存查询', 'book', ['books' => $books, 'page' => $page, 'count' => $count, 'stock' => $stock]);
}
private function template($title, $name, $parameters = []) {
template::render('defaults', $name, array_merge(['title' => $title], $parameters));
}
}

99
src/controller/user.php

@ -0,0 +1,99 @@
<?php
use model\users;
use model\stock;
use model\records;
use model\template;
class user_controller {
public function info() {
$page = $_GET['page'] ?? 1;
$this->template('个人资料', 'info');
}
public function record() {
$page = $_GET['page'] ?? 1;
$books = records::list_records_by_uid($_SESSION['user']['uid'], $page);
$count = records::count_records_by_uid($_SESSION['user']['uid']);
$stock = records::count_in_records_by_uid($_SESSION['user']['uid']);
$this->template('借书记录', 'record', ['books' => $books, 'page' => $page, 'count' => $count, 'stock' => $stock]);
}
public function update() {
$this->template('更新信息', 'update');
}
public function login() {
$this->template('用户登录', 'login');
}
public function register() {
$this->template('用户注册', 'register');
}
public function update_stock() {
if (isset($_GET['sid']) && is_numeric($_GET['sid']) && isset($_GET['bid']) && is_numeric($_GET['bid'])) {
if (stock::update_stock_state($_GET['sid'], 1))
records::add_record($_GET['bid'], $_SESSION['user']['uid'], $_GET['sid'], time());
} header('Location: /book/'.$_GET['bid'].'?page='.$_GET['page']);
}
public function update_record() {
if (isset($_GET['rid']) && is_numeric($_GET['rid']) && isset($_GET['sid']) && is_numeric($_GET['sid'])) {
if (records::update_record($_GET['rid'], time())) stock::update_stock_state($_GET['sid'], 0);
} header('Location: /user/record?page='.$_GET['page']);
}
public function do_login() {
$username = $_POST['username'];
$password = $_POST['password'];
if (!(strlen($username) <= 30 && preg_match('/^[a-zA-Z_][a-zA-Z0-9_]+$/u', $username)))
exit(header('Location: /user/login?error=用户名不合规'));
if ($user = users::get_user($username)) {
if ($user['password'] == hash('sha256', $GLOBALS['config']['salt'].$password)) {
$_SESSION['user'] = $user;
header('Location: /user/info');
} else header('Location: /user/login?error=密码错误');
} else header('Location: /user/login?error=用户不存在');
}
public function do_logout() {
session_destroy();
header('Location: /user/login?error=注销成功');
}
public function do_update() {
$sex = $_POST['sex'];
$birthday = $_POST['birthday'];
if (empty($password = $_POST['password']))
$password = null;
elseif ($password != $_POST['confirm'])
exit(header('Location: /user/update?error=两次输入密码不一致'));
if (users::update_user($_SESSION['user']['uid'], $password, $sex, $birthday, $_SESSION['user']['id_card'], $_SESSION['user']['borrow_num'], $_SESSION['user']['type'])) {
session_destroy();
header('Location: /user/login?error=更新成功,请重新登录');
} else header('Location: /user/update?error=数据库错误');
}
public function do_register() {
$username = $_POST['username'];
if (!(strlen($username) <= 30 && preg_match('/^[a-zA-Z_][a-zA-Z0-9_]+$/u', $username)))
exit(header('Location: /user/register?error=用户名不合规'));
$id_card = $_POST['id_card'];
if (strlen($id_card) < 10 || !is_numeric($id_card))
exit(header('Location: /user/register?error=身份证不合规'));
$password = $_POST['password'];
if ($password != $_POST['confirm'])
exit(header('Location: /user/register?error=两次输入密码不一致'));
if (users::add_user($username, $password, 0, '1900-01-01', $id_card, 15, 0))
header('Location: /user/login?error=注册成功,请登录');
else header('Location: /user/register?error=数据库错误');
}
private function template($title, $name, $parameters = []) {
template::render('users', $name, array_merge(['title' => $title], $parameters));
}
}

63
src/model/books.php

@ -0,0 +1,63 @@
<?php
namespace model;
use model\database;
class books {
public static function get_book_by_id(int $bid) {
return (new database())->table('books')->where(['bid' => $bid])->select();
}
public static function del_book_by_id(int $bid) {
return (new database())->table('books')->where(['bid' => $bid])->delete();
}
public static function add_book($name, $author, $publish, $isbn, $cover, $cid, $lang) {
return (new database())->table('books')->insert([
'name' => $name,
'author' => $author,
'publish' => $publish,
'isbn' => $isbn,
'cover' => $cover,
'cid' => (int)$cid,
'lang' => $lang
]);
}
public static function update_book(int $bid, $name, $author, $publish, $isbn, $cover, $cid, $lang) {
return (new database())->table('books')->where(['bid' => $bid])->update([
'name' => $name,
'author' => $author,
'publish' => $publish,
'isbn' => $isbn,
'cover' => $cover,
'cid' => (int)$cid,
'lang' => $lang
]);
}
public static function update_book_category(int $cid, $category) {
return (new database())->table('books')->where(['cid' => $cid])->update(['cid' => (int)$category]);
}
public static function list_books(int $page = 1) {
$books = (new database())->table('books')->page(20, $page);
return isset($books[0]['bid']) ? $books : [$books];
}
public static function find_books($word, int $page = 1) {
$books = (new database())->table('books')->like('name', $word)->page(20, $page);
return isset($books[0]['bid']) ? $books : [$books];
}
public static function count_books() {
return (new database())->table('books')->count();
}
public static function count_find_books($word) {
return (new database())->table('books')->like('name', $word)->count();
}
}

39
src/model/categories.php

@ -0,0 +1,39 @@
<?php
namespace model;
use model\database;
class categories {
public static function get_category_by_id(int $cid) {
return (new database())->table('categories')->where(['cid' => $cid])->select();
}
public static function del_category_by_id(int $cid) {
return (new database())->table('categories')->where(['cid' => $cid])->delete();
}
public static function add_category($name) {
return (new database())->table('categories')->insert(['name' => $name]);
}
public static function update_category(int $cid, $name) {
return (new database())->table('categories')->where(['cid' => $cid])->update(['name' => $name]);
}
public static function get_categories() {
$categories = (new database())->table('categories')->select();
return isset($categories[0]['cid']) ? $categories : [$categories];
}
public static function list_categories(int $page = 1) {
$categories = (new database())->table('categories')->page(20, $page);
return isset($categories[0]['cid']) ? $categories : [$categories];
}
public static function count_categories() {
return (new database())->table('categories')->count();
}
}

146
src/model/database.php

@ -0,0 +1,146 @@
<?php
namespace model;
class database {
private $pdo = null, $table, $where, $order, $limit, $prepare;
public function __construct() {
if ($this->pdo == null) {
try {
$this->pdo = new \PDO('mysql:host='.$GLOBALS['config']['database']['host'].';dbname='.$GLOBALS['config']['database']['database'],
$GLOBALS['config']['database']['username'], $GLOBALS['config']['database']['password'], [\PDO::ATTR_PERSISTENT => true]);
} catch (PDOException $e) {
exit('Error: ' . $e->getMessage());
}
}
$this->table = null;
$this->where = [];
$this->order = '';
$this->limit = '';
$this->prepare = '';
}
public function table(string $table) {
$this->table = $table;
return $this;
}
public function where(array $where) {
$this->where = array_merge($this->where, $where);
return $this;
}
public function like($name, $word) {
$this->order = ' where `'.$name.'` like "%'.$word.'%"';
return $this;
}
public function group_by($name) {
$this->order = ' group by `'.$name.'`';
return $this;
}
public function select($select = null) {
$this->prepare_where();
if (is_array($select)) {
$select = '`'.implode('`, `', $select).'`';
} elseif ($select == 'count(*)') {
$select = 'count(*)';
} elseif (!empty($select)) {
$select = '`'.$select.'`';
} else {
$select = '*';
}
$db = $this->pdo->prepare("select $select from `$this->table`$this->where$this->order$this->limit");
$db->execute($this->prepare);
if ($db = $db->fetchAll(\PDO::FETCH_ASSOC))
return count($db) > 1 ? $db : $db[0];
else return false;
}
public function insert(array $data) {
if (count($data) > 1) {
$keys = '`'.implode('`, `', array_keys($data)).'`';
foreach ($data as $v) $values[] = '?';
$values = implode(', ', $values);
} else {
$keys = '`'.array_keys($data)[0].'`';
$values = '?';
}
$db = $this->pdo->prepare("insert into `$this->table`($keys) values($values)");
return $db->execute(array_values($data));
}
public function update(array $data) {
$this->prepare_where();
if (count($data) > 1) {
$update = '`'.implode('` = ?, `', array_keys($data)).'` = ?';
} else {
$update = '`'.array_keys($data)[0].'` = ?';
}
$db = $this->pdo->prepare("update `$this->table` set $update$this->where");
return $db->execute(array_merge(array_values($data), $this->prepare));
}
public function delete() {
$this->prepare_where();
$db = $this->pdo->prepare("delete from `$this->table`$this->where");
return $db->execute($this->prepare);
}
public function count() {
return $this->select('count(*)')['count(*)'];
}
public function last($last) {
$this->order = ' order by `'.$last.'` desc';
$this->limit = ' limit 1';
return $this->select();
}
public function page(int $limit, int $page) {
$this->limit = ' limit '.($page-1)*$limit.', '.$limit;
return $this->select();
}
public function pdo_query($sql) {
$db = $this->pdo->query($sql);
if ($db = $db->fetchAll(\PDO::FETCH_ASSOC))
return count($db) > 1 ? $db : $db[0];
else return false;
}
public function pdo_prepare($sql) {
$this->prepare = $sql;
return $this;
}
public function execute($arr) {
$db = $this->pdo->prepare($this->prepare);
$db->execute($arr);
if ($db = $db->fetchAll(\PDO::FETCH_ASSOC))
return count($db) > 1 ? $db : $db[0];
else return false;
}
private function prepare_where() {
$where = '';
$this->prepare = [];
if (!empty($this->where) && is_array($this->where)) {
$where = ' where ';
if (count($this->where) > 1) {
$where .= '`'.implode('` = ? and `', array_keys($this->where)).'` = ?';
} else $where .= '`'.array_keys($this->where)[0].'` = ?';
$this->prepare = array_values($this->where);
}
$this->where = $where;
}
}

71
src/model/records.php

@ -0,0 +1,71 @@
<?php
namespace model;
use model\database;
class records {
public static function get_records_by_uid(int $uid) {
$records = ((new database())->pdo_prepare(
'select r.rid, b.bid, b.cover'.
' from records r left join books b on r.bid = b.bid where r.uid = :uid')->execute([':uid' => $uid])) ?? false;
return isset($records[0]['rid']) ? $records : [$records];
}
public static function get_in_records_by_uid(int $uid) {
$records = ((new database())->pdo_prepare(
'select r.rid, b.bid, b.cover'.
' from records r left join books b on r.bid = b.bid where r.uid = :uid and r.state = 0')->execute([':uid' => $uid])) ?? false;
return isset($records[0]['rid']) ? $records : [$records];
}
public static function add_record($bid, $uid, $sid, $borrow_time) {
return (new database())->table('records')->insert([
'bid' => $bid,
'uid' => $uid,
'sid' => $sid,
'borrow_time' => $borrow_time,
'state' => 0
]);
}
public static function update_record($rid, $return_time) {
return (new database())->table('records')->where(['rid' => $rid])->update(['return_time' => $return_time, 'state' => 1]);
}
public static function list_hot_records(int $page = 1) {
$records = ((new database())->pdo_query(
'select b.bid, b.cid, b.name, b.author, b.publish, b.isbn, b.cover, b.lang, any_value(r.borrow_time) as borrow_time'.
' from records r left join books b on r.bid = b.bid group by b.bid order by borrow_time desc limit '.(($page-1)*20).', 20')) ?? false;
return isset($records[0]['bid']) ? $records : [$records];
}
public static function list_records_by_uid(int $uid, int $page = 1) {
$records = ((new database())->pdo_prepare(
'select r.rid, r.sid, b.name, b.author, b.publish, b.isbn, r.borrow_time, r.return_time, r.state'.
' from records r left join books b on r.bid = b.bid where r.uid = :uid limit '.(($page-1)*20).', 20')->execute([':uid' => $uid])) ?? false;
return isset($records[0]['rid']) ? $records : [$records];
}
public static function count_records() {
return (new database())->table('records')->count();
}
public static function count_hot_records() {
return (new database())->pdo_query('select count(*) from (select `bid` as `count` from `records` group by `bid`) as c')['count(*)'] ?? 0;
}
public static function count_records_by_uid(int $uid) {
return (new database())->table('records')->where(['uid' => $uid])->count();
}
public static function count_in_records() {
return (new database())->table('records')->where(['state' => 0])->count();
}
public static function count_in_records_by_uid(int $uid) {
return (new database())->table('records')->where(['uid' => $uid, 'state' => 0])->count();
}
}

75
src/model/stock.php

@ -0,0 +1,75 @@
<?php
namespace model;
use model\database;
class stock {
public static function get_stock_by_id(int $sid) {
return ((new database())->pdo_prepare(
'select s.sid, b.bid, b.cid, b.name, b.isbn, b.author, b.publish, b.cover, b.lang, s.place, s.health, s.state'.
' from stock s left join books b on s.bid = b.bid where s.sid = :sid')->execute([':sid' => $sid])) ?? false;
}
public static function del_stock_by_id(int $sid) {
return (new database())->table('stock')->where(['sid' => $sid])->delete();
}
public static function add_stock($bid, $place, $health, $state) {
return (new database())->table('stock')->insert([
'bid' => $bid,
'place' => $place,
'health' => $health,
'state' => $state
]);
}
public static function update_stock(int $sid, $bid, $place, $health, $state) {
return (new database())->table('stock')->where(['sid' => $sid])->update([
'bid' => $bid,
'place' => $place,
'health' => $health,
'state' => $state
]);
}
public static function update_stock_state(int $sid, $state) {
return (new database())->table('stock')->where(['sid' => $sid])->update(['state' => $state]);
}
public static function count_stock() {
return (new database())->table('stock')->count();
}
public static function count_in_stock() {
return (new database())->table('stock')->where(['state' => 0])->count();
}
public static function count_out_stock() {
return (new database())->table('stock')->where(['state' => 1])->count();
}
public static function count_stock_by_bid(int $bid) {
return (new database())->table('stock')->where(['bid' => $bid])->count();
}
public static function count_in_stock_by_bid(int $bid) {
return (new database())->table('stock')->where(['bid' => $bid, 'state' => 0])->count();
}
public static function list_stock(int $page = 1) {
$stock = (new database())->pdo_query(
'select s.sid, b.bid, b.cid, b.name, b.isbn, b.author, b.publish, b.cover, b.lang, s.place, s.health, s.state'.
' from stock s left join books b on s.bid = b.bid limit '.(($page-1)*20).', 20');
return isset($stock[0]['sid']) ? $stock : [$stock];
}
public static function list_stock_by_bid(int $bid, int $page = 1) {
$stock = (new database())->pdo_query(
'select s.sid, b.bid, b.cid, b.name, b.isbn, b.author, b.publish, b.cover, b.lang, s.place, s.health, s.state'.
' from stock s left join books b on s.bid = b.bid where s.bid = '.$bid.' limit '.(($page-1)*20).', 20');
return isset($stock[0]['sid']) ? $stock : [$stock];
}
}

14
src/model/template.php

@ -0,0 +1,14 @@
<?php
namespace model;
class template {
public static function render($cont, $name, $parameters = []) {
foreach ($parameters as $k => $v) $$k = $v;
require(APP_ROOT.'/src/template/header.php');
require(APP_ROOT.'/src/template/side_nav.php');
require(APP_ROOT.'/src/template/'.$cont.'/'.$name.'.php');
require(APP_ROOT.'/src/template/footer.php');
}
}

54
src/model/users.php

@ -0,0 +1,54 @@
<?php
namespace model;
use model\database;
class users {
public static function get_user(string $username) {
return (new database())->table('users')->where(['username' => $username])->select();
}
public static function get_user_by_id(int $uid) {
return (new database())->table('users')->where(['uid' => $uid])->select();
}
public static function del_user_by_id(int $uid) {
return (new database())->table('users')->where(['uid' => $uid])->delete();
}
public static function add_user($username, $password, $sex, $birthday, $id_card, $borrow_num = 15, $type = 0) {
return (new database())->table('users')->insert([
'username' => $username,
'password' => hash('sha256', $GLOBALS['config']['salt'].$password),
'birthday' => $birthday,
'sex' => (int)$sex,
'id_card' => $id_card,
'borrow_num' => (int)$borrow_num,
'type' => (int)$type
]);
}
public static function update_user(int $uid, $password, $sex, $birthday, $id_card, $borrow_num, $type) {
$update = [
'sex' => (int)$sex,
'birthday' => $birthday,
'id_card' => $id_card,
'borrow_num' => $borrow_num,
'type' => $type,
];
if (!empty($password)) $update['password'] = hash('sha256', $GLOBALS['config']['salt'].$password);
return (new database())->table('users')->where(['uid' => $uid])->update($update);
}
public static function list_users(int $page = 1) {
$users = (new database())->table('users')->page(20, $page);
return isset($users[0]['uid']) ? $users : [$users];
}
public static function count_users() {
return (new database())->table('users')->count();
}
}

109
src/router.php

@ -0,0 +1,109 @@
<?php
class router {
public function __construct() {
$router = [
'/' => ['index', 1],
'/book' => ['book', 0],
'/user' => ['user', 0],
'/admin' => ['admin', 0],
'/lists' => ['lists', 1],
'/search' => ['search', 1]
];
$to = ''; $uri = explode('?', $_SERVER['REQUEST_URI'])[0];
foreach ($router as $k => $v)
if ($k == ($v[1] ? $uri : substr($uri, 0, strlen($k)))) $to = $v[0];
switch ($to) {
case 'user':
$controller = new user_controller();
switch (explode('/', $uri)[2] ?? null) {
case 'login': $controller->login(); break;
case 'register': $controller->register(); break;
case 'info': $this->check_login(); $controller->info(); break;
case 'record': $this->check_login(); $controller->record(); break;
case 'update': $this->check_login(); $controller->update(); break;
case 'update-stock': $this->check_login(); $controller->update_stock(); break;
case 'update-record': $this->check_login(); $controller->update_record(); break;
case 'do': switch (explode('/', $uri)[3] ?? null) {
case 'login': $controller->do_login(); break;
case 'register': $controller->do_register(); break;
case 'logout': $this->check_login(); $controller->do_logout(); break;
case 'update': $this->check_login(); $controller->do_update(); break;
default: break;
} break;
default:
header('Location: /user/'.($this->check_login(0)?'info':'login')); break;
} break;
case 'admin':
if (isset($_SESSION['user']) && $_SESSION['user']['type'] == 1) {
$controller = new admin_controller();
switch (explode('/', $uri)[2] ?? null) {
case 'users': $controller->users(); break;
case 'books': $controller->books(); break;
case 'stock': $controller->stock(); break;
case 'categories': $controller->categories(); break;
case 'add-user': $controller->add_user(); break;
case 'update-user': $controller->update_user(); break;
case 'delete-user': $controller->delete_user(); break;
case 'add-book': $controller->add_book(); break;
case 'update-book': $controller->update_book(); break;
case 'delete-book': $controller->delete_book(); break;
case 'add-stock': $controller->add_stock(); break;
case 'update-stock': $controller->update_stock(); break;
case 'delete-stock': $controller->delete_stock(); break;
case 'add-category': $controller->add_category(); break;
case 'update-category': $controller->update_category(); break;
case 'delete-category': $controller->delete_category(); break;
case 'do': switch (explode('/', $uri)[3] ?? null) {
case 'add-user': $controller->do_add_user(); break;
case 'update-user': $controller->do_update_user(); break;
case 'delete-user': $controller->do_delete_user(); break;
case 'add-book': $controller->do_add_book(); break;
case 'update-book': $controller->do_update_book(); break;
case 'delete-book': $controller->do_delete_book(); break;
case 'add-stock': $controller->do_add_stock(); break;
case 'update-stock': $controller->do_update_stock(); break;
case 'delete-stock': $controller->do_delete_stock(); break;
case 'add-category': $controller->do_add_category(); break;
case 'update-category': $controller->do_update_category(); break;
case 'delete-category': $controller->do_delete_category(); break;
default: break;
} break;
default: header('Location: '.($this->check_login(0)?'/admin/users':'/user/login')); break;
}
} else header('Location: /user'); break;
default:
$controller = new default_controller();
switch ($to) {
case 'index': $controller->index(); break;
case 'lists': $controller->lists(); break;
case 'search': $controller->search(); break;
case 'book': $controller->book((int)(explode('/', $uri)[2] ?? 0)); break;
default: http_response_code(404); break;
} break;
}
}
private function check_login($jump = true) {
return ($login = !isset($_SESSION['user'])) && $jump ? exit(header('Location: /user/login')) : !$login;
}
}

49
src/template/admins/add_book.php

@ -0,0 +1,49 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">添加书籍</h2>
<form action="/admin/do/add-book?page=<?=$_GET['page']?>" method="post">
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 书 名:<input type="text" name="name" />
</p>
<p class="text-grey-dark mt-2">
 作 者:<input type="text" name="author" />
</p>
<p class="text-grey-dark mt-2">
 出版社:<input type="text" name="publish" />
</p>
<p class="text-grey-dark mt-2">
ISBN:<input type="text" name="isbn" />
</p>
<p class="text-grey-dark mt-2">
封面图片:<input type="text" name="cover" />
</p>
<p class="text-grey-dark mt-2">
书籍类型:<select name="type">
<?php foreach ($categories as $category) { ?>
<option value="<?=$category['cid']?>"><?=$category['name']?></option>
<?php } ?>
</select>
</p>
<p class="text-grey-dark mt-2">
书籍语言:<select name="lang">
<option value="zh-cn">简体中文</option>
<option value="en-us">英文</option>
</select>
</p>
<p class="text-grey-dark mt-2">
 
</p>
<a class="no-underline" href="/admin/books?page=<?=$_GET['page']?>">
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="button" value=" 返 回 " />
</a>
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value=" 添 加 " />
</form>
</div>
</div>
</div>

24
src/template/admins/add_category.php

@ -0,0 +1,24 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">添加分类</h2>
<form action="/admin/do/add-category?page=<?=$_GET['page']?>" method="post">
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 分类名:<input type="text" name="name" />
</p>
<p class="text-grey-dark mt-2">
 
</p>
<a class="no-underline" href="/admin/categories?page=<?=$_GET['page']?>">
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="button" value=" 返 回 " />
</a>
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value=" 添 加 " />
</form>
</div>
</div>
</div>

59
src/template/admins/add_stock.php

@ -0,0 +1,59 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">添加库存</h2>
<form action="/admin/do/add-stock?page=<?=$_GET['page']?>&bid=<?=$_GET['bid']?>" method="post">
<p class="mt-2">
 
</p>
<img src="<?=$book['cover']?>" />
<p class="text-grey-dark mt-2">
 书 名:<?=$book['name']?>
</p>
<p class="text-grey-dark mt-2">
 作 者:<?=$book['author']?>
</p>
<p class="text-grey-dark mt-2">
 出版社:<?=$book['publish']?>
</p>
<p class="text-grey-dark mt-2">
ISBN:<?=$book['isbn']?>
</p>
<p class="text-grey-dark mt-2">
书籍类型:<?php foreach ($categories as $category) if ($category['cid'] == $book['cid']) echo $category['name']; ?>
</p>
<p class="text-grey-dark mt-2">
书籍语言:<?=$book['lang']=='zh-cn'?'简体中文':'英文'?>
</p>
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 书架号:<input type="text" name="place" />
</p>
<p class="text-grey-dark mt-2">
受损程度:<select name="health">
<option value="0">正常</option>
<option value="1">中等</option>
<option value="2">受损</option>
</select>
</p>
<p class="text-grey-dark mt-2">
借阅状态:<select name="state">
<option value="0">在馆</option>
<option value="1">借出</option>
</select>
</p>
<p class="text-grey-dark mt-2">
 
</p>
<a class="no-underline" href="/admin/stock?bid=<?=$_GET['bid']?>&page=<?=$_GET['page']?>">
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="button" value=" 返 回 " />
</a>
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value=" 添 加 " />
</form>
</div>
</div>
</div>

51
src/template/admins/add_user.php

@ -0,0 +1,51 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">添加用户</h2>
<form action="/admin/do/add-user?page=<?=$_GET['page']?>" method="post">
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 用户名:<input type="text" name="username" />
</p>
<p class="text-grey-dark mt-2">
 密 码:<input type="password" name="password" />
</p>
<p class="text-grey-dark mt-2">
重复密码:<input type="password" name="confirm" />
</p>
<p class="text-grey-dark mt-2">
 性 别:<select name="sex">
<option value="1" selected></option>
<option value="0"></option>
</select>
</p>
<p class="text-grey-dark mt-2">
 生 日:<input type="text" name="birthday" value="1900-01-01" />
</p>
<p class="text-grey-dark mt-2">
 身份证:<input type="text" name="id_card" value="440105190001019999" />
</p>
<p class="text-grey-dark mt-2">
借书配额:<input type="text" name="borrow_num" value="15"/>
</p>
<p class="text-grey-dark mt-2">
用户类型:<select name="type">
<option value="1">管理员</option>
<option value="0" selected>普通用户</option>
</select>
</p>
<p class="text-grey-dark mt-2">
 
</p>
<a class="no-underline" href="/admin/users?page=<?=$_GET['page']?>">
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="button" value=" 返 回 " />
</a>
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value=" 添 加 " />
</form>
</div>
</div>
</div>

63
src/template/admins/books.php

@ -0,0 +1,63 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">书籍管理</h2>
</div>
<a href="/admin/add-book?page=<?=$page?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">添加书籍</a>
</div>
<div class="px-6 md:px-0 mt-4 md:flex flex-wrap order-1 md:-order-1 md:shadow-md">
<div class="p-4 px-6 w-full md:w-1/2 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<h4>书籍列表</h4>
<table class="mt-4 w-full">
<thead class="p-2 text-sm leading-loose border-b text-indigo">
<tr>
<td>书名</td>
<td class="hidden js-mobile-hidden">作者</td>
<td class="hidden js-mobile-hidden">出版社</td>
<td class="text-center hidden js-mobile-hidden">ISBN</td>
<td class="text-right">库存</td>
<td class="text-right">操作</td>
</tr>
</thead>
<tbody class="p-2 leading-loose text-sm">
<?php if (isset($books[0]['bid'])) {
foreach ($books as $book) { ?><tr class="border-b">
<td class="py-2"><?=$book['name']?></td>
<td class="py-2 hidden js-mobile-hidden"><?=$book['author']?></td>
<td class="py-2 hidden js-mobile-hidden"><?=$book['publish']?></td>
<td class="py-2 text-center hidden js-mobile-hidden"><?=$book['isbn']?></td>
<td class="py-2 text-right"><?=$book['stock']?></td>
<td class="py-2 text-right">
<a href="/admin/update-book?page=<?=$page?>&bid=<?=$book['bid']?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none hidden js-mobile-hidden">更新</a>
<a href="/admin/stock?bid=<?=$book['bid']?>&books=<?=$page?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">库存</a>
<a href="/admin/delete-book?page=<?=$page?>&bid=<?=$book['bid']?>" class="no-underline bg-magenta-dark hover:bg-magenta-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">删除</a>
</td>
</tr>
<?php }
} else { ?>
<tr class="border-b">
<td class="py-2">没有库存</td>
</td>
<?php } ?>
</tbody>
</table>
</div>
<div class="w-full md:w-1/2 p-4 md:pt-12 md:pl-1 mt-4 md:mt-0 lg:pt-12 lg:pl-8 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<div class="flex">
<div class="w-1/2">
<p class="text-indigo text-sm p-2">书籍条目</p>
<p class="font-medium text-sm pl-2"><?=$count?></p>
</div>
<div class="w-1/2">
<p class="text-indigo text-sm p-2">书籍总量</p>
<p class="font-medium text-sm pl-2"><?=$stock?></p>
</div>
</div>
<div class="pt-6">
<?php $path = '/admin/books'; require(APP_ROOT.'/src/template/admins/page_switch.php'); ?>
</div>
</div>
</div>
</div>

56
src/template/admins/categories.php

@ -0,0 +1,56 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">分类管理</h2>
</div>
<a href="/admin/add-category?page=<?=$page?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">添加分类</a>
</div>
<div class="px-6 md:px-0 mt-4 md:flex flex-wrap order-1 md:-order-1 md:shadow-md">
<div class="p-4 px-6 w-full md:w-1/2 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<h4>分类列表</h4>
<table class="mt-4 w-full">
<thead class="p-2 text-sm leading-loose border-b text-indigo">
<tr>
<td>ID</td>
<td>分类名</td>
<td class="text-right">操作</td>
</tr>
</thead>
<tbody class="p-2 leading-loose text-sm">
<?php if (isset($categories[0]['cid'])) {
foreach ($categories as $category) { ?><tr class="border-b">
<td class="py-2"><?=$category['cid']?></td>
<td class="py-2"><?=$category['name']?></td>
<td class="py-2 text-right">
<a href="/admin/update-category?page=<?=$page?>&cid=<?=$category['cid']?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">更新</a>
<a href="/admin/delete-category?page=<?=$page?>&cid=<?=$category['cid']?>" class="no-underline bg-magenta-dark hover:bg-magenta-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">删除</a>
</td>
</tr>
<?php }
} else { ?>
<tr class="border-b">
<td class="py-2">没有分类</td>
</td>
<?php } ?>
</tbody>
</table>
</div>
<div class="w-full md:w-1/2 p-4 md:pt-12 md:pl-1 mt-4 md:mt-0 lg:pt-12 lg:pl-8 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<div class="flex">
<div class="w-1/2">
<p class="text-indigo text-sm p-2">分类数量</p>
<p class="font-medium text-sm pl-2"><?=$count?></p>
</div>
<div class="w-1/2">
<p class="text-indigo text-sm p-2">书籍总量</p>
<p class="font-medium text-sm pl-2"><?=$stock?></p>
</div>
</div>
<div class="pt-6">
<?php $path = '/admin/books'; require(APP_ROOT.'/src/template/admins/page_switch.php'); ?>
</div>
</div>
</div>
</div>

41
src/template/admins/delete_book.php

@ -0,0 +1,41 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">删除书籍</h2>
<p class="text-grey-dark mt-2">修改不可逆,请谨慎操作!</p>
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<img src="<?=$book['cover']?>" />
<p class="text-grey-dark mt-2">
 书 名:<?=$book['name']?>
</p>
<p class="text-grey-dark mt-2">
 作 者:<?=$book['author']?>
</p>
<p class="text-grey-dark mt-2">
 出版社:<?=$book['publish']?>
</p>
<p class="text-grey-dark mt-2">
ISBN:<?=$book['isbn']?>
</p>
<p class="text-grey-dark mt-2">
书籍类型:<?php foreach ($categories as $category) if ($category['cid'] == $book['cid']) echo $category['name']; ?>
</p>
<p class="text-grey-dark mt-2">
书籍语言:<?=$book['lang']=='zh-cn'?'简体中文':'英文'?>
</p>
<p class="text-grey-dark mt-2">
 
</p>
<a class="no-underline" href="/admin/books?page=<?=$_GET['page']?>">
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="button" value="返回列表" />
</a>
<a class="no-underline" href="/admin/do/delete-book?page=<?=$_GET['page']?>&bid=<?=$book['bid']?>">
<input class="bg-magenta-dark hover:bg-magenta-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="button" value="确认删除" />
</a>
</div>
</div>
</div>

35
src/template/admins/delete_category.php

@ -0,0 +1,35 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">删除分类</h2>
<p class="text-grey-dark mt-2">修改不可逆,请谨慎操作!</p>
<form action="/admin/do/delete-category?page=<?=$_GET['page']?>&cid=<?=$_GET['cid']?>" method="post">
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 分类名:<?=$category['name']?>
</p>
<p class="text-grey-dark mt-2">
 合并至:<select name="category">
<?php $cid = $category['cid'];
foreach ($categories as $category) {
if ($category['cid'] != $cid) { ?>
<option value="<?=$category['cid']?>"><?=$category['name']?></option>
<?php }
} ?>
</select>
</p>
<p class="text-grey-dark mt-2">
 
</p>
<a class="no-underline" href="/admin/categories?page=<?=$_GET['page']?>">
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="button" value="返回列表" />
</a>
<input class="bg-magenta-dark hover:bg-magenta-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value="确认删除" />
</a>
</div>
</div>
</div>

54
src/template/admins/delete_stock.php

@ -0,0 +1,54 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">删除库存</h2>
<p class="text-grey-dark mt-2">修改不可逆,请谨慎操作!</p>
<p class="mt-2">
 
</p>
<img src="<?=$book['cover']?>" />
<p class="text-grey-dark mt-2">
 书 名:<?=$book['name']?>
</p>
<p class="text-grey-dark mt-2">
 作 者:<?=$book['author']?>
</p>
<p class="text-grey-dark mt-2">
 出版社:<?=$book['publish']?>
</p>
<p class="text-grey-dark mt-2">
ISBN:<?=$book['isbn']?>
</p>
<p class="text-grey-dark mt-2">
书籍类型:<?php foreach ($categories as $category) if ($category['cid'] == $book['cid']) echo $category['name']; ?>
</p>
<p class="text-grey-dark mt-2">
书籍语言:<?=$book['lang']=='zh-cn'?'简体中文':'英文'?>
</p>
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 书架号:<?=$book['place']?>
</p>
<p class="text-grey-dark mt-2">
受损程度:<?=$book['health']?($book['health']==2?'破损':'中等'):'正常'?>
</p>
<p class="text-grey-dark mt-2">
借阅状态:<?=$book['state']?'借出':'在馆'?>
</p>
<p class="text-grey-dark mt-2">
 
</p>
<a class="no-underline" href="/admin/stock?page=<?=$_GET['page']?>">
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="button" value="返回列表" />
</a>
<a class="no-underline" href="/admin/do/delete-stock?page=<?=$_GET['page']?>&sid=<?=$book['sid']?>">
<input class="bg-magenta-dark hover:bg-magenta-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="button" value="确认删除" />
</a>
</form>
</div>
</div>
</div>

40
src/template/admins/delete_user.php

@ -0,0 +1,40 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">删除用户</h2>
<p class="text-grey-dark mt-2">修改不可逆,请谨慎操作!</p>
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 用户名:<?=$user['username']?>
</p>
<p class="text-grey-dark mt-2">
 性 别:<?=$user['sex']?'男':'女'?>
</p>
<p class="text-grey-dark mt-2">
 生 日:<?=$user['birthday']?>
</p>
<p class="text-grey-dark mt-2">
 身份证:<?=$user['id_card']?>
</p>
<p class="text-grey-dark mt-2">
借书配额:<?=$user['borrow_num']?>
</p>
<p class="text-grey-dark mt-2">
用户类型:<?=$user['type']?'管理员':'普通用户'?>
</p>
<p class="text-grey-dark mt-2">
 
</p>
<a class="no-underline" href="/admin/users?page=<?=$_GET['page']?>">
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="button" value="返回列表" />
</a>
<a class="no-underline" href="/admin/do/delete-user?page=<?=$_GET['page']?>&uid=<?=$user['uid']?>">
<input class="bg-magenta-dark hover:bg-magenta-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="button" value="确认删除" />
</a>
</div>
</div>
</div>

15
src/template/admins/page_switch.php

@ -0,0 +1,15 @@
<?php $total = (int)(1+$count/20); ?>
<p class="text-indigo text-sm p-2"><?=$page?> / <?=$total?></p>
<?php if ($page > 2) { ?>
<a href="<?=$path?>?page=1" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-3 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">首页</a>
<?php } if ($page == 1) { ?>
<a class="no-underline bg-grey text-white text-sm px-3 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">上一页</a>
<?php } else { ?>
<a href="<?=$path?>?page=<?=$page-1?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-3 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">上一页</a>
<?php } if ($page == $total) { ?>
<a class="no-underline bg-grey text-white text-sm px-3 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">下一页</a>
<?php } else { ?>
<a href="<?=$path?>?page=<?=$page+1?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-3 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">下一页</a>
<?php } if ($total > 2 && $page < $total - 1) { ?>
<a href="<?=$path?>?page=<?=$total?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-3 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">尾页</a>
<?php } ?>

68
src/template/admins/stock.php

@ -0,0 +1,68 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">库存管理</h2>
</div>
<?php if (isset($_GET['bid']) && is_numeric($_GET['bid'])) { ?>
<a href="/admin/add-stock?page=<?=$page?>&bid=<?=$_GET['bid']?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">添加库存</a>
<?php } ?>
</div>
<div class="px-6 md:px-0 mt-4 md:flex flex-wrap order-1 md:-order-1 md:shadow-md">
<div class="p-4 px-6 w-full md:w-1/2 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<h4>库存列表</h4>
<table class="mt-4 w-full">
<thead class="p-2 text-sm leading-loose border-b text-indigo">
<tr>
<td>书名</td>
<td class="hidden js-mobile-hidden">书架号</td>
<td class="hidden js-mobile-hidden">ISBN</td>
<td class="text-center hidden js-mobile-hidden">受损程度</td>
<td class="text-center">借阅状态</td>
<td class="text-right">操作</td>
</tr>
</thead>
<tbody class="p-2 leading-loose text-sm">
<?php if (isset($books[0]['bid'])) {
foreach ($books as $book) { ?><tr class="border-b">
<td class="py-2"><?=$book['name']?></td>
<td class="py-2 hidden js-mobile-hidden"><?=$book['place']?></td>
<td class="py-2 hidden js-mobile-hidden"><?=$book['isbn']?></td>
<td class="py-2 text-center hidden js-mobile-hidden"><?=$book['health']?($book['health']==2?'破损':'中等'):'正常'?></td>
<td class="py-2 text-center"><?=$book['state']?'借出':'在馆'?></td>
<td class="py-2 text-right">
<a href="/admin/update-stock?page=<?=$page?>&sid=<?=$book['sid']?>&bid=<?=$book['bid']?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">更新</a>
<a href="/admin/delete-stock?page=<?=$page?>&sid=<?=$book['sid']?>&bid=<?=$book['bid']?>" class="no-underline bg-magenta-dark hover:bg-magenta-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">删除</a>
</td>
</tr>
<?php }
} else { ?>
<tr class="border-b">
<td class="py-2">没有库存</td>
</td>
<?php } ?>
</tbody>
</table>
</div>
<div class="w-full md:w-1/2 p-4 md:pt-12 md:pl-1 mt-4 md:mt-0 lg:pt-12 lg:pl-8 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<div class="flex">
<div class="w-1/2">
<p class="text-indigo text-sm p-2">剩余库存</p>
<p class="font-medium text-sm pl-2"><?=$stock?></p>
</div>
<div class="w-1/2">
<p class="text-indigo text-sm p-2">库存总量</p>
<p class="font-medium text-sm pl-2"><?=$count?></p>
</div>
</div>
<div class="pt-6">
<?php $path = '/admin/books'; require(APP_ROOT.'/src/template/admins/page_switch.php'); ?>
<?php if (isset($_GET['bid']) && is_numeric($_GET['bid'])) { ?>
<a href="/admin/books?page=<?=$_GET['books']?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">返回列表</a>
<a href="/admin/stock" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">所有库存</a>
<?php } ?>
</div>
</div>
</div>
</div>

47
src/template/admins/update_book.php

@ -0,0 +1,47 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">更新书籍</h2>
<p class="text-grey-dark mt-2">留空则不作修改</p>
<form action="/admin/do/update-book?page=<?=$_GET['page']?>&bid=<?=$book['bid']?>" method="post">
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 书 名:<input type="text" name="name" value="<?=$book['name']?>" />
</p>
<p class="text-grey-dark mt-2">
 作 者:<input type="text" name="author" value="<?=$book['author']?>" />
</p>
<p class="text-grey-dark mt-2">
 出版社:<input type="text" name="publish" value="<?=$book['publish']?>" />
</p>
<p class="text-grey-dark mt-2">
ISBN:<input type="text" name="isbn" value="<?=$book['isbn']?>" />
</p>
<p class="text-grey-dark mt-2">
封面图片:<input type="text" name="cover" value="<?=$book['cover']?>" />
</p>
<p class="text-grey-dark mt-2">
书籍类型:<select name="type">
<?php foreach ($categories as $category) { ?>
<option value="<?=$category['cid']?>"<?=$category['cid']==$book['cid']?' selected':''?>><?=$category['name']?></option>
<?php } ?>
</select>
</p>
<p class="text-grey-dark mt-2">
书籍语言:<select name="lang">
<option value="zh-cn"<?=$book['lang']=='zh-cn'?' selected':''?>>简体中文</option>
<option value="en-us"<?=$book['lang']=='en-us'?' selected':''?>>英文</option>
</select>
</p>
<p class="text-grey-dark mt-2">
 
</p>
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value=" 更 新 " />
</form>
</div>
</div>
</div>

22
src/template/admins/update_category.php

@ -0,0 +1,22 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">更新分类</h2>
<p class="text-grey-dark mt-2">留空则不作修改</p>
<form action="/admin/do/update-category?page=<?=$_GET['page']?>&cid=<?=$_GET['cid']?>" method="post">
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 出版社:<input type="text" name="name" value="<?=$category['name']?>"/>
</p>
<p class="text-grey-dark mt-2">
 
</p>
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value=" 更 新 " />
</form>
</div>
</div>
</div>

56
src/template/admins/update_stock.php

@ -0,0 +1,56 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">更新库存</h2>
<form action="/admin/do/update-stock?page=<?=$_GET['page']?>&sid=<?=$_GET['sid']?>&bid=<?=$_GET['bid']?>" method="post">
<p class="mt-2">
 
</p>
<img src="<?=$book['cover']?>" />
<p class="text-grey-dark mt-2">
 书 名:<?=$book['name']?>
</p>
<p class="text-grey-dark mt-2">
 作 者:<?=$book['author']?>
</p>
<p class="text-grey-dark mt-2">
 出版社:<?=$book['publish']?>
</p>
<p class="text-grey-dark mt-2">
ISBN:<?=$book['isbn']?>
</p>
<p class="text-grey-dark mt-2">
书籍类型:<?php foreach ($categories as $category) if ($category['cid'] == $book['cid']) echo $category['name']; ?>
</p>
<p class="text-grey-dark mt-2">
书籍语言:<?=$book['lang']=='zh-cn'?'简体中文':'英文'?>
</p>
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 书架号:<input type="text" name="place" value="<?=$book['place']?>" />
</p>
<p class="text-grey-dark mt-2">
受损程度:<select name="health">
<option value="0"<?=$book['health']==0?' selected':''?>>正常</option>
<option value="1"<?=$book['health']==1?' selected':''?>>中等</option>
<option value="2"<?=$book['health']==2?' selected':''?>>受损</option>
</select>
</p>
<p class="text-grey-dark mt-2">
借阅状态:<select name="state">
<option value="0"<?=$book['state']==0?' selected':''?>>在馆</option>
<option value="1"<?=$book['state']==1?' selected':''?>>借出</option>
</select>
</p>
<p class="text-grey-dark mt-2">
 
</p>
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value=" 更 新 " />
</form>
</div>
</div>
</div>

45
src/template/admins/update_user.php

@ -0,0 +1,45 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">更新用户</h2>
<p class="text-grey-dark mt-2">留空则不作修改</p>
<form action="/admin/do/update-user?page=<?=$_GET['page']?>&uid=<?=$user['uid']?>" method="post">
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 用户名:<?=$user['username']?>
</p>
<p class="text-grey-dark mt-2">
 性 别:<select name="sex">
<option value="1" <?=$user['sex']?'selected':''?>></option><option value="0" <?=$user['sex']?'':'selected'?>></option></select>
</p>
<p class="text-grey-dark mt-2">
 生 日:<input type="text" name="birthday" value="<?=$user['birthday']?>"/>
</p>
<p class="text-grey-dark mt-2">
 身份证:<input type="text" name="id_card" value="<?=$user['id_card']?>"/>
</p>
<p class="text-grey-dark mt-2">
借书配额:<input type="text" name="borrow_num" value="<?=$user['borrow_num']?>"/>
</p>
<p class="text-grey-dark mt-2">
用户类型:<select name="type">
<option value="1" <?=$user['type']?'selected':''?>>管理员</option><option value="0" <?=$user['type']?'':'selected'?>>普通用户</option></select>
</p>
<p class="text-grey-dark mt-2">
 密 码:<input type="password" name="password" />
</p>
<p class="text-grey-dark mt-2">
重复密码:<input type="password" name="confirm" />
</p>
<p class="text-grey-dark mt-2">
 
</p>
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value=" 更 新 " />
</form>
</div>
</div>
</div>

64
src/template/admins/users.php

@ -0,0 +1,64 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">用户管理</h2>
</div>
<a href="/admin/add-user?page=<?=$page?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">添加用户</a>
</div>
<div class="px-6 md:px-0 mt-4 md:flex flex-wrap order-1 md:-order-1 md:shadow-md">
<div class="p-4 px-6 w-full md:w-1/2 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<h4>用户列表</h4>
<table class="mt-4 w-full">
<thead class="p-2 text-sm leading-loose border-b text-indigo">
<tr>
<td>用户名</td>
<td class="hidden js-mobile-hidden">性别</td>
<td class="text-center hidden js-mobile-hidden">生日</td>
<td class="text-center hidden js-mobile-hidden">身份证</td>
<td class="text-right hidden js-mobile-hidden">借书配额</td>
<td class="text-right">用户类型</td>
<td class="text-right">操作</td>
</tr>
</thead>
<tbody class="p-2 leading-loose text-sm">
<?php if (isset($users[0]['uid'])) {
foreach ($users as $user) { ?><tr class="border-b">
<td class="py-2"><?=$user['username']?></td>
<td class="py-2 hidden js-mobile-hidden"><?=$user['sex']?'男':'女'?></td>
<td class="py-2 text-center hidden js-mobile-hidden"><?=$user['birthday']?></td>
<td class="py-2 text-center hidden js-mobile-hidden"><?=$user['id_card']?></td>
<td class="py-2 text-right hidden js-mobile-hidden"><?=$user['borrow_num']?></td>
<td class="py-2 text-right"><?=$user['type']?'管理员':'普通用户'?></td>
<td class="py-2 text-right">
<a href="/admin/update-user?page=<?=$page?>&uid=<?=$user['uid']?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">更新</a>
<a href="/admin/delete-user?page=<?=$page?>&uid=<?=$user['uid']?>" class="no-underline bg-magenta-dark hover:bg-magenta-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">删除</a>
</td>
</tr>
<?php }
} else { ?>
<tr class="border-b">
<td class="py-2">没有用户</td>
</td>
<?php } ?>
</tbody>
</table>
</div>
<div class="w-full md:w-1/2 p-4 md:pt-12 md:pl-1 mt-4 md:mt-0 lg:pt-12 lg:pl-8 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<div class="flex">
<div class="w-1/2">
<p class="text-indigo text-sm p-2">用户数量</p>
<p class="font-medium text-sm pl-2"><?=$count?></p>
</div>
<div class="w-1/2">
<p class="text-indigo text-sm p-2">借出书籍</p>
<p class="font-medium text-sm pl-2"><?=$stock?></p>
</div>
</div>
<div class="pt-6">
<?php $path = '/admin/users'; require(APP_ROOT.'/src/template/admins/page_switch.php'); ?>
</div>
</div>
</div>
</div>

65
src/template/defaults/book.php

@ -0,0 +1,65 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">库存查询</h2>
</div>
<a onClick="javascript:history.back(-1);" class="no-underline cursor-pointer bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">返回上页</a>
</div>
<div class="px-6 md:px-0 mt-4 md:flex flex-wrap order-1 md:-order-1 md:shadow-md">
<div class="p-4 px-6 w-full md:w-1/2 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<h4>库存列表</h4>
<table class="mt-4 w-full">
<thead class="p-2 text-sm leading-loose border-b text-indigo">
<tr>
<td>书名</td>
<td class="hidden js-mobile-hidden">书架号</td>
<td class="hidden js-mobile-hidden">ISBN</td>
<td class="text-center hidden js-mobile-hidden">受损程度</td>
<td class="text-center">借阅状态</td>
<td class="text-right">操作</td>
</tr>
</thead>
<tbody class="p-2 leading-loose text-sm">
<?php if (isset($books[0]['bid'])) {
foreach ($books as $book) { ?><tr class="border-b">
<td class="py-2"><?=$book['name']?></td>
<td class="py-2 hidden js-mobile-hidden"><?=$book['place']?></td>
<td class="py-2 hidden js-mobile-hidden"><?=$book['isbn']?></td>
<td class="py-2 text-center hidden js-mobile-hidden"><?=$book['health']?($book['health']==2?'破损':'中等'):'正常'?></td>
<td class="py-2 text-center"><?=$book['state']?'借出':'在馆'?></td>
<td class="py-2 text-right">
<?php if ($book['state']) { ?>
<a class="no-underline bg-grey text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">借阅</a>
<?php } else { ?>
<a href="/user/update-stock?page=<?=$page?>&sid=<?=$book['sid']?>&bid=<?=$book['bid']?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">借阅</a>
<?php } ?>
</td>
</tr>
<?php }
} else { ?>
<tr class="border-b">
<td class="py-2">没有可用库存</td>
</td>
<?php } ?>
</tbody>
</table>
</div>
<div class="w-full md:w-1/2 p-4 md:pt-12 md:pl-1 mt-4 md:mt-0 lg:pt-12 lg:pl-8 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<div class="flex">
<div class="w-1/2">
<p class="text-indigo text-sm p-2">剩余库存</p>
<p class="font-medium text-sm pl-2"><?=$stock?></p>
</div>
<div class="w-1/2">
<p class="text-indigo text-sm p-2">库存总量</p>
<p class="font-medium text-sm pl-2"><?=$count?></p>
</div>
</div>
<div class="pt-6">
<?php $path = '/admin/books'; require(APP_ROOT.'/src/template/admins/page_switch.php'); ?>
</div>
</div>
</div>
</div>

42
src/template/defaults/index.php

@ -0,0 +1,42 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">热门书籍</h2>
</div>
</div>
<!-- Filter -->
<div class="px-6 md:px-0 flex items-baseline justify-between border-b-2 border-grey-light mt-6 order-0 lg:order-1"></div>
<!-- Library -->
<div class="hidden px-2 pt-2 md:px-0 flex-wrap order-2 pb-8 js-tab-pane active" id="section-library">
<?php if (isset($books[0]['bid'])) {
foreach ($books as $book) { ?>
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full xs:w-1/2 sm:w-1/3 md:w-1/5 p-4 js-book" data-href="/book/<?=$book['bid']?>">
<img src="<?=$book['cover']?>" class="w-1/3 sm:w-full shadow-md transition-normal hover:brighter hover:translate-y-1 hover:shadow-lg hover:border-indigo">
<div class="ml-3 sm:ml-0 w-2/3 sm:w-full">
<p class="text-sm my-2 font-medium sm:font-normal"><?=$book['name']?></p>
<p class="block text-grey-dark sm:hidden mt-2 mb-3 text-sm leading-medium">
<?php foreach ($categories as $category) if ($category['cid'] == $book['cid']) echo $category['name']; ?> (<?=$book['author']?>-<?=$book['publish']?>)
</p>
<p class="block text-grey sm:hidden mt-2 mb-3 text-sm leading-medium">
<?=$book['lang']=='zh-cn'?'简体中文':'英文'?> (ISBN: <?=$book['isbn']?>)
</p>
<label class="hidden sm:inline-block rounded-full libre-bg-grey text-white px-2 py-1/2 text-xs"><?=$book['author']?></label>
<label class="hidden sm:inline-block rounded-full libre-bg-grey text-white px-2 py-1/2 text-xs"><?=$book['publish']?></label>
<label class="hidden sm:inline-block rounded-full libre-bg-grey text-white px-2 py-1/2 text-xs"><?php foreach ($categories as $category) if ($category['cid'] == $book['cid']) echo $category['name']; ?></label>
<label class="hidden sm:inline-block rounded-full libre-bg-grey text-white px-2 py-1/2 text-xs"><?=$book['lang']=='zh-cn'?'简体中文':'英文'?></label>
<label class="hidden sm:inline-block rounded-full libre-bg-grey text-white px-2 py-1/2 text-xs">ISBN: <?=$book['isbn']?></label>
</div>
</div>
<?php } ?>
<?php $path = '/'; require(APP_ROOT.'/src/template/defaults/page_switch.php'); ?>
<?php } else { ?>
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full xs:w-1/2 sm:w-1/3 md:w-1/5 p-4">
<p class="text-2xl my-2 font-bold sm:font-bold">暂无热门数据</p>
</div>
<?php } ?>
</div>
</div>
<?php
if (isset($_SESSION['user'])) require(APP_ROOT.'/src/template/defaults/user_profile.php');

42
src/template/defaults/lists.php

@ -0,0 +1,42 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">书籍列表</h2>
</div>
</div>
<!-- Filter -->
<div class="px-6 md:px-0 flex items-baseline justify-between border-b-2 border-grey-light mt-6 order-0 lg:order-1"></div>
<!-- Library -->
<div class="hidden px-2 pt-2 md:px-0 flex-wrap order-2 pb-8 js-tab-pane active" id="section-library">
<?php if (isset($books[0]['bid'])) {
foreach ($books as $book) { ?>
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full xs:w-1/2 sm:w-1/3 md:w-1/5 p-4 js-book" data-href="/book/<?=$book['bid']?>">
<img src="<?=$book['cover']?>" class="w-1/3 sm:w-full shadow-md transition-normal hover:brighter hover:translate-y-1 hover:shadow-lg hover:border-indigo">
<div class="ml-3 sm:ml-0 w-2/3 sm:w-full">
<p class="text-sm my-2 font-medium sm:font-normal"><?=$book['name']?></p>
<p class="block text-grey-dark sm:hidden mt-2 mb-3 text-sm leading-medium">
<?php foreach ($categories as $category) if ($category['cid'] == $book['cid']) echo $category['name']; ?> (<?=$book['author']?>-<?=$book['publish']?>)
</p>
<p class="block text-grey sm:hidden mt-2 mb-3 text-sm leading-medium">
<?=$book['lang']=='zh-cn'?'简体中文':'英文'?> (ISBN: <?=$book['isbn']?>)
</p>
<label class="hidden sm:inline-block rounded-full libre-bg-grey text-white px-2 py-1/2 text-xs"><?=$book['author']?></label>
<label class="hidden sm:inline-block rounded-full libre-bg-grey text-white px-2 py-1/2 text-xs"><?=$book['publish']?></label>
<label class="hidden sm:inline-block rounded-full libre-bg-grey text-white px-2 py-1/2 text-xs"><?php foreach ($categories as $category) if ($category['cid'] == $book['cid']) echo $category['name']; ?></label>
<label class="hidden sm:inline-block rounded-full libre-bg-grey text-white px-2 py-1/2 text-xs"><?=$book['lang']=='zh-cn'?'简体中文':'英文'?></label>
<label class="hidden sm:inline-block rounded-full libre-bg-grey text-white px-2 py-1/2 text-xs">ISBN: <?=$book['isbn']?></label>
</div>
</div>
<?php } ?>
<?php $path = '/lists'; require(APP_ROOT.'/src/template/defaults/page_switch.php'); ?>
<?php } else { ?>
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full xs:w-1/2 sm:w-1/3 md:w-1/5 p-4">
<p class="text-2xl my-2 font-bold sm:font-bold">暂无书籍</p>
</div>
<?php } ?>
</div>
</div>
<?php
if (isset($_SESSION['user'])) require(APP_ROOT.'/src/template/defaults/user_profile.php');

17
src/template/defaults/page_switch.php

@ -0,0 +1,17 @@
<div class="m-auto text-center w-full">
<?php $total = (int)(1+$count/20); ?>
<p class="text-indigo text-sm p-2 leading-medium"><?=$page?> / <?=$total?><br> </p>
<?php if ($page > 2) { ?>
<a href="<?=$path?>?page=1" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm m-1 py-2 px-5 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">首页</a>
<?php } if ($page == 1) { ?>
<a class="no-underline bg-grey text-white text-sm m-1 py-2 px-5 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">上一页</a>
<?php } else { ?>
<a href="<?=$path?>?page=<?=$page-1?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm m-1 py-2 px-5 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">上一页</a>
<?php } if ($page == $total) { ?>
<a class="no-underline bg-grey text-white text-sm m-1 py-2 px-5 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">下一页</a>
<?php } else { ?>
<a href="<?=$path?>?page=<?=$page+1?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm m-1 py-2 px-5 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">下一页</a>
<?php } if ($total > 2 && $page < $total - 1) { ?>
<a href="<?=$path?>?page=<?=$total?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm m-1 py-2 px-5 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">尾页</a>
<?php } ?>
</div>

44
src/template/defaults/search.php

@ -0,0 +1,44 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">搜索结果</h2>
</div>
</div>
<!-- Filter -->
<div class="px-6 md:px-0 flex items-baseline justify-between border-b-2 border-grey-light mt-6 order-0 lg:order-1"></div>
<!-- Picks -->
<div class="flex-wrap order-2 pt-0 md:pt-6 md:pb-8 js-tab-pane active">
<?php if (empty($_GET['s'])) { ?>
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full">
<p class="text-2xl my-2 font-bold sm:font-bold">请在上方搜索框输入书名关键字 ~</p>
</div>
<?php } elseif (isset($books[0]['bid'])) {
foreach ($books as $book) { ?>
<div class="flex justify-start items-center p-5 px-6 w-full sm:w-1/2">
<img src="<?=$book['cover']?>" alt="pick" class="shadow-md w-1/3">
<div class="ml-4 mt-1 w-2/3">
<p class="font-medium"><strong><?=$book['name']?></strong></p>
<p class="mt-3 text-sm">
<?php foreach ($categories as $category) if ($category['cid'] == $book['cid']) echo $category['name']; ?> (<?=$book['author']?>-<?=$book['publish']?>)
</p>
<p class="mt-3 text-sm">
<?=$book['lang']=='zh-cn'?'简体中文':'英文'?> (ISBN: <?=$book['isbn']?>)
</p>
<a href="/book/<?=$book['bid']?>" class="no-underline">
<button class="shadow-md mt-3 bg-grey-lightest hover:bg-white text-indigo-darker text-xs py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">查询库存</button>
</a>
</div>
</div>
<?php } ?>
<?php $path = '/search'; require(APP_ROOT.'/src/template/defaults/page_switch.php'); ?>
<?php } else { ?>
<div class="flex justify-start items-center p-5 px-6 w-full sm:w-1/2">
<p class="text-2xl my-2 font-bold sm:font-bold">没有找到搜索结果呢 ...</p>
</div>
<?php } ?>
</div>
</div>
<?php
if (isset($_SESSION['user'])) require(APP_ROOT.'/src/template/defaults/user_profile.php');

41
src/template/defaults/user_profile.php

@ -0,0 +1,41 @@
<!-- Profile -->
<div class="hidden absolute pin-b z-10 lg:relative lg:block w-full lg:w-1/5 bg-grey-lighter-2 px-6 pt-10" id="profile">
<div class="flex items-center mb-6">
<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="avatar">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-1178.000000, -87.000000)">
<g transform="translate(1159.000000, 0.000000)">
<g transform="translate(0.000000, 87.000000)">
<g transform="translate(19.000000, 0.000000)">
<circle id="small-circle" fill="#005CAF" cx="30" cy="30" r="30"></circle>
<path id="moon" d="M30.5,49.7304688 C40.7172679,49.7304688 30.5,43.266096 30.5,33.0488281 C30.5,22.8315603 40.7172679,12 30.5,12 C20.2827321,12 11.0390625,20.6479665 11.0390625,30.8652344 C11.0390625,41.0825022 20.2827321,49.7304688 30.5,49.7304688 Z" fill="#A5DEE4"></path>
<circle id="big-circle" fill="#0B346E" cx="31" cy="31" r="11"></circle>
</g>
</g>
</g>
</g>
</g>
</svg>
<div class="ml-3">
<?php if (isset($_SESSION['user'])) { ?>
<p>您好,<?=$_SESSION['user']['username']?> !</p>
<p class="text-grey-dark mt-1 text-sm">剩余借书配额:<?=$_SESSION['user']['borrow_num']-$records_count?>/<?=$_SESSION['user']['borrow_num']?></p>
<?php } else { ?>
<p>您好,访客用户 !</p>
<p class="text-grey-dark mt-1 text-sm">...</p>
<?php } ?>
</div>
</div>
<div class="my-4 border-t pt-4">
<h3 class="text-indigo-dark font-normal"><strong>当前已借出书籍</strong>(共 <?=$records_count?> 本)</h3>
<div class="flex flex-wrap -ml-2 justify-start items-center">
<?php if (isset($records[0]['rid'])) {
foreach ($records as $record) { ?>
<img src="<?=$record['cover']?>" data-href="/book/<?=$record['bid']?>" class="js-book w-1/6 lg:w-1/5 max-w-tiny shadow-md block m-2 transition-normal hover:brighter">
<?php }
} else { ?>
<p class="block m-2 transition-normal">暂未借阅书籍</p>
<?php } ?>
</div>
</div>
</div>

16
src/template/example/example-popup.php

@ -0,0 +1,16 @@
<div class="hidden p-4" id="popup">
<h3 class="font-medium">Popeye Aug 2019</h3>
<p class="text-sm mt-2 mb-3">Curabitur quis ut pharetra odio id, vitae eros eget tristique maecenas, ullamcorper vitae.</p>
<div class="relative">
<select class="block appearance-none w-full text-sm bg-white border border-grey-light hover:border-grey pl-3 py-1 pr-8 rounded shadow leading-normal focus:outline-none focus:shadow-outline" id="tippy-select">
<option>Start</option>
<option>Loaned</option>
<option selected>Finished</option>
</select>
<div class="pointer-events-none absolute pin-y pin-r flex items-center px-2 text-grey-darker">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
</svg>
</div>
</div>
</div>

43
src/template/example/example-user_profile.php

@ -0,0 +1,43 @@
<!-- Profile -->
<div class="hidden absolute pin-b z-10 lg:relative lg:block w-full lg:w-1/5 bg-grey-lighter-2 px-6 pt-10" id="profile">
<div class="flex items-center mb-6">
<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="avatar">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-1178.000000, -87.000000)">
<g transform="translate(1159.000000, 0.000000)">
<g transform="translate(0.000000, 87.000000)">
<g transform="translate(19.000000, 0.000000)">
<circle id="small-circle" fill="#005CAF" cx="30" cy="30" r="30"></circle>
<path id="moon" d="M30.5,49.7304688 C40.7172679,49.7304688 30.5,43.266096 30.5,33.0488281 C30.5,22.8315603 40.7172679,12 30.5,12 C20.2827321,12 11.0390625,20.6479665 11.0390625,30.8652344 C11.0390625,41.0825022 20.2827321,49.7304688 30.5,49.7304688 Z" fill="#A5DEE4"></path>
<circle id="big-circle" fill="#0B346E" cx="31" cy="31" r="11"></circle>
</g>
</g>
</g>
</g>
</g>
</svg>
<div class="ml-3">
<p>Amie Chen</p>
<p class="text-grey-dark mt-1 text-sm">Joined since 2017</p>
</div>
</div>
<div class="my-4 border-t pt-4">
<h3 class="text-indigo-dark font-normal">You have read <strong>4 of 30 books</strong> in 2019</h3>
<div class="flex flex-wrap -ml-2 justify-start items-center">
<img src="./images/read-01.jpg" alt="read" class="w-1/6 lg:w-1/5 max-w-tiny shadow-md block m-2 transition-normal hover:brighter">
<img src="./images/read-02.jpg" alt="read" class="w-1/6 lg:w-1/5 max-w-tiny shadow-md block m-2 transition-normal hover:brighter">
<img src="./images/read-03.jpg" alt="read" class="w-1/6 lg:w-1/5 max-w-tiny shadow-md block m-2 transition-normal hover:brighter">
<img src="./images/read-04.jpg" alt="read" class="w-1/6 lg:w-1/5 max-w-tiny shadow-md block m-2 transition-normal hover:brighter">
</div>
</div>
<div class="mt-6">
<p class="text-grey-dark mt-1 text-sm">Currently Reading</p>
<div class="flex items-start mt-2">
<img src="./images/read-04.jpg" alt="read" class="w-1/6 lg:w-1/5 max-w-tiny shadow-md block transition-normal hover:brighter">
<div class="ml-3">
<p class="mt-1 leading-normal">Popular Lies* About Graphic Design</p>
<p class="text-indigo text-sm mt-1">15/250 pages</p>
</div>
</div>
</div>
</div>

251
src/template/example/example.php

@ -0,0 +1,251 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">Art &amp; Design</h2>
<p class="text-grey-dark mt-2">Interesting Stats</p>
</div>
<button class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">Add New Book</button>
</div>
<!-- Desktop Stats -->
<div class="hidden px-6 md:px-0 mt-4 md:flex flex-wrap order-1 md:-order-1 md:shadow-md js-tab-pane" id="section-stats">
<div class="p-4 px-6 w-full md:w-1/2 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<h4>Your favourite authors in this category</h4>
<table class="mt-4 w-full">
<thead class="p-2 text-sm leading-loose border-b text-indigo">
<tr>
<td>Name</td>
<td class="text-center">Owned/Wishlist</td>
<td class="text-right">Nationality</td>
</tr>
</thead>
<tbody class="p-2 leading-loose text-sm">
<tr class="border-b">
<td class="py-2">Yohji Yamamoto</td>
<td class="py-2 text-center">5/4</td>
<td class="py-2 text-right">Japan</td>
</tr>
<tr class="border-b">
<td class="py-2">Sato Oki</td>
<td class="py-2 text-center">1/3</td>
<td class="py-2 text-right">Japan</td>
</tr>
<tr>
<td class="py-2">Amaya Arzuaga</td>
<td class="py-2 text-center">1/1</td>
<td class="py-2 text-right">Spain</td>
</tr>
</tbody>
</table>
</div>
<div class="w-full md:w-1/2 p-4 md:pt-12 md:pl-1 mt-4 md:mt-0 lg:pt-12 lg:pl-8 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<div class="flex">
<div class="w-1/2">
<p class="text-indigo text-sm p-2">Most read format</p>
<p class="font-medium text-sm pl-2">Print</p>
</div>
<div class="w-1/2">
<p class="text-indigo text-sm p-2">Total read/own</p>
<p class="font-medium text-sm pl-2">4/7</p>
</div>
</div>
<div class="pt-6">
<p class="text-indigo text-sm p-2">Most re-read book</p>
<p class="font-medium text-sm pl-2 leading-normal">Just My Type: A Book About Fonts
<br><span class="font-normal">by Simon Garfield</span></p>
</div>
</div>
</div>
<!-- Filter -->
<div class="px-6 md:px-0 flex items-baseline justify-between border-b-2 border-grey-light mt-6 order-0 lg:order-1">
<h4 class="hidden md:inline-block text-grey-dark font-normal">Books</h4>
<div>
<div class="inline-block md:hidden no-underline border-indigo pb-2 px-2 text-sm mr-2 text-indigo-darkest hover:cursor-pointer js-tab relative" data-tab="section-stats">Stats</div>
<div class="no-underline inline-block border-indigo pb-2 px-2 text-sm mr-2 text-indigo-darkest hover:cursor-pointer js-tab active relative" data-tab="section-library">Library <span class="text-indigo text-xs">(7)</span></div>
<div class="no-underline inline-block border-indigo pb-2 px-2 text-sm text-indigo-darkest hover:cursor-pointer js-tab relative" data-tab="section-picks">Picks for you</div>
</div>
</div>
<!-- Library -->
<div class="hidden px-2 pt-2 md:px-0 flex-wrap order-2 pb-8 js-tab-pane active" id="section-library">
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full xs:w-1/2 sm:w-1/3 md:w-1/5 p-4 js-book">
<img src="/assets/img/book-01.jpg" alt="book-01" class="w-1/3 sm:w-full shadow-md transition-normal hover:brighter hover:translate-y-1 hover:shadow-lg hover:border-indigo">
<div class="ml-3 sm:ml-0 w-2/3 sm:w-full">
<p class="text-sm my-2 font-medium sm:font-normal">apartmento Aug 2019</p>
<p class="block sm:hidden mt-2 mb-3 text-sm leading-medium">Eu quo donec pellentesque, urna velit. Ultrices ante iaculis ligula praesent.</p>
<label for="" class="hidden sm:inline-block rounded-full libre-bg-grey text-white px-2 py-1/2 text-xs">Loaned</label>
<div class="block sm:hidden relative">
<select class="block appearance-none w-full text-sm bg-white border border-grey-light hover:border-grey pl-3 py-1 pr-8 rounded shadow leading-normal focus:outline-none focus:shadow-outline">
<option>Start</option>
<option>Loaned</option>
<option selected>Finished</option>
</select>
<div class="pointer-events-none absolute pin-y pin-r flex items-center px-2 text-grey-darker">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
</svg>
</div>
</div>
</div>
</div>
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full xs:w-1/2 sm:w-1/3 md:w-1/5 p-4">
<img src="/assets/img/book-02.jpg" alt="book-02" class="w-1/3 sm:w-full shadow-md transition-normal hover:brighter hover:translate-y-1 hover:shadow-lg hover:border-indigo js-book">
<div class="ml-3 sm:ml-0 w-2/3 sm:w-full">
<p class="text-sm my-2 font-medium sm:font-normal">Popeye Aug 2019</p>
<p class="block sm:hidden mt-2 mb-3 text-sm leading-medium">Eu quo donec pellentesque, urna velit. Ultrices ante iaculis ligula praesent.</p>
<label for="" class="hidden sm:inline-block rounded-full libre-bg-yellow text-white px-2 py-1/2 text-xs">Started</label>
<div class="block sm:hidden relative">
<select class="block appearance-none w-full text-sm bg-white border border-grey-light hover:border-grey pl-3 py-1 pr-8 rounded shadow leading-normal focus:outline-none focus:shadow-outline">
<option>Start</option>
<option>Loaned</option>
<option>Reading</option>
<option selected>Finished</option>
</select>
<div class="pointer-events-none absolute pin-y pin-r flex items-center px-2 text-grey-darker">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
</svg>
</div>
</div>
</div>
</div>
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full xs:w-1/2 sm:w-1/3 md:w-1/5 p-4">
<img src="/assets/img/book-03.jpg" alt="book-03" class="w-1/3 sm:w-full shadow-md transition-normal hover:brighter hover:translate-y-1 hover:shadow-lg hover:border-indigo js-book">
<div class="ml-3 sm:ml-0 w-2/3 sm:w-full">
<p class="text-sm my-2 font-medium sm:font-normal">Brutus Aug 2019</p>
<p class="block sm:hidden mt-2 mb-3 text-sm leading-medium">Eu quo donec pellentesque, urna velit. Ultrices ante iaculis ligula praesent.</p>
<label for="" class="hidden sm:inline-block rounded-full libre-bg-pink text-white px-2 py-1/2 text-xs">Reading</label>
<div class="block sm:hidden relative">
<select class="block appearance-none w-full text-sm bg-white border border-grey-light hover:border-grey pl-3 py-1 pr-8 rounded shadow leading-normal focus:outline-none focus:shadow-outline">
<option>Start</option>
<option>Loaned</option>
<option selected>Finished</option>
</select>
<div class="pointer-events-none absolute pin-y pin-r flex items-center px-2 text-grey-darker">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
</svg>
</div>
</div>
</div>
</div>
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full xs:w-1/2 sm:w-1/3 md:w-1/5 p-4">
<img src="/assets/img/book-04.jpg" alt="book-04" class="w-1/3 sm:w-full shadow-md transition-normal hover:brighter hover:translate-y-1 hover:shadow-lg hover:border-indigo js-book">
<div class="ml-3 sm:ml-0 w-2/3 sm:w-full">
<p class="text-sm my-2 font-medium sm:font-normal">Harnako Aug 2019</p>
<p class="block sm:hidden mt-2 mb-3 text-sm leading-medium">Eu quo donec pellentesque, urna velit. Ultrices ante iaculis ligula praesent.</p>
<label for="" class="hidden sm:inline-block rounded-full bg-indigo text-white px-2 py-1/2 text-xs">Finished</label>
<div class="block sm:hidden relative">
<select class="block appearance-none w-full text-sm bg-white border border-grey-light hover:border-grey pl-3 py-1 pr-8 rounded shadow leading-normal focus:outline-none focus:shadow-outline">
<option>Start</option>
<option>Loaned</option>
<option selected>Finished</option>
</select>
<div class="pointer-events-none absolute pin-y pin-r flex items-center px-2 text-grey-darker">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
</svg>
</div>
</div>
</div>
</div>
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full xs:w-1/2 sm:w-1/3 md:w-1/5 p-4">
<img src="/assets/img/book-05.jpg" alt="book-05" class="w-1/3 sm:w-full shadow-md transition-normal hover:brighter hover:translate-y-1 hover:shadow-lg hover:border-indigo js-book">
<div class="ml-3 sm:ml-0 w-2/3 sm:w-full">
<p class="text-sm my-2 font-medium sm:font-normal">Premium 2 2019</p>
<p class="block sm:hidden mt-2 mb-3 text-sm leading-medium">Eu quo donec pellentesque, urna velit. Ultrices ante iaculis ligula praesent.</p>
<label for="" class="hidden sm:inline-block rounded-full bg-indigo text-white px-2 py-1/2 text-xs">Finished</label>
<div class="block sm:hidden relative">
<select class="block appearance-none w-full text-sm bg-white border border-grey-light hover:border-grey pl-3 py-1 pr-8 rounded shadow leading-normal focus:outline-none focus:shadow-outline">
<option>Start</option>
<option>Loaned</option>
<option selected>Finished</option>
</select>
<div class="pointer-events-none absolute pin-y pin-r flex items-center px-2 text-grey-darker">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
</svg>
</div>
</div>
</div>
</div>
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full xs:w-1/2 sm:w-1/3 md:w-1/5 p-4">
<img src="/assets/img/book-06.jpg" alt="book-06" class="w-1/3 sm:w-full shadow-md transition-normal hover:brighter hover:translate-y-1 hover:shadow-lg hover:border-indigo js-book">
<div class="ml-3 sm:ml-0 w-2/3 sm:w-full">
<p class="text-sm my-2 font-medium sm:font-normal">Premium 4 2019</p>
<p class="block sm:hidden mt-2 mb-3 text-sm leading-medium">Eu quo donec pellentesque, urna velit. Ultrices ante iaculis ligula praesent.</p>
<label for="" class="hidden sm:inline-block rounded-full bg-indigo text-white px-2 py-1/2 text-xs">Finished</label>
<div class="block sm:hidden relative">
<select class="block appearance-none w-full text-sm bg-white border border-grey-light hover:border-grey pl-3 py-1 pr-8 rounded shadow leading-normal focus:outline-none focus:shadow-outline">
<option>Start</option>
<option>Loaned</option>
<option selected>Finished</option>
</select>
<div class="pointer-events-none absolute pin-y pin-r flex items-center px-2 text-grey-darker">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
</svg>
</div>
</div>
</div>
</div>
<div class="flex flex-row sm:flex-col items-center sm:items-start w-full xs:w-1/2 sm:w-1/3 md:w-1/5 p-4">
<img src="/assets/img/book-07.jpg" alt="book-07" class="w-1/3 sm:w-full shadow-md transition-normal hover:brighter hover:translate-y-1 hover:shadow-lg hover:border-indigo js-book">
<div class="ml-3 sm:ml-0 w-2/3 sm:w-full">
<p class="text-sm my-2 font-medium sm:font-normal">Brutus Aug 2019</p>
<p class="block sm:hidden mt-2 mb-3 text-sm leading-medium">Eu quo donec pellentesque, urna velit. Ultrices ante iaculis ligula praesent.</p>
<label for="" class="hidden sm:inline-block rounded-full libre-bg-pink text-white px-2 py-1/2 text-xs">Reading</label>
<div class="block sm:hidden relative">
<select class="block appearance-none w-full text-sm bg-white border border-grey-light hover:border-grey pl-3 py-1 pr-8 rounded shadow leading-normal focus:outline-none focus:shadow-outline">
<option>Start</option>
<option>Loaned</option>
<option selected>Finished</option>
</select>
<div class="pointer-events-none absolute pin-y pin-r flex items-center px-2 text-grey-darker">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
</svg>
</div>
</div>
</div>
</div>
</div>
<!-- Picks -->
<div class="hidden flex-wrap order-2 pt-0 md:pt-6 md:pb-8 js-tab-pane" id="section-picks">
<div class="flex justify-start items-center p-5 px-6 w-full sm:w-1/2" style="background-color:#FBC164;">
<img src="/assets/img/pick-1.jpg" alt="pick" class="shadow-md w-1/3">
<div class="ml-4 mt-1 w-2/3">
<p class="font-medium">Popeye Jul 2019</p>
<p class="mt-3 text-sm">Eu quo donec pellentesque, urna velit. Ultrices ante iaculis ligula praesent</p>
<button class="shadow-md mt-3 bg-grey-lightest hover:bg-white text-indigo-darker text-xs py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">Add to Wishlist</button>
</div>
</div>
<div class="flex justify-start items-center p-5 px-6 w-full sm:w-1/2" style="background-color:#F1CECD;">
<img src="/assets/img/pick-2.jpg" alt="pick" class="shadow-md w-1/3">
<div class="ml-4 mt-1 w-2/3">
<p class="font-medium">Brutus Aug 2019</p>
<p class="mt-3 text-sm">Sapien eget, fermentum curabitur quis ut pharetra odio id, vitae eros eget maecenas, ullamcorper vitae.</p>
<button class="shadow-md mt-3 bg-grey-lightest hover:bg-white text-indigo-darker text-xs py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">Add to Wishlist</button>
</div>
</div>
<div class="flex justify-start items-center p-5 px-6 w-full sm:w-1/2" style="background-color:#ECE7E9;">
<img src="/assets/img/pick-3.jpg" alt="pick" class="shadow-md w-1/3">
<div class="ml-4 mt-1 w-2/3">
<p class="font-medium">Casa Aug 2019</p>
<p class="mt-3 text-sm">Curabitur quis ut pharetra odio id, vitae eros eget tristique maecenas, ullamcorper vitae.</p>
<button class="shadow-md mt-3 bg-grey-lightest hover:bg-white text-indigo-darker text-xs py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">Add to Wishlist</button>
</div>
</div>
<div class="flex justify-start items-center p-5 px-6 w-full sm:w-1/2" style="background-color:#D0E3E8;">
<img src="/assets/img/pick-4.jpg" alt="pick" class="shadow-md w-1/3">
<div class="ml-4 mt-1 w-2/3">
<p class="font-medium">SUPER: Jul 2019</p>
<p class="mt-3 text-sm">Eu quo donec pellentesque, urna velit. Ultrices ante iaculis ligula praesent</p>
<button class="shadow-md mt-3 bg-grey-lightest hover:bg-white text-indigo-darker text-xs py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">Add to Wishlist</button>
</div>
</div>
</div>
</div>
<?php
require(APP_ROOT.'/src/template/user_profile.php');
require(APP_ROOT.'/src/template/defaults/example-popup.php');

5
src/template/footer.php

@ -0,0 +1,5 @@
</div>
<script src="/assets/js/bundle.js" async defer></script>
</body>
</html>

71
src/template/header.php

@ -0,0 +1,71 @@
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title><?=$title?> - <?=$GLOBALS['config']['name']?></title>
<meta name="description" content="A responsive web app template with common components like profile, list, tabs, menu views. Made for Codrops exclusively.">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/assets/css/default.css">
</head>
<body class="bg-grey-lighter font-sans antialiased">
<!--[if lt IE 7]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<div class="fixed bg-grey-lighter pin z-50 flex justify-center items-center" id="loading">
<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="morphing">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-1178.000000, -87.000000)">
<g transform="translate(1159.000000, 0.000000)">
<g transform="translate(0.000000, 87.000000)">
<g transform="translate(19.000000, 0.000000)">
<circle id="small-circle" fill="#005CAF" cx="30" cy="30" r="30"></circle>
<path id="moon" d="M30.5,49.7304688 C40.7172679,49.7304688 30.5,43.266096 30.5,33.0488281 C30.5,22.8315603 40.7172679,12 30.5,12 C20.2827321,12 11.0390625,20.6479665 11.0390625,30.8652344 C11.0390625,41.0825022 20.2827321,49.7304688 30.5,49.7304688 Z" fill="#A5DEE4"></path>
<circle id="big-circle" fill="#0B346E" cx="31" cy="31" r="11"></circle>
</g>
</g>
</g>
</g>
</g>
</svg>
</div>
<div class="bg-indigo-darker text-center p-4 px-6 flex items-center">
<div class="hidden lg:block lg:w-1/4 xl:w-1/5 pr-8">
<a href="/" class="flex justify-start pl-6">
<img src="/assets/img/logo.svg" class="" alt="logo">
</a>
</div>
<div class="lg:hidden pr-3" id="mobile-nav-trigger">
<div class="toggle p-2 block"><span></span></div>
</div>
<div class="flex flex-grow items-center lg:w-3/4 xl:w-4/5">
<span class="relative w-full">
<form action="/search">
<input type="search" name="s" value="<?=$_GET['s'] ?? ''?>" placeholder="搜索书名" class="w-full text-sm text-white transition border border-transparent focus:outline-none focus:border-indigo placeholder-white rounded bg-indigo-medium py-1 px-2 pl-10 appearance-none leading-normal ds-input">
</form>
<div class="absolute search-icon" style="top: .5rem; left: .8rem;">
<svg class="fill-current pointer-events-none text-white w-4 h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"></path>
</svg>
</div>
</span>
<?php if (isset($_SESSION['user'])) { ?>
<p class="text-sm text-right text-white py-2 px-3 hidden lg:block lg:w-1/3 px-6">
您好,<?=$_SESSION['user']['username']?> ! [<a class="no-underline text-white hover:text-grey-dark" href="/user/do/logout" >注销</a>]
</p>
<?php } else { ?>
<p class="text-sm text-right text-white py-2 px-3 hidden lg:block lg:w-1/3 px-6">
您尚未
<a class="no-underline text-white hover:text-grey-dark" href="/user/login" >登录</a> |
<a class="no-underline text-white hover:text-grey-dark" href="/user/register" >注册</a>
</p>
<?php } ?>
</div>
</div>
<!-- Main -->
<div class="flex">

67
src/template/side_nav.php

@ -0,0 +1,67 @@
<!-- Side Nav -->
<?php
$nav = [
['name' => '首页', 'id' => 'index', 'svg' => 'home', 'href' => '/'],
['name' => '快捷功能', 'id' => 'categories', 'svg' => 'category', 'sidenav' => [
['name' => '书籍列表', 'href' => '/lists'],
['name' => '书籍检索', 'href' => '/search']
]],
['name' => '用户中心', 'id' => 'users', 'svg' => 'profile', 'sidenav' => [
['name' => '个人资料', 'href' => '/user/info'],
['name' => '借书记录', 'href' => '/user/record']
]],
['name' => '管理中心', 'id' => 'admins', 'svg' => 'wishlist', 'sidenav' => [
['name' => '用户管理', 'href' => '/admin/users'],
['name' => '书籍管理', 'href' => '/admin/books'],
['name' => '库存管理', 'href' => '/admin/stock'],
['name' => '分类管理', 'href' => '/admin/categories'],
]]
];
?>
<nav class="absolute lg:relative lg:flex lg:text-sm bg-indigo-darker lg:bg-transparent pin-l pin-r py-4 px-6 lg:pt-10 lg:pl-12 lg:pr-6 -mt-1 lg:mt-0 overflow-y-auto lg:w-1/5 lg:border-r z-40 hidden">
<ul class="list-reset mb-8 w-full">
<?php
foreach ($nav as $item) {
if (isset($item['sidenav'])) {
if ($item['id'] == 'admins' && !(isset($_SESSION['user']) && $_SESSION['user']['type'] == 1)) continue; ?>
<li class="ml-2 mb-4">
<div class="flex" id="sidenav-<?=$item['id']?>-trigger">
<img src="/assets/img/<?=$item['svg']?>-default.svg" alt="<?=$item['svg']?>-icon" class="w-4 h-4 mr-2">
<div class="hover:cursor-pointer text-white lg:text-indigo-darkest no-underline font-medium w-full relative">
<?=$item['name']."\n"?>
<div class="pointer-events-none absolute pin-y pin-r flex items-center px-1 text-grey-darker" id="sidenav-<?=$item['id']?>-icon">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
</svg>
</div>
</div>
</div>
<ul class="text-grey lg:text-grey-dark list-reset leading-loose mt-2" id="sidenav-<?=$item['id']?>">
<?php foreach ($item['sidenav'] as $sidenav) { ?>
<?=gen_li_tag($sidenav['name'], $sidenav['href'])?>
<?php } ?>
</ul>
</li>
<?php } else { ?>
<li class="ml-2 mb-4 flex">
<img src="/assets/img/<?=$item['svg']?>-default.svg" alt="<?=$item['svg']?>-icon" class="w-4 h-4 mr-2">
<div class="font-medium mobile-home-trigger">
<a class="hover:cursor-pointer text-white lg:text-indigo-darkest no-underline" href="<?=$item['href']?>"><?=$item['name']?></a>
</div>
</li>
<?php }
}
function gen_li_tag($name, $href) {
return $href == explode('?', $_SERVER['REQUEST_URI'])[0] ?
'<li class="flex justify-between items-center transition-normal ml-1 border-l border-grey-dark pl-4 mobile-home-trigger">'.
'<a class="no-underline text-indigo-lighter lg:text-indigo-darker font-medium hover:cursor-pointer" href="'.$href.'">'.
'<span>'.$name.'</span>'.
'</a>'.
'</li>'."\n":
'<li class="transition-normal ml-1 border-l border-grey-dark pl-4">'.
'<a class="no-underline text-white lg:text-grey-dark hover:text-indigo-dark hover:cursor-pointer" href="'.$href.'">'.$name.'</a>'.
'</li>'."\n";
}
?>
</nav>

47
src/template/users/info.php

@ -0,0 +1,47 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">个人资料</h2>
</div>
<a href="/user/update" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">更新信息</a>
</div>
<div class="px-6 md:px-0 mt-4 md:flex flex-wrap order-1 md:-order-1 md:shadow-md" id="section-stats">
<div class="p-4 px-6 w-full md:w-1/2 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<h4>基本信息</h4>
<div class="mt-4 w-full flex">
<div class="w-1/2">
<p class="text-indigo text-sm p-2">用户名</p>
<p class="font-medium text-sm pl-2"><?=$_SESSION['user']['username']?></p>
</div>
</div>
<div class="mt-4 w-full flex">
<div class="w-1/2">
<p class="text-indigo text-sm p-2">性别</p>
<p class="font-medium text-sm pl-2"><?=$_SESSION['user']['sex']?'男':'女'?></p>
</div>
<div class="w-1/2">
<p class="text-indigo text-sm p-2">生日</p>
<p class="font-medium text-sm pl-2"><?=$_SESSION['user']['birthday']?></p>
</div>
</div>
</div>
<div class="w-full md:w-1/2 p-4 md:pt-12 md:pl-1 mt-4 md:mt-0 lg:pt-12 lg:pl-8 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<div class="pt-6">
<p class="text-indigo text-sm p-2">身份证</p>
<p class="font-medium text-sm pl-2 leading-normal"><?=$_SESSION['user']['id_card']?></p>
</div>
<div class="flex">
<div class="w-1/2">
<p class="text-indigo text-sm p-2">借书配额</p>
<p class="font-medium text-sm pl-2"><?=$_SESSION['user']['borrow_num']?></p>
</div>
<div class="w-1/2">
<p class="text-indigo text-sm p-2">访问级别</p>
<p class="font-medium text-sm pl-2"><?=$_SESSION['user']['type']?'管理员':'普通用户'?></p>
</div>
</div>
</div>
</div>
</div>

27
src/template/users/login.php

@ -0,0 +1,27 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">用户登录</h2>
<p class="mt-2">
<a class="no-underline text-grey-dark" href="/user/register">没有账号?点我注册</a>
</p>
<form action="/user/do/login" method="post">
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 用户名:<input type="text" name="username" />
</p>
<p class="text-grey-dark mt-2">
 密 码:<input type="password" name="password" />
</p>
<p class="text-grey-dark mt-2">
 
</p>
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value=" 登 录 " />
</form>
</div>
</div>
</div>

65
src/template/users/record.php

@ -0,0 +1,65 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">借书记录</h2>
</div>
<a href="/lists" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">借阅更多</a>
</div>
<div class="px-6 md:px-0 mt-4 md:flex flex-wrap order-1 md:-order-1 md:shadow-md">
<div class="p-4 px-6 w-full md:w-1/2 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<h4>借阅列表</h4>
<table class="mt-4 w-full">
<thead class="p-2 text-sm leading-loose border-b text-indigo">
<tr>
<td>书名</td>
<td class="hidden js-mobile-hidden">作者</td>
<td class="hidden js-mobile-hidden">出版社</td>
<td class="text-center hidden js-mobile-hidden">ISBN</td>
<td class="text-right">借书日期</td>
<td class="text-right">还书日期</td>
</tr>
</thead>
<tbody class="p-2 leading-loose text-sm">
<?php if (isset($books[0]['rid'])) {
foreach ($books as $book) { ?><tr class="border-b">
<td class="py-2"><?=$book['name']?></td>
<td class="py-2 hidden js-mobile-hidden"><?=$book['author']?></td>
<td class="py-2 hidden js-mobile-hidden"><?=$book['publish']?></td>
<td class="py-2 text-center hidden js-mobile-hidden"><?=$book['isbn']?></td>
<td class="py-2 text-right"><?=date('Y-m-d', $book['borrow_time'])?></td>
<?php if ($book['state']) { ?>
<td class="py-2 text-right"><?=date('Y-m-d', $book['return_time'])?></td>
<?php } else { ?>
<td class="py-2 text-right">
<a href="/user/update-record?page=<?=$page?>&rid=<?=$book['rid']?>&sid=<?=$book['sid']?>" class="no-underline bg-indigo-dark hover:bg-indigo-darker text-white text-sm px-1 transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none">归还</a>
</td>
<?php } ?>
</tr>
<?php }
} else { ?>
<tr class="border-b">
<td class="py-2">没有记录</td>
</td>
<?php } ?>
</tbody>
</table>
</div>
<div class="w-full md:w-1/2 p-4 md:pt-12 md:pl-1 mt-4 md:mt-0 lg:pt-12 lg:pl-8 rounded md:rounded-r-none bg-white shadow-md md:shadow-none">
<div class="flex">
<div class="w-1/2">
<p class="text-indigo text-sm p-2">借书配额</p>
<p class="font-medium text-sm pl-2"><?=$stock?>/<?=$_SESSION['user']['borrow_num']?></p>
</div>
<div class="w-1/2">
<p class="text-indigo text-sm p-2">访问级别</p>
<p class="font-medium text-sm pl-2"><?=$_SESSION['user']['type']?'管理员':'普通用户'?></p>
</div>
</div>
<div class="pt-6">
<?php $path = '/admin/books'; require(APP_ROOT.'/src/template/admins/page_switch.php'); ?>
</div>
</div>
</div>
</div>

33
src/template/users/register.php

@ -0,0 +1,33 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">用户注册</h2>
<p class="mt-2">
<a class="no-underline text-grey-dark" href="/user/login">已有账号?点我登录</a>
</p>
<form action="/user/do/register" method="post">
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 用户名:<input type="text" name="username" />
</p>
<p class="text-grey-dark mt-2">
 身份证:<input type="text" name="id_card" />
</p>
<p class="text-grey-dark mt-2">
 密 码:<input type="password" name="password" />
</p>
<p class="text-grey-dark mt-2">
重复密码:<input type="password" name="confirm" />
</p>
<p class="text-grey-dark mt-2">
 
</p>
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value=" 注 册 " />
</form>
</div>
</div>
</div>

32
src/template/users/update.php

@ -0,0 +1,32 @@
<!-- Content -->
<div class="flex flex-1 flex-col md:px-6 pt-10" id="content">
<!-- Title -->
<div class="px-6 md:px-0 flex justify-between items-center -order-1">
<div>
<h2 class="font-normal">更新信息</h2>
<p class="text-grey-dark mt-2">留空则不作修改</p>
<form action="/user/do/update" method="post">
<p class="mt-2" style="color:red">
    <?=strip_tags($_GET['error']??' ')?>
</p>
<p class="text-grey-dark mt-2">
 性 别:<select name="sex">
<option value="1" <?=$_SESSION['user']['sex']?'selected':''?>></option><option value="0" <?=$_SESSION['user']['sex']?'':'selected'?>></option></select>
</p>
<p class="text-grey-dark mt-2">
 生 日:<input type="text" name="birthday" value="<?=$_SESSION['user']['birthday']?>"/>
</p>
<p class="text-grey-dark mt-2">
 密 码:<input type="password" name="password" />
</p>
<p class="text-grey-dark mt-2">
重复密码:<input type="password" name="confirm" />
</p>
<p class="text-grey-dark mt-2">
 
</p>
<input class="bg-indigo-dark hover:bg-indigo-darker text-white text-sm py-2 px-4 rounded-full transition-normal hover:shadow hover:translate-y-1 active:translate-y-1 focus:outline-none" type="submit" value=" 更 新 " />
</form>
</div>
</div>
</div>
Loading…
Cancel
Save