diff --git a/HTTPWrapper b/HTTPWrapper index efbdcd7..8a274d8 160000 --- a/HTTPWrapper +++ b/HTTPWrapper @@ -1 +1 @@ -Subproject commit efbdcd7554942a0999a4f29fc95d79e7c9d3c1f8 +Subproject commit 8a274d862c609a734f5c287e70af3e6717e011f9 diff --git a/design.txt b/design.txt new file mode 100644 index 0000000..c15866a --- /dev/null +++ b/design.txt @@ -0,0 +1,207 @@ +数据库作业: +语言 + JavaScript,HTML,C++ +数据库: + MySQL + +=================== +数据库表设计 +=================== + +表前缀: bs_ +用户表(bs_user) + 登录账号 varchar 主键 + 登录密码 varchar (hashed) + 昵称 varchar + 用户级别 integer (0 超级管理员 1 管理员 2 图书馆借阅处 3 读者) + 3级用户必须有对应的用户信息! + 账户状态 integer (0 隐藏 1 禁止登陆 2 需要验证才能激活 3 允许登陆) + 隐藏状态: 以该登陆账号登陆时会提示账户不存在,但注册时会提示不能不注册 + 禁止登陆: 以该登陆账号登陆时会提示账户已被禁用 + 待验证: 刚注册完的用户需要经过验证,登陆时会提示待验证. 验证后状态变为3 + 允许登陆: 一切正常 + +级别表(bs_level) + 等级 integer 主键 + 默认最低借阅限额 integer + 默认最高借阅限额 integer + 默认最低借阅时间 integer + 默认最高借阅时间 integer + 可接受的最小余额额度 money + +读者表(bs_reader) + 登录账号 外键到bs_user + 姓名 varchar + 身份证号 varchar + 联系电话 varchar + 等级 integer (触发器->升级->改变限额等信息) 外键到bs_level + 成长值(经验值) integer (签到送经验值等等) + 借阅限额 integer (可以与级别表中的默认值不一致,但升级时会受到影响进而重新评估) + 已使用借阅额度 integer 冗余 + 借阅时间限额 integer (天) + 积分 integer (签到,奖励,活动) + 余额 money + +图书类别表(bs_booktype) + 类别名称 varchar 主键 + +图书表(bs_book) + 图书定义序号 varchar 主键 (考虑到有些书没有ISBN号) + ISBN号 varchar 主键 + 名称 varchar + 类别 外键到bs_booktype + 作者 varchar + 出版社 varchar + 出版日期 date + 状态 integer (0 隐藏 1 禁用 2 正常) + 隐藏: 不在图书搜索中显示这本书的信息 + 禁用: 禁止借阅这本书 + +图书状态表(bs_bookstatus) + 图书实体序号 varchar 主键 (一本书可能在图书馆里有多本藏书) + 图书类别序号 外键到bs_book + 位置 varchar (用来提示图书所在位置) + 状态 integer (0 借出 1 丢失 2 在馆) + 借出: 书籍已借出,可以在bs_borrow中查找到 + 丢失: 书籍已丢失,且无法从其他表中查找到有关信息.(用于报告丢失) + 在馆: 书籍在馆,可以借出 + +借阅关系表(bs_borrow) + 借阅者账号 外键到bs_user + 图书实体序号 外键到bs_bookstatus + 借阅日期 date + 最迟还书日期 date (即使用户在借阅图书后升级,这个日期也不会改动. 此日期是在借阅书籍的时候计算的) + 还书日期 date 可以为空 (如果没还书就是null,否则表示书已归还,此条数据留存为历史数据) + +=================== +特性设计 +=================== +5分钟安装(在线安装,类似Wordpress Install) +超级管理员账号 可以修改所有账户的密码,此账户只能有一个,可以添加管理员账号,其他功能同管理员账号 +管理员账号 可以修改自己和所有普通用户的密码,添加/修改图书类别表,其他功能同图书馆借阅处账号 +图书馆借阅处账号 可以修改自己的密码,添加/修改借阅关系表 + +=================== +具体设计 +=================== +5分钟安装需要的信息: + 数据库服务器地址 dbaddr + 数据库端口 dbport + 数据库账户 dbuser + 数据库口令 dbpass + 数据库名称 dbname + 超级管理员口令 supass (超级管理员账户锁定为root) + +新建账号: + session + +增删改查 : 图书类别,图书,账户 + http://booksys.com/api/v1/install POST + POST: + dbaddr,dbport,dbuser,dbpass,dbname,supass + + http://booksys.com/api/v1/search?type=...&name=... GET + GET: + type= 0 用户 1 书籍 + name= 用户名,书籍名称 + typename= 书籍种类名称,仅当type为1时有效 + + http://booksys.com/api/v1/explore GET + GET: + 没有参数 + + http://booksys.com/api/v1/addbook POST + POST: + (图书定义序号自动生成) + isbn + bookname + booktype + author + publisher + pubdate + status + + http://booksys.com/api/v1/editbook POST + POST: + book_key (唯一图书定义序号) + isbn + bookname + booktype + author + publisher + pubdate + status + + http://booksys.com/api/v1/removebook POST + POST: + book_key (唯一图书定义序号) + + 错误: + 当图书的任一实体处于借出状态时将不能删除图书定义. + + http://booksys.com/api/v1/addbooktype POST + POST: + booktype + + 错误: + 当新的类型名称发生冲突 + + http://booksys.com/api/v1/editbooktype POST + POST: + booktype_old + booktype_new + + 错误: + 当新的类型名称发生冲突 + + 副作用: + 改变图书种类会引起所有与原种类相关图书的信息变更 + + http://booksys.com/api/v1/removebooktype POST + POST: + booktype + + 错误: + 当任一图书定义使用此定义时将不能删除图书种类 + + http://booksys.com/api/v1/register POST + POST: + account + pass + nickname + + 提示:通过此API注册的用户等级锁定为3. 且注册后账户处于状态2 + + 错误: + 账户名称重复时 + + http://booksys.com/api/v1/enableuser POST + POST: + account + realname + realid + realphone + + 提示:通过此API激活的用户等级必须为3.(更高等级的用户不需要经此激活) 激活后账户状态将自动变更为3. + + 错误: + 内容填充错误或禁止激活. + + http://booksys.com/api/v1/login POST + POST: + account + pass + + 提示:通过此API可登陆的用户等级为0,1,2,3,账户状态为3才能登陆成功,账户状态为2时返回提示信息前往激活,账户状态为1时返回禁止登陆,账户状态为0时返回需要联系管理员激活信息. + + 错误: + 账户或密码错误(包括账户错误) + + 返回: + 当登陆成功时返回一个apikey用于调用以上的API. 此key在一段时间内有效. + + http://booksys.com/api/v1/logout POST + POST: + apikey + + 提示:退出登陆. 会立刻注销此apikey \ No newline at end of file diff --git a/search.cpp b/search.cpp index e69de29..c94b20c 100644 --- a/search.cpp +++ b/search.cpp @@ -0,0 +1,147 @@ +#include "Request.h" +#include "Response.h" +#include "Util.h" +#include "json.hpp" +using namespace std; +using json=nlohmann::json; + +int main() +{ + Request req; + Response res; + json j; + + auto jsonfail=[&](int errcode,const std::string& errmsg) + { + j["success"]=0; + j["errcode"]=errcode; + j["errmsg"]=errmsg; + }; + + if(req.requestMethod=="GET") + { + if(req.get["type"].empty()) + { + jsonfail(2,"Missing Parameter: type"); + } + else + { + string searchType=req.get["type"]; + if(searchType=="0") + { + /// Search User + if(req.get["name"].empty()) + { + jsonfail(3,"Missing Parameter: name"); + } + else + { + /// Search User by ONLY nickname. + string nickname=req.get["name"]; + DBInfo db; + if(db.readConfig()<0) + { + /// Failed to read config. May be not installed. + jsonfail(4,"Failed to read configure."); + } + else + { + MySQLConn conn; + if(db.connectProxy(conn)<0) + { + jsonfail(5,"Failed to connect DB"); + } + else + { + vector> vec; + if(conn.exec(make_str("select name from bs_user where nickname like '%",nickname,"%'"),[&](MySQLResult& res) + { + res.stepRow([&](char** val,unsigned long* len) + { + vec.push_back(make_pair(val[0],val[1])); + }); + })<0) + { + jsonfail(6,"Failed to execute SQL."); + } + else + { + j["success"]=1; + int sz=vec.size(); + for(int i=0;i> vec; + if(conn.exec(make_str("select class_id,name from bs_book where name like '%",bookname,"%'"),[&](MySQLResult& res) + { + res.stepRow([&](char** val,unsigned long* len) + { + vec.push_back(make_pair(val[0],val[1])); + }); + })<0) + { + jsonfail(16,"Failed to execute SQL."); + } + else + { + j["success"]=1; + int sz=vec.size(); + for(int i=0;i