├── README.md ├── administrator.py ├── book_information.py ├── createDB.py ├── func.py ├── icon ├── book.png ├── borrowing.png ├── detial.png ├── history.png └── person.png ├── image ├── bg.jpg └── image.png ├── login.py ├── main.py ├── signup.py ├── student.py ├── student_information.py ├── 演示视频.mp4 └── 说明.pdf /README.md: -------------------------------------------------------------------------------- 1 | # Library-Management-System 2 | 3 | 图书管理系统,学弟学妹们记得star和fork哦 4 | 5 | 功能详见 说明.pdf(其实就是我当时的实验报告,差不多可以直接用) 6 | 7 | ## 注意事项 8 | 9 | 没想到还有挺多人看的,简单修复了一下错误,基本功能应该是没啥问题,学弟学妹们可以自行添加/删除功能。 10 | 11 | 2024.5.4号更新,4个issues都解决了,现在基本功能应该没啥问题了。 12 | 13 | 在创建数据库的时候,默认加入了一个管理员,用户名/密码为admin/123456。后面新注册的都是学生用户,密码在数据表里面存储的都是加密后的数据。 14 | 15 | 数据表里面本来是有挺多条数据的,找不到了。。。大家自己添加几条信息吧,也可以看我上传的视频,看看效果。 16 | 17 | ## 使用前提 18 | 19 | 保证已安装mysql数据库。 20 | 21 | 我记得这门课应该有历代祖传的mysql5.6+navicat。按照提示安装即可。 22 | 23 | ![alt text](image/image.png) 24 | 25 | ## 使用方法 26 | 27 | 1.首先需要单独执行createDB.py来创建数据库。(python环境要有pymsql包) 28 | 29 | 2.创建好之后执行main.py即可运行。(python环境要有pyqt5) 30 | 31 | ## 代码文件说明 32 | 33 | 1. icon文件夹:存放一些小图标。 34 | 2. image文件夹:存放一些图片。 35 | 3. createDB.py:创建数据库的文件,运行一次把这些表创建就行。会创建一个名为library的数据库,里面有6张表。 36 | 4. main.py:程序执行主文件。 37 | 5. login.py:登录前端界面代码。 38 | 6. signup.py:注册前端界面代码。 39 | 7. administrator.py:管理员前端界面代码。 40 | 8. book_information.py:管理员前端界面中编辑书本信息的界面代码。 41 | 9. student.py:学生前端界面代码。 42 | 10. student_information.py:学生前端界面中学生信息界面代码。 43 | 11. func.py:所有的后端处理函数。 44 | -------------------------------------------------------------------------------- /administrator.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | import os 4 | from PyQt5.QtWidgets import (QApplication, QWidget, QGridLayout, QGroupBox, 5 | QToolButton, QSplitter, QVBoxLayout, QHBoxLayout, 6 | QLabel, QTableWidget, QTableWidgetItem, QAbstractItemView, 7 | QLineEdit, QFileDialog, QMessageBox, QComboBox) 8 | from PyQt5.QtGui import QIcon, QFont 9 | from PyQt5.QtCore import Qt, QSize 10 | import func 11 | import student_information 12 | import book_information 13 | 14 | 15 | class AdministratorPage(QWidget): 16 | def __init__(self, info): 17 | super().__init__() 18 | self.info = info 19 | self.focus = 0 20 | self.initUI() 21 | 22 | def initUI(self): 23 | # 标题栏 24 | self.titleBar = QWidget() 25 | self.titleBar.setFixedSize(1250, 50) 26 | self.setTitleBar() 27 | 28 | # 分割 29 | self.body = QSplitter(Qt.Vertical,self) 30 | self.setLeftMunu() 31 | self.content = None 32 | self.setContent() 33 | 34 | self.bodyLayout = QGridLayout() 35 | self.bodyLayout.addWidget(self.titleBar, 0, 0, 1, 7) 36 | self.bodyLayout.addWidget(self.body, 1, 0, 7, 7) 37 | self.setContentsMargins(0, 0, 0, 0) 38 | self.setLayout(self.bodyLayout) 39 | self.setFixedSize(1280, 720) 40 | self.setMyStyle() 41 | 42 | # 设置标题栏 43 | def setTitleBar(self): 44 | self.title = QLabel() 45 | self.title.setText('图书馆管理系统-----管理员界面') 46 | self.title.setFixedHeight(30) 47 | 48 | self.account = QToolButton() 49 | self.account.setIcon(QIcon('icon/person.png')) 50 | self.account.setText('管理员用户:'+ self.info['aid']) 51 | self.account.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) 52 | self.account.setFixedHeight(30) 53 | self.account.setEnabled(False) 54 | 55 | self.out = QToolButton() 56 | self.out.setText('退出') 57 | self.out.setFixedHeight(30) 58 | 59 | titleLayout = QHBoxLayout() 60 | titleLayout.addSpacing(100) 61 | titleLayout.addWidget(self.title) 62 | titleLayout.addWidget(self.account) 63 | titleLayout.addWidget(self.out) 64 | self.titleBar.setLayout(titleLayout) 65 | 66 | def setLeftMunu(self): 67 | # 书籍管理 68 | self.bookManage = QToolButton() 69 | self.bookManage.setText('图书管理') 70 | self.bookManage.setFixedSize(160, 50) 71 | self.bookManage.setIcon(QIcon('icon/book.png')) 72 | self.bookManage.setIconSize(QSize(30, 30)) 73 | self.bookManage.clicked.connect( 74 | lambda: self.switch(0, self.bookManage)) 75 | self.bookManage.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) 76 | 77 | # 用户管理 78 | self.userManage = QToolButton() 79 | self.userManage.setText('用户管理') 80 | self.userManage.setFixedSize(160, 50) 81 | self.userManage.setIcon(QIcon('icon/detial.png')) 82 | self.userManage.setIconSize(QSize(30, 30)) 83 | self.userManage.clicked.connect(lambda: self.switch(1, self.userManage)) 84 | self.userManage.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) 85 | 86 | # 借阅日志 87 | self.history = QToolButton() 88 | self.history.setText('借阅日志') 89 | self.history.setFixedSize(160, 50) 90 | self.history.setIcon(QIcon('icon/history.png')) 91 | self.history.setIconSize(QSize(30, 30)) 92 | self.history.clicked.connect(lambda: self.switch(2, self.history)) 93 | self.history.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) 94 | 95 | 96 | 97 | self.btnList = [self.bookManage, 98 | self.userManage, self.history] 99 | 100 | self.layout = QHBoxLayout() 101 | self.layout.addStretch() 102 | self.layout.addWidget(self.bookManage) 103 | self.layout.addStretch() 104 | self.layout.addWidget(self.userManage) 105 | self.layout.addStretch() 106 | self.layout.addWidget(self.history) 107 | self.layout.addStretch() 108 | self.layout.setContentsMargins(0, 0, 0, 0) 109 | self.layout.setSpacing(0) 110 | 111 | self.menu = QGroupBox() 112 | self.menu.setFixedSize(1250, 50) 113 | self.menu.setLayout(self.layout) 114 | self.menu.setContentsMargins(0, 0, 0, 0) 115 | self.body.addWidget(self.menu) 116 | 117 | def switch(self, index, btn): 118 | self.focus = index 119 | for i in self.btnList: 120 | i.setStyleSheet(''' 121 | *{ 122 | background: white; 123 | } 124 | QToolButton:hover{ 125 | background-color: rgba(230, 230, 230, 0.3); 126 | } 127 | ''') 128 | 129 | btn.setStyleSheet(''' 130 | QToolButton{ 131 | background-color: rgba(230, 230, 230, 0.7); 132 | } 133 | ''') 134 | self.setContent() 135 | 136 | # 设置右侧信息页 137 | def setContent(self): 138 | if self.content is not None: 139 | self.content.deleteLater() 140 | if self.focus == 0: 141 | self.content = BookManage() 142 | elif self.focus == 1: 143 | self.content = StudentManage() 144 | elif self.focus == 2: 145 | self.content = HistoryManage() 146 | self.body.addWidget(self.content) 147 | 148 | def setMyStyle(self): 149 | self.setStyleSheet(''' 150 | QWidget{ 151 | background-color: white; 152 | } 153 | ''') 154 | self.titleBar.setStyleSheet(''' 155 | QWidget{ 156 | background-color: rgba(44,44,44,1); 157 | border:1px solid black; 158 | } 159 | ''') 160 | self.menu.setStyleSheet(''' 161 | QWidget{ 162 | border: 0px; 163 | border-right: 1px solid rgba(227, 227, 227, 1); 164 | } 165 | QToolButton{ 166 | color: rgba(51, 90, 129, 1); 167 | font-family: 微软雅黑; 168 | font-size: 25px; 169 | border-right: 1px solid rgba(227, 227, 227, 1); 170 | } 171 | QToolButton:hover{ 172 | background-color: rgba(230, 230, 230, 0.3); 173 | } 174 | ''') 175 | self.title.setStyleSheet(''' 176 | *{ 177 | color: white; 178 | font-family: 微软雅黑; 179 | font-size: 25px; 180 | border: 0px; 181 | } 182 | ''') 183 | self.account.setStyleSheet(''' 184 | *{ 185 | color: white; 186 | font-weight: 微软雅黑; 187 | font-size: 25px; 188 | border: 0px; 189 | } 190 | ''') 191 | self.out.setStyleSheet(''' 192 | QToolButton{ 193 | color: white; 194 | border:0px; 195 | font-size: 12px; 196 | } 197 | QToolButton:hover{ 198 | color: rgba(11, 145, 255, 1); 199 | } 200 | ''') 201 | 202 | 203 | class BookManage(QGroupBox): 204 | def __init__(self): 205 | super().__init__() 206 | self.book_list = [] 207 | self.body = QVBoxLayout() 208 | self.table = None 209 | self.setTitleBar() 210 | self.setSearchBar() 211 | self.searchFunction() 212 | 213 | self.setLayout(self.body) 214 | self.initUI() 215 | 216 | # 标题栏 217 | def setTitleBar(self): 218 | self.title = QLabel() 219 | self.title.setText('书籍信息管理') 220 | self.title.setFixedHeight(25) 221 | titleLayout = QHBoxLayout() 222 | titleLayout.addStretch() 223 | titleLayout.addWidget(self.title) 224 | titleLayout.addStretch() 225 | self.titleBar = QWidget() 226 | self.titleBar.setFixedSize(1250, 50) 227 | self.titleBar.setLayout(titleLayout) 228 | self.body.addWidget(self.titleBar) 229 | 230 | # 设置搜索框 231 | def setSearchBar(self): 232 | self.selectBox = QComboBox() 233 | self.selectBox.addItems(['书号', '分类', '出版社', '作者', '书名']) 234 | self.selectBox.setFixedHeight(30) 235 | self.searchTitle = QLabel() 236 | self.searchTitle.setText('搜索书籍') 237 | self.searchInput = QLineEdit() 238 | self.searchInput.setText('') 239 | self.searchInput.setClearButtonEnabled(True) 240 | self.searchInput.setFixedSize(400, 40) 241 | self.searchButton = QToolButton() 242 | self.searchButton.setFixedSize(100, 40) 243 | self.searchButton.setText('搜索') 244 | self.searchButton.clicked.connect(self.searchFunction) 245 | self.addNewBookButton = QToolButton() 246 | self.addNewBookButton.setFixedSize(120, 40) 247 | self.addNewBookButton.setText('插入新书') 248 | self.addNewBookButton.clicked.connect(self.addNewBookFunction) 249 | searchLayout = QHBoxLayout() 250 | searchLayout.addStretch() 251 | searchLayout.addWidget(self.selectBox) 252 | searchLayout.addWidget(self.searchTitle) 253 | searchLayout.addWidget(self.searchInput) 254 | searchLayout.addWidget(self.searchButton) 255 | searchLayout.addWidget(self.addNewBookButton) 256 | searchLayout.addStretch() 257 | self.searchWidget = QWidget() 258 | self.searchWidget.setLayout(searchLayout) 259 | self.body.addWidget(self.searchWidget) 260 | 261 | # 搜索方法 262 | def searchFunction(self): 263 | convert = {'书号': 'bno', '分类': 'class', '出版社': 'press', '作者': 'author', '书名': 'bname', '': 'bname'} 264 | self.book_list = func.search_book(self.searchInput.text(), convert[self.selectBox.currentText()]) 265 | if self.book_list == []: 266 | print('未找到') 267 | if self.table is not None: 268 | self.table.deleteLater() 269 | self.setTable() 270 | 271 | # 设置表格 272 | def setTable(self): 273 | self.table = QTableWidget(1, 9) 274 | self.table.setContentsMargins(10, 10, 10, 10) 275 | self.table.verticalHeader().setVisible(False) 276 | self.table.horizontalHeader().setVisible(False) 277 | self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) 278 | self.table.setFocusPolicy(Qt.NoFocus) 279 | self.table.setColumnWidth(0, 80) 280 | # self.table.setColumnWidth(1, 150) 281 | # self.table.setColumnWidth(2, 125) 282 | # self.table.setColumnWidth(3, 125) 283 | # self.table.setColumnWidth(4, 100) 284 | self.table.setColumnWidth(6, 80) 285 | 286 | self.table.setItem(0, 0, QTableWidgetItem('书号')) 287 | self.table.setItem(0, 1, QTableWidgetItem('书名')) 288 | self.table.setItem(0, 2, QTableWidgetItem('作者')) 289 | self.table.setItem(0, 3, QTableWidgetItem('出版日期')) 290 | self.table.setItem(0, 4, QTableWidgetItem('出版社')) 291 | self.table.setItem(0, 5, QTableWidgetItem('分类')) 292 | self.table.setItem(0, 6, QTableWidgetItem('位置')) 293 | self.table.setItem(0, 7, QTableWidgetItem('总数/剩余')) 294 | self.table.setItem(0, 8, QTableWidgetItem('操作')) 295 | 296 | for i in range(9): 297 | self.table.item(0, i).setTextAlignment(Qt.AlignCenter) 298 | self.table.item(0, i).setFont(QFont('微软雅黑', 15)) 299 | 300 | # 显示借阅详情 301 | for i in self.book_list: 302 | self.insertRow(i) 303 | self.body.addWidget(self.table) 304 | 305 | # 插入行 306 | def insertRow(self, val: list): 307 | itemBID = QTableWidgetItem(val[0]) 308 | itemBID.setTextAlignment(Qt.AlignCenter) 309 | 310 | itemNAME = QTableWidgetItem('《' + val[1] + '》') 311 | itemNAME.setTextAlignment(Qt.AlignCenter) 312 | 313 | itemauthor = QTableWidgetItem(val[2]) 314 | itemauthor.setTextAlignment(Qt.AlignCenter) 315 | 316 | itemDATE = QTableWidgetItem(val[3]) 317 | itemDATE.setTextAlignment(Qt.AlignCenter) 318 | 319 | itemPRESS = QTableWidgetItem(val[4]) 320 | itemPRESS.setTextAlignment(Qt.AlignCenter) 321 | 322 | itemPOSITION = QTableWidgetItem(val[5]) 323 | itemPOSITION.setTextAlignment(Qt.AlignCenter) 324 | 325 | itemSUM = QTableWidgetItem(str(val[6])+'/'+str(val[7])) 326 | itemSUM.setTextAlignment(Qt.AlignCenter) 327 | 328 | itemCLASSIFICATION = QTableWidgetItem(val[8]) 329 | itemCLASSIFICATION.setTextAlignment(Qt.AlignCenter) 330 | 331 | itemModify = QToolButton(self.table) 332 | itemModify.setFixedSize(50, 25) 333 | itemModify.setText('修改') 334 | itemModify.clicked.connect(lambda: self.updateBookFunction(val[0])) 335 | itemModify.setStyleSheet(''' 336 | *{ 337 | color: white; 338 | font-family: 微软雅黑; 339 | background: rgba(38, 175, 217, 1); 340 | border: 0; 341 | } 342 | ''') 343 | itemDelete = QToolButton(self.table) 344 | itemDelete.setFixedSize(50, 25) 345 | itemDelete.setText('删除') 346 | itemDelete.clicked.connect(lambda: self.deleteBookFunction(val[0])) 347 | itemDelete.setStyleSheet(''' 348 | *{ 349 | color: white; 350 | font-family: 微软雅黑; 351 | background: rgba(222, 52, 65, 1); 352 | border: 0; 353 | } 354 | ''') 355 | 356 | itemLayout = QHBoxLayout() 357 | itemLayout.setContentsMargins(0, 0, 0, 0) 358 | itemLayout.addWidget(itemModify) 359 | itemLayout.addWidget(itemDelete) 360 | itemWidget = QWidget() 361 | itemWidget.setLayout(itemLayout) 362 | 363 | self.table.insertRow(1) 364 | self.table.setItem(1, 0, itemBID) 365 | self.table.setItem(1, 1, itemNAME) 366 | self.table.setItem(1, 2, itemauthor) 367 | self.table.setItem(1, 3, itemDATE) 368 | self.table.setItem(1, 4, itemPRESS) 369 | self.table.setItem(1, 5, itemCLASSIFICATION) 370 | self.table.setItem(1, 6, itemPOSITION) 371 | self.table.setItem(1, 7, itemSUM) 372 | self.table.setCellWidget(1, 8, itemWidget) 373 | 374 | def updateBookFunction(self, bno: str): 375 | book_info = func.get_book_info(bno) 376 | if book_info is None: 377 | return 378 | self.sum = book_info['sum'] 379 | self.updateBookDialog = book_information.BookInfo(book_info) 380 | self.updateBookDialog.after_close.connect(self.updateBook) 381 | self.updateBookDialog.show() 382 | 383 | def updateBook(self, book_info: dict): 384 | change = self.sum - book_info['sum'] 385 | # 书本减少的数量不能大于未借出的书本数 386 | if change > book_info['rest']: 387 | book_info['sum'] = self.sum - book_info['rest'] 388 | book_info['rest'] = 0 389 | else: 390 | book_info['rest'] -= change 391 | ans = func.update_book(book_info) 392 | if ans: 393 | self.searchFunction() 394 | 395 | def addNewBookFunction(self): 396 | self.newBookDialog = book_information.BookInfo() 397 | self.newBookDialog.show() 398 | self.newBookDialog.after_close.connect(self.addNewBook) 399 | 400 | def addNewBook(self, book_info: dict): 401 | ans = func.new_book(book_info) 402 | if ans: 403 | self.searchFunction() 404 | 405 | def deleteBookFunction(self, bno: str): 406 | msgBox = QMessageBox(QMessageBox.Warning, "警告!", '您将会永久删除这本书以及相关信息!', 407 | QMessageBox.NoButton, self) 408 | msgBox.addButton("确认", QMessageBox.AcceptRole) 409 | msgBox.addButton("取消", QMessageBox.RejectRole) 410 | if msgBox.exec_() == QMessageBox.AcceptRole: 411 | ans = func.delete_book(bno) 412 | if ans: 413 | self.searchFunction() 414 | 415 | def initUI(self): 416 | self.setFixedSize(1270, 600) 417 | self.setStyleSheet(''' 418 | *{ 419 | background-color: white; 420 | border:0px; 421 | } 422 | ''') 423 | self.titleBar.setStyleSheet(''' 424 | QWidget { 425 | border:0; 426 | background-color: rgba(216, 216, 216, 1); 427 | color: rgba(113, 118, 121, 1); 428 | } 429 | QLabel{ 430 | font-size: 25px; 431 | font-family: 微软雅黑; 432 | } 433 | ''') 434 | self.searchTitle.setStyleSheet(''' 435 | QLabel{ 436 | font-size:25px; 437 | color: black; 438 | font-family: 微软雅黑; 439 | } 440 | ''') 441 | self.searchInput.setStyleSheet(''' 442 | QLineEdit{ 443 | border: 1px solid rgba(201, 201, 201, 1); 444 | color: rgba(120, 120, 120, 1) 445 | } 446 | ''') 447 | self.searchButton.setStyleSheet(''' 448 | QToolButton{ 449 | background-color:rgba(52, 118, 176, 1); 450 | color: white; 451 | font-size: 25px; 452 | font-family: 微软雅黑; 453 | } 454 | ''') 455 | self.addNewBookButton.setStyleSheet(''' 456 | QToolButton{ 457 | background-color:rgba(52, 118, 176, 1); 458 | color: white; 459 | font-size: 25px; 460 | font-family: 微软雅黑; 461 | } 462 | ''') 463 | self.selectBox.setStyleSheet(''' 464 | *{ 465 | border: 0px; 466 | } 467 | QComboBox{ 468 | border: 1px solid rgba(201, 201, 201, 1); 469 | } 470 | ''') 471 | 472 | 473 | class StudentManage(QWidget): 474 | def __init__(self): 475 | super().__init__() 476 | self.book_list = [] 477 | self.body = QVBoxLayout() 478 | self.table = None 479 | self.setTitleBar() 480 | self.setSearchBar() 481 | self.searchFunction() 482 | 483 | self.setLayout(self.body) 484 | self.initUI() 485 | 486 | # 标题栏 487 | def setTitleBar(self): 488 | self.title = QLabel() 489 | self.title.setText('学生信息管理') 490 | self.title.setFixedHeight(25) 491 | titleLayout = QHBoxLayout() 492 | titleLayout.addStretch() 493 | titleLayout.addWidget(self.title) 494 | titleLayout.addStretch() 495 | self.titleBar = QWidget() 496 | self.titleBar.setFixedSize(1270, 50) 497 | self.titleBar.setLayout(titleLayout) 498 | self.body.addWidget(self.titleBar) 499 | 500 | # 设置搜索框 501 | def setSearchBar(self): 502 | self.searchTitle = QLabel() 503 | self.searchTitle.setText('搜索学生') 504 | self.searchInput = QLineEdit() 505 | self.searchInput.setText('ID/姓名') 506 | self.searchInput.setClearButtonEnabled(True) 507 | self.searchInput.setFixedSize(400, 40) 508 | self.searchButton = QToolButton() 509 | self.searchButton.setFixedSize(100, 40) 510 | self.searchButton.setText('搜索') 511 | self.searchButton.clicked.connect(self.searchFunction) 512 | 513 | searchLayout = QHBoxLayout() 514 | searchLayout.addStretch() 515 | searchLayout.addWidget(self.searchTitle) 516 | searchLayout.addWidget(self.searchInput) 517 | searchLayout.addWidget(self.searchButton) 518 | searchLayout.addStretch() 519 | 520 | self.searchWidget = QWidget() 521 | self.searchWidget.setLayout(searchLayout) 522 | self.body.addWidget(self.searchWidget) 523 | 524 | # 搜索方法 525 | def searchFunction(self): 526 | self.stu_list = func.search_student(self.searchInput.text()) 527 | if self.stu_list == []: 528 | print('未找到') 529 | if self.table is not None: 530 | self.table.deleteLater() 531 | self.setTable() 532 | 533 | # 设置表格 534 | def setTable(self): 535 | self.table = QTableWidget(1, 6) 536 | self.table.setContentsMargins(10, 10, 10, 10) 537 | self.table.verticalHeader().setVisible(False) 538 | self.table.horizontalHeader().setVisible(False) 539 | self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) 540 | self.table.setFocusPolicy(Qt.NoFocus) 541 | 542 | self.table.setColumnWidth(2, 150) 543 | self.table.setColumnWidth(3, 175) 544 | self.table.setColumnWidth(4, 175) 545 | self.table.setColumnWidth(5, 120) 546 | 547 | self.table.setItem(0, 0, QTableWidgetItem('学号')) 548 | self.table.setItem(0, 1, QTableWidgetItem('姓名')) 549 | self.table.setItem(0, 2, QTableWidgetItem('学院')) 550 | self.table.setItem(0, 3, QTableWidgetItem('专业')) 551 | self.table.setItem(0, 4, QTableWidgetItem('最大借书数')) 552 | self.table.setItem(0, 5, QTableWidgetItem('操作')) 553 | 554 | for i in range(6): 555 | self.table.item(0, i).setTextAlignment(Qt.AlignCenter) 556 | self.table.item(0, i).setFont(QFont('微软雅黑', 15)) 557 | 558 | # 显示借阅详情 559 | for i in self.stu_list: 560 | self.insertRow(i) 561 | self.body.addWidget(self.table) 562 | 563 | # 插入行 564 | def insertRow(self, val: list): 565 | itemSID = QTableWidgetItem(val[0]) 566 | itemSID.setTextAlignment(Qt.AlignCenter) 567 | 568 | itemNAME = QTableWidgetItem(val[1]) 569 | itemNAME.setTextAlignment(Qt.AlignCenter) 570 | 571 | itemDEPARTMENT = QTableWidgetItem(val[2]) 572 | itemDEPARTMENT.setTextAlignment(Qt.AlignCenter) 573 | 574 | itemMAJOR = QTableWidgetItem(val[3]) 575 | itemMAJOR.setTextAlignment(Qt.AlignCenter) 576 | 577 | itemMAX = QTableWidgetItem(str(val[4])) 578 | itemMAX.setTextAlignment(Qt.AlignCenter) 579 | 580 | itemModify = QToolButton(self.table) 581 | itemModify.setFixedSize(50, 25) 582 | itemModify.setText('修改') 583 | itemModify.clicked.connect(lambda: self.updateStudentFunction(val[0])) 584 | itemModify.setStyleSheet(''' 585 | *{ 586 | color: white; 587 | font-family: 微软雅黑; 588 | background: rgba(38, 175, 217, 1); 589 | border: 0; 590 | } 591 | ''') 592 | itemDelete = QToolButton(self.table) 593 | itemDelete.setFixedSize(50, 25) 594 | itemDelete.setText('删除') 595 | itemDelete.clicked.connect(lambda: self.deleteStudentFunction(val[0])) 596 | itemDelete.setStyleSheet(''' 597 | *{ 598 | color: white; 599 | font-family: 微软雅黑; 600 | background: rgba(222, 52, 65, 1); 601 | border: 0; 602 | } 603 | ''') 604 | 605 | itemLayout = QHBoxLayout() 606 | itemLayout.setContentsMargins(0, 0, 0, 0) 607 | itemLayout.addWidget(itemModify) 608 | itemLayout.addWidget(itemDelete) 609 | itemWidget = QWidget() 610 | itemWidget.setLayout(itemLayout) 611 | 612 | self.table.insertRow(1) 613 | self.table.setItem(1, 0, itemSID) 614 | self.table.setItem(1, 1, itemNAME) 615 | self.table.setItem(1, 2, itemDEPARTMENT) 616 | self.table.setItem(1, 3, itemMAJOR) 617 | self.table.setItem(1, 4, itemMAX) 618 | self.table.setCellWidget(1, 5, itemWidget) 619 | 620 | def updateStudentFunction(self, sno: str): 621 | stu_info = func.get_student_info(sno) 622 | if stu_info is None: 623 | return 624 | self.updateStudentDialog = student_information.StudentInfo(stu_info) 625 | self.updateStudentDialog.after_close.connect(self.updateStudent) 626 | self.updateStudentDialog.show() 627 | 628 | def updateStudent(self, stu_info: dict): 629 | ans = func.update_student(stu_info) 630 | if ans: 631 | self.searchFunction() 632 | 633 | def deleteStudentFunction(self, bno: str): 634 | msgBox = QMessageBox(QMessageBox.Warning, "警告!", '您将会永久删除此学生以及相关信息!', 635 | QMessageBox.NoButton, self) 636 | msgBox.addButton("确认", QMessageBox.AcceptRole) 637 | msgBox.addButton("取消", QMessageBox.RejectRole) 638 | if msgBox.exec_() == QMessageBox.AcceptRole: 639 | ans = func.delete_student(bno) 640 | if ans: 641 | self.searchFunction() 642 | 643 | def initUI(self): 644 | self.setFixedSize(1270, 600) 645 | self.setStyleSheet(''' 646 | *{ 647 | background-color: white; 648 | border:0px; 649 | } 650 | ''') 651 | self.titleBar.setStyleSheet(''' 652 | QWidget { 653 | border:0; 654 | background-color: rgba(216, 216, 216, 1); 655 | color: rgba(113, 118, 121, 1); 656 | } 657 | QLabel{ 658 | font-size: 25px; 659 | font-family: 微软雅黑; 660 | } 661 | ''') 662 | self.searchTitle.setStyleSheet(''' 663 | QLabel{ 664 | font-size:25px; 665 | color: black; 666 | font-family: 微软雅黑; 667 | } 668 | ''') 669 | self.searchInput.setStyleSheet(''' 670 | QLineEdit{ 671 | border: 1px solid rgba(201, 201, 201, 1); 672 | color: rgba(120, 120, 120, 1) 673 | } 674 | ''') 675 | self.searchButton.setStyleSheet(''' 676 | QToolButton{ 677 | background-color:rgba(52, 118, 176, 1); 678 | color: white; 679 | font-size: 25px; 680 | font-family: 微软雅黑; 681 | } 682 | ''') 683 | 684 | 685 | class BorrowManage(QWidget): 686 | def __init__(self): 687 | super().__init__() 688 | self.body = QVBoxLayout() 689 | self.borrow_list = [] 690 | self.table = None 691 | self.setTitleBar() 692 | self.setSearchBar() 693 | self.searchFunction() 694 | 695 | self.setLayout(self.body) 696 | self.initUI() 697 | 698 | # 标题栏 699 | def setTitleBar(self): 700 | self.title = QLabel() 701 | self.title.setText('借阅信息管理') 702 | self.title.setFixedHeight(25) 703 | titleLayout = QHBoxLayout() 704 | titleLayout.addStretch() 705 | titleLayout.addWidget(self.title) 706 | titleLayout.addStretch() 707 | self.titleBar = QWidget() 708 | self.titleBar.setFixedSize(1270, 50) 709 | self.titleBar.setLayout(titleLayout) 710 | self.body.addWidget(self.titleBar) 711 | 712 | # 设置搜索框 713 | def setSearchBar(self): 714 | self.searchTitle = QLabel() 715 | self.searchTitle.setText('搜索学生') 716 | self.searchInput = QLineEdit() 717 | self.searchInput.setText('ID/姓名') 718 | self.searchInput.setClearButtonEnabled(True) 719 | self.searchInput.setFixedSize(450, 40) 720 | self.searchStudentButton = QToolButton() 721 | self.searchStudentButton.setFixedSize(120, 40) 722 | self.searchStudentButton.setText('搜索学号') 723 | self.searchStudentButton.clicked.connect(lambda: self.searchFunction('sno')) 724 | 725 | self.searchBookButton = QToolButton() 726 | self.searchBookButton.setFixedSize(120, 40) 727 | self.searchBookButton.setText('搜索书号') 728 | self.searchBookButton.clicked.connect(lambda: self.searchFunction()) 729 | 730 | searchLayout = QHBoxLayout() 731 | searchLayout.addStretch() 732 | searchLayout.addWidget(self.searchTitle) 733 | searchLayout.addWidget(self.searchInput) 734 | searchLayout.addWidget(self.searchStudentButton) 735 | searchLayout.addWidget(self.searchBookButton) 736 | searchLayout.addStretch() 737 | 738 | self.searchWidget = QWidget() 739 | self.searchWidget.setLayout(searchLayout) 740 | self.body.addWidget(self.searchWidget) 741 | 742 | # 搜索方法 743 | def searchFunction(self, e: str = 'bno'): 744 | # 搜索书号 745 | if e == 'bno': 746 | self.borrow_list = func.get_borrowing_books(self.searchInput.text(), True) 747 | else: 748 | # 搜索学号 749 | self.borrow_list = func.get_borrowing_books(self.searchInput.text()) 750 | self.sno = self.searchInput.text() 751 | if self.borrow_list == []: 752 | print('未找到') 753 | if self.table is not None: 754 | self.table.deleteLater() 755 | self.setTable() 756 | 757 | # 设置表格 758 | def setTable(self, val: dict = None): 759 | self.table = QTableWidget(1, 7) 760 | self.table.setContentsMargins(10, 10, 10, 10) 761 | self.table.setFixedHeight(500) 762 | self.table.verticalHeader().setVisible(False) 763 | self.table.horizontalHeader().setVisible(False) 764 | self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) 765 | self.table.setFocusPolicy(Qt.NoFocus) 766 | self.table.setColumnWidth(2, 120) 767 | self.table.setColumnWidth(1, 120) 768 | self.table.setColumnWidth(4, 170) 769 | self.table.setColumnWidth(3, 170) 770 | 771 | self.table.setItem(0, 0, QTableWidgetItem('学生号')) 772 | self.table.setItem(0, 1, QTableWidgetItem('书号')) 773 | self.table.setItem(0, 2, QTableWidgetItem('书名')) 774 | self.table.setItem(0, 3, QTableWidgetItem('借书日期')) 775 | self.table.setItem(0, 4, QTableWidgetItem('还书日期')) 776 | self.table.setItem(0, 5, QTableWidgetItem('罚金')) 777 | self.table.setItem(0, 6, QTableWidgetItem('操作')) 778 | 779 | for i in range(7): 780 | self.table.item(0, i).setTextAlignment(Qt.AlignCenter) 781 | self.table.item(0, i).setFont(QFont('微软雅黑', 15)) 782 | for i in self.borrow_list: 783 | self.insertRow(i) 784 | 785 | self.body.addWidget(self.table) 786 | 787 | # 插入行 788 | def insertRow(self, val: list): 789 | itemSID = QTableWidgetItem(val[0]) 790 | itemSID.setTextAlignment(Qt.AlignCenter) 791 | itemBID = QTableWidgetItem(val[1]) 792 | itemBID.setTextAlignment(Qt.AlignCenter) 793 | itemNAME = QTableWidgetItem(val[2]) 794 | itemNAME.setTextAlignment(Qt.AlignCenter) 795 | itemBEGIN = QTableWidgetItem(val[3]) 796 | itemBEGIN.setTextAlignment(Qt.AlignCenter) 797 | itemBACK = QTableWidgetItem(val[4]) 798 | itemBACK.setTextAlignment(Qt.AlignCenter) 799 | itemPUNISHED = QLabel() 800 | itemPUNISHED.setText('0') 801 | itemPUNISHED.setAlignment(Qt.AlignCenter) 802 | isPunished = func.days_between(val[4], time.strftime("%Y-%m-%d-%H:%M")) 803 | if isPunished <= 0: 804 | itemPUNISHED.setStyleSheet(''' 805 | *{ 806 | color: green; 807 | font-size:20px; 808 | font-family: 微软雅黑; 809 | } 810 | ''') 811 | else: 812 | itemPUNISHED.setText(str(isPunished)) 813 | itemPUNISHED.setStyleSheet(''' 814 | *{ 815 | color: red; 816 | font-size:20px; 817 | font-family: 微软雅黑; 818 | } 819 | ''') 820 | itemOPERATE = QToolButton(self.table) 821 | itemOPERATE.setFixedSize(70, 25) 822 | itemOPERATE.setText('还书') 823 | itemOPERATE.clicked.connect(lambda: self.retrurnBook(val[0], val[1], isPunished)) 824 | itemOPERATE.setStyleSheet(''' 825 | *{ 826 | color: white; 827 | font-family: 微软雅黑; 828 | background: rgba(38, 175, 217, 1); 829 | border: 0; 830 | font-size:18px; 831 | } 832 | ''') 833 | 834 | itemLayout = QHBoxLayout() 835 | itemLayout.setContentsMargins(0, 0, 0, 0) 836 | itemLayout.addWidget(itemOPERATE) 837 | itemWidget = QWidget() 838 | itemWidget.setLayout(itemLayout) 839 | 840 | self.table.insertRow(1) 841 | self.table.setItem(1, 0, itemSID) 842 | self.table.setItem(1, 1, itemBID) 843 | self.table.setItem(1, 2, itemNAME) 844 | self.table.setItem(1, 3, itemBEGIN) 845 | self.table.setItem(1, 4, itemBACK) 846 | self.table.setCellWidget(1, 5, itemPUNISHED) 847 | self.table.setCellWidget(1, 6, itemWidget) 848 | 849 | def retrurnBook(self, sno: str, bno: str, isPunished: int): 850 | if isPunished > 0: 851 | func.pay(bno, sno, isPunished) 852 | ans = func.return_book(bno, sno) 853 | # 刷新表格 854 | if ans: 855 | self.searchFunction('bno') 856 | 857 | def initUI(self): 858 | self.setFixedSize(1270, 600) 859 | self.setStyleSheet(''' 860 | *{ 861 | background-color: white; 862 | border:0px; 863 | } 864 | ''') 865 | self.titleBar.setStyleSheet(''' 866 | QWidget { 867 | border:0; 868 | background-color: rgba(216, 216, 216, 1); 869 | color: rgba(113, 118, 121, 1); 870 | } 871 | QLabel{ 872 | font-size: 25px; 873 | font-family: 微软雅黑; 874 | } 875 | ''') 876 | self.searchWidget.setStyleSheet(''' 877 | QToolButton{ 878 | background-color:rgba(52, 118, 176, 1); 879 | color: white; 880 | font-size: 25px; 881 | font-family: 微软雅黑; 882 | } 883 | QLineEdit{ 884 | border: 1px solid rgba(201, 201, 201, 1); 885 | color: rgba(120, 120, 120, 1) 886 | } 887 | QLabel{ 888 | font-size:25px; 889 | color: black; 890 | font-family: 微软雅黑; 891 | } 892 | ''') 893 | 894 | 895 | class HistoryManage(QWidget): 896 | def __init__(self): 897 | super().__init__() 898 | self.body = QVBoxLayout() 899 | self.table = None 900 | self.setTitleBar() 901 | self.setSearchBar() 902 | self.searchFunction() 903 | self.body.addStretch() 904 | 905 | self.setLayout(self.body) 906 | self.initUI() 907 | 908 | # 标题栏 909 | def setTitleBar(self): 910 | self.title = QLabel() 911 | self.title.setText('借阅记录管理') 912 | self.title.setFixedHeight(25) 913 | titleLayout = QHBoxLayout() 914 | titleLayout.addSpacing(50) 915 | titleLayout.addWidget(self.title) 916 | self.titleBar = QWidget() 917 | self.titleBar.setFixedSize(1270, 50) 918 | self.titleBar.setLayout(titleLayout) 919 | self.body.addWidget(self.titleBar) 920 | 921 | # 设置搜索框 922 | def setSearchBar(self): 923 | self.searchTitle = QLabel() 924 | self.searchTitle.setText('搜索学生') 925 | self.searchInput = QLineEdit() 926 | self.searchInput.setText('ID/姓名') 927 | self.searchInput.setClearButtonEnabled(True) 928 | self.searchInput.setFixedSize(400, 40) 929 | self.searchStudentButton = QToolButton() 930 | self.searchStudentButton.setFixedSize(120, 40) 931 | self.searchStudentButton.setText('搜索学号') 932 | self.searchStudentButton.clicked.connect(lambda: self.searchFunction('sno')) 933 | 934 | self.searchBookButton = QToolButton() 935 | self.searchBookButton.setFixedSize(120, 40) 936 | self.searchBookButton.setText('搜索书号') 937 | self.searchBookButton.clicked.connect(lambda: self.searchFunction()) 938 | 939 | self.outButton = QToolButton() 940 | self.outButton.setText('导出') 941 | self.outButton.clicked.connect(self.outFunction) 942 | self.outButton.setFixedSize(100, 40) 943 | 944 | searchLayout = QHBoxLayout() 945 | searchLayout.addStretch() 946 | searchLayout.addWidget(self.searchTitle) 947 | searchLayout.addWidget(self.searchInput) 948 | searchLayout.addWidget(self.searchStudentButton) 949 | searchLayout.addWidget(self.searchBookButton) 950 | searchLayout.addWidget(self.outButton) 951 | searchLayout.addStretch() 952 | 953 | self.searchWidget = QWidget() 954 | self.searchWidget.setFixedWidth(900) 955 | self.searchWidget.setLayout(searchLayout) 956 | self.body.addWidget(self.searchWidget) 957 | 958 | # 搜索方法 959 | def searchFunction(self, e: str = 'bno'): 960 | # 搜索书号 961 | if e == 'bno': 962 | self.log_list = func.get_log(self.searchInput.text(), True) 963 | else: 964 | # 搜索学号 965 | self.log_list = func.get_log(self.searchInput.text()) 966 | if self.log_list == []: 967 | print('未找到') 968 | if self.table is not None: 969 | self.table.deleteLater() 970 | self.setTable() 971 | 972 | # 创建表格 973 | def setTable(self, val: dict = None): 974 | self.table = QTableWidget(1, 6) 975 | self.table.setFixedHeight(450) 976 | self.table.setContentsMargins(10, 10, 10, 10) 977 | self.table.verticalHeader().setVisible(False) 978 | self.table.horizontalHeader().setVisible(False) 979 | self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) 980 | self.table.setFocusPolicy(Qt.NoFocus) 981 | self.table.setColumnWidth(0, 100) 982 | self.table.setColumnWidth(1, 150) 983 | self.table.setColumnWidth(2, 170) 984 | self.table.setColumnWidth(3, 175) 985 | self.table.setColumnWidth(4, 175) 986 | self.table.setColumnWidth(5, 100) 987 | self.table.setItem(0, 0, QTableWidgetItem('学号')) 988 | self.table.setItem(0, 1, QTableWidgetItem('书号')) 989 | self.table.setItem(0, 2, QTableWidgetItem('书名')) 990 | self.table.setItem(0, 3, QTableWidgetItem('借书日期')) 991 | self.table.setItem(0, 4, QTableWidgetItem('还书日期')) 992 | self.table.setItem(0, 5, QTableWidgetItem('罚金')) 993 | 994 | for i in range(6): 995 | self.table.item(0, i).setTextAlignment(Qt.AlignCenter) 996 | self.table.item(0, i).setFont(QFont('微软雅黑', 15)) 997 | 998 | for i in self.log_list: 999 | self.insertRow(i) 1000 | self.body.addWidget(self.table) 1001 | 1002 | # 插入行 1003 | def insertRow(self, val: list): 1004 | itemSNAME = QTableWidgetItem(val[0]) 1005 | itemSNAME.setTextAlignment(Qt.AlignCenter) 1006 | itemBID = QTableWidgetItem(val[1]) 1007 | itemBID.setTextAlignment(Qt.AlignCenter) 1008 | itemNAME = QTableWidgetItem('《' + val[2] + '》') 1009 | itemNAME.setTextAlignment(Qt.AlignCenter) 1010 | itemBEGIN = QTableWidgetItem(val[3]) 1011 | itemBEGIN.setTextAlignment(Qt.AlignCenter) 1012 | itemBACK = QTableWidgetItem(val[4]) 1013 | itemBACK.setTextAlignment(Qt.AlignCenter) 1014 | itemPUNISHED = QLabel() 1015 | itemPUNISHED.setText(str(val[5])) 1016 | itemPUNISHED.setAlignment(Qt.AlignCenter) 1017 | if val[5] == 0: 1018 | itemPUNISHED.setStyleSheet(''' 1019 | *{ 1020 | color: green; 1021 | font-size: 20px; 1022 | } 1023 | ''') 1024 | else: 1025 | itemPUNISHED.setStyleSheet(''' 1026 | *{ 1027 | color: red; 1028 | font-size: 20px; 1029 | } 1030 | ''') 1031 | self.table.insertRow(1) 1032 | self.table.setItem(1, 0, itemSNAME) 1033 | self.table.setItem(1, 1, itemBID) 1034 | self.table.setItem(1, 2, itemNAME) 1035 | self.table.setItem(1, 3, itemBEGIN) 1036 | self.table.setItem(1, 4, itemBACK) 1037 | self.table.setCellWidget(1, 5, itemPUNISHED) 1038 | 1039 | def outFunction(self): 1040 | import csv 1041 | dirName = QFileDialog.getExistingDirectory(self, '选择文件夹') 1042 | title = ['sno', 'bno', 'bname', 'borrow_date', 'return_date', 'punish_money'] 1043 | with open(os.path.join(dirName, 'log.csv'), 'w', newline='') as f: 1044 | writer = csv.writer(f) 1045 | writer.writerow(title) 1046 | for row in self.log_list: 1047 | writer.writerow(row) 1048 | 1049 | def initUI(self): 1050 | self.setFixedSize(1280, 600) 1051 | self.setStyleSheet(''' 1052 | *{ 1053 | background-color: white; 1054 | border:0px; 1055 | } 1056 | ''') 1057 | self.titleBar.setStyleSheet(''' 1058 | QWidget { 1059 | border:0; 1060 | background-color: rgba(216, 216, 216, 1); 1061 | color: rgba(113, 118, 121, 1); 1062 | } 1063 | QLabel{ 1064 | font-size: 25px; 1065 | font-family: 微软雅黑; 1066 | } 1067 | ''') 1068 | self.table.setStyleSheet(''' 1069 | font-size:18px; 1070 | color: black; 1071 | background-color: white; 1072 | font-family: 微软雅黑; 1073 | ''') 1074 | self.outButton.setStyleSheet(''' 1075 | QToolButton{ 1076 | background-color:rgba(52, 118, 176, 1); 1077 | color: white; 1078 | font-size: 25px; 1079 | font-family: 微软雅黑; 1080 | } 1081 | ''') 1082 | self.searchWidget.setStyleSheet(''' 1083 | QToolButton{ 1084 | background-color:rgba(52, 118, 176, 1); 1085 | color: white; 1086 | font-size: 25px; 1087 | font-family: 微软雅黑; 1088 | } 1089 | QLineEdit{ 1090 | border: 1px solid rgba(201, 201, 201, 1); 1091 | color: rgba(120, 120, 120, 1) 1092 | } 1093 | QLabel{ 1094 | font-size:25px; 1095 | color: black; 1096 | font-family: 微软雅黑; 1097 | } 1098 | ''') 1099 | 1100 | 1101 | if __name__ == '__main__': 1102 | app = QApplication(sys.argv) 1103 | user_message = { 1104 | 'class': 'admin', 1105 | 'aid': 'admin' 1106 | } 1107 | ex = AdministratorPage(user_message) 1108 | ex.show() 1109 | sys.exit(app.exec_()) 1110 | -------------------------------------------------------------------------------- /book_information.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PyQt5.QtWidgets import ( 3 | QApplication, QVBoxLayout, QLabel, QLineEdit, QToolButton, QGroupBox, QMessageBox) 4 | from PyQt5.QtCore import pyqtSignal 5 | from PyQt5.QtGui import QIcon 6 | 7 | KEY_LIST = ['bno', 'bname', 'author', 8 | 'date', 'press', 'position', 'sum', 'class'] 9 | 10 | 11 | class BookInfo(QGroupBox): 12 | ''' 13 | 编辑书本信息的界面 14 | 返回book_msg{ 15 | 'bno': str, 16 | 'bname': str, 17 | 'author': str, 18 | 'date': str, 19 | 'press': str, 20 | 'position': str, 21 | 'sum': int, 22 | 'class': str 23 | } 24 | ''' 25 | after_close = pyqtSignal(dict) 26 | 27 | def __init__(self, book_msg: dict = None): 28 | super().__init__() 29 | if book_msg is not None: 30 | self.book_msg = book_msg 31 | else: 32 | self.book_msg = { 33 | 'bno': '请输入书号', 34 | 'bname': '请输入书名', 35 | 'author': '请输入作者', 36 | 'date': '请输入出版日期', 37 | 'press': '请输入出版社', 38 | 'position': '请输入存放位置', 39 | 'sum': '请输入数量', 40 | 'class': '请输入分类, 以空格区分' 41 | } 42 | 43 | self.title = QLabel() 44 | self.title.setText('书本信息') 45 | 46 | self.subTitle = QLabel() 47 | self.subTitle.setText('编辑书籍信息') 48 | 49 | # 书号输入框 50 | self.bnoInput = QLineEdit() 51 | self.bnoInput.setFixedSize(400, 40) 52 | self.bnoInput.setText(self.book_msg['bno']) 53 | self.bnoInput.initText = '请输入书号' 54 | self.bnoInput.mousepressEvent = lambda x: self.inputClick(self.bnoInput) 55 | # bno不允许修改 56 | if self.bnoInput.text() != self.bnoInput.initText: 57 | self.bnoInput.setEnabled(False) 58 | 59 | # 书名输入框 60 | self.bnameInput = QLineEdit() 61 | self.bnameInput.setFixedSize(400, 40) 62 | self.bnameInput.setText(self.book_msg['bname']) 63 | self.bnameInput.initText = '请输入书名' 64 | self.bnameInput.mousepressEvent = lambda x: self.inputClick(self.bnameInput) 65 | 66 | # 总书数 67 | self.NumInput = QLineEdit() 68 | self.NumInput.setFixedSize(400, 40) 69 | self.NumInput.setText(str(self.book_msg['sum'])) 70 | self.NumInput.initText = '请输入数量' 71 | self.NumInput.mousepressEvent = lambda x: self.inputClick(self.NumInput) 72 | 73 | # 作者 74 | self.authorInput = QLineEdit() 75 | self.authorInput.setFixedSize(400, 40) 76 | self.authorInput.setText(self.book_msg['author']) 77 | self.authorInput.initText = '请输入作者' 78 | self.authorInput.mousepressEvent = lambda x: self.inputClick(self.authorInput) 79 | 80 | # 出版社 81 | self.pressInput = QLineEdit() 82 | self.pressInput.setFixedSize(400, 40) 83 | self.pressInput.setText(self.book_msg['press']) 84 | self.pressInput.initText = '请输入出版社' 85 | self.pressInput.mousepressEvent = lambda x: self.inputClick(self.pressInput) 86 | 87 | # 出版日期 88 | self.DATEInput = QLineEdit() 89 | self.DATEInput.setFixedSize(400, 40) 90 | self.DATEInput.setText(self.book_msg['date']) 91 | self.DATEInput.initText = '请输入出版日期' 92 | self.DATEInput.mousepressEvent = lambda x: self.inputClick(self.DATEInput) 93 | 94 | # 位置 95 | self.positionInput = QLineEdit() 96 | self.positionInput.setFixedSize(400, 40) 97 | self.positionInput.setText(self.book_msg['position']) 98 | self.positionInput.initText = '请输入存放位置' 99 | self.positionInput.mousepressEvent = lambda x: self.inputClick(self.positionInput) 100 | 101 | # 分类 102 | self.classInput = QLineEdit() 103 | self.classInput.setFixedSize(400, 40) 104 | self.classInput.setText(self.book_msg['class']) 105 | self.classInput.initText = '请输入分类, 以空格区分' 106 | self.classInput.mousepressEvent = lambda x: self.inputClick(self.classInput) 107 | 108 | # 提交 109 | self.submit = QToolButton() 110 | self.submit.setText('提交') 111 | self.submit.setFixedSize(400, 40) 112 | self.submit.clicked.connect(self.submitFunction) 113 | 114 | # 退出 115 | self.back = QToolButton() 116 | self.back.setText('退出') 117 | self.back.setFixedSize(400, 40) 118 | self.back.clicked.connect(self.close) 119 | 120 | self.btnList = [ 121 | self.bnoInput, 122 | self.bnameInput, 123 | self.authorInput, 124 | self.DATEInput, 125 | self.pressInput, 126 | self.positionInput, 127 | self.NumInput, 128 | self.classInput 129 | ] 130 | 131 | self.bodyLayout = QVBoxLayout() 132 | self.bodyLayout.addWidget(self.title) 133 | self.bodyLayout.addWidget(self.subTitle) 134 | for i in self.btnList: 135 | self.bodyLayout.addWidget(i) 136 | self.bodyLayout.addWidget(self.submit) 137 | self.bodyLayout.addWidget(self.back) 138 | 139 | self.setLayout(self.bodyLayout) 140 | self.initUI() 141 | 142 | def inputClick(self, e): 143 | for item in self.btnList: 144 | if item.text() == '': 145 | item.setText(item.initText) 146 | if e.text() == e.initText: 147 | e.setText('') 148 | 149 | def submitFunction(self): 150 | for btn, key in zip(self.btnList, KEY_LIST): 151 | if btn.text() == btn.initText: 152 | self.book_msg[key] = '' 153 | else: 154 | self.book_msg[key] = btn.text() 155 | 156 | if not self.book_msg['bno'].isalnum(): 157 | self.errorBox('书编号存在非法字符') 158 | return 159 | if len(self.book_msg['bno']) > 15: 160 | self.errorBox('书编号长度大于15') 161 | return 162 | if len(self.book_msg['bname']) == 0: 163 | self.errorBox('书名不能为空') 164 | return 165 | if len(self.book_msg['author']) == 0: 166 | self.errorBox('作者不能为空') 167 | return 168 | if len(self.book_msg['date']) > 12: 169 | self.errorBox('日期编号过长') 170 | return 171 | if len(self.book_msg['press']) > 12: 172 | self.errorBox('出版社名称长度不能超过20') 173 | return 174 | po = self.book_msg['position'] 175 | if not (len(po) == 3 and po[0].isalpha and po[1:].isdigit()): 176 | self.errorBox('位置编号不合法') 177 | return 178 | if self.book_msg['sum'].isdigit(): 179 | self.book_msg['sum'] = int(self.book_msg['sum']) 180 | else: 181 | self.errorBox('图书数量有非法字符') 182 | return 183 | self.close() 184 | self.after_close.emit(self.book_msg) 185 | 186 | def initUI(self): 187 | self.setFixedSize(422, 550) 188 | self.setWindowTitle('编辑书本') 189 | self.setWindowIcon(QIcon('icon/book.png')) 190 | self.setMyStyle() 191 | 192 | def errorBox(self, mes: str): 193 | msgBox = QMessageBox( 194 | QMessageBox.Warning, 195 | "警告!", 196 | mes, 197 | QMessageBox.NoButton, 198 | self 199 | ) 200 | msgBox.addButton("确认", QMessageBox.AcceptRole) 201 | msgBox.exec_() 202 | 203 | def setMyStyle(self): 204 | self.setStyleSheet(''' 205 | QWidget{ 206 | background-color: white; 207 | } 208 | QLineEdit{ 209 | border:0px; 210 | border-bottom: 1px solid rgba(229, 229, 229, 1); 211 | color: grey; 212 | } 213 | QToolButton{ 214 | border: 0px; 215 | background-color:rgba(52, 118, 176, 1); 216 | color: white; 217 | font-size: 25px; 218 | font-family: 微软雅黑; 219 | } 220 | QGroupBox{ 221 | border: 1px solid rgba(229, 229, 229, 1); 222 | border-radius: 5px; 223 | } 224 | ''') 225 | self.title.setStyleSheet(''' 226 | *{ 227 | color: rgba(113, 118, 121, 1); 228 | font-size: 30px; 229 | font-family: 微软雅黑; 230 | } 231 | ''') 232 | self.subTitle.setStyleSheet(''' 233 | *{ 234 | color: rgba(184, 184, 184, 1); 235 | } 236 | ''') 237 | 238 | 239 | if __name__ == '__main__': 240 | book_msg = { 241 | 'bno': '4', 242 | 'bname': 'Java', 243 | 'author': 'kak', 244 | 'date': '2009-05', 245 | 'press': '电子出版社', 246 | 'position': 'C05', 247 | 'sum': 5, 248 | 'class': 'aasd asd asd ad ' 249 | } 250 | app = QApplication(sys.argv) 251 | ex = BookInfo(book_msg) 252 | ex.show() 253 | sys.exit(app.exec_()) 254 | -------------------------------------------------------------------------------- /createDB.py: -------------------------------------------------------------------------------- 1 | import pymysql 2 | 3 | Config = { 4 | "host": '127.0.0.1', 5 | "user": 'root', 6 | "pwd": '123456', 7 | 'db': 'library' 8 | } 9 | 10 | 11 | def create_database(): 12 | try: 13 | conn = pymysql.connect(host=Config['host'], user=Config['user'], password=Config['pwd']) 14 | print("成功连接到数据库") 15 | cursor = conn.cursor() 16 | conn.autocommit(True) 17 | cursor.execute("CREATE DATABASE `{}`".format(Config['db'])) 18 | conn.autocommit(False) 19 | cursor.execute("use `{}`".format(Config['db'])) 20 | print("成功创建数据库:{}".format(Config['db'])) 21 | 22 | print("开始创建数据表") 23 | # 创建学生信息表 24 | cursor.execute("""CREATE TABLE `student`( 25 | `sno` varchar(15), 26 | `password` varchar(70), 27 | `sname` varchar(10), 28 | `dept` varchar(20), 29 | `majority` varchar(20), 30 | `max_book` int, 31 | primary key(`sno`)) 32 | """) 33 | # 创建管理员表 34 | cursor.execute("""CREATE TABLE `administrator`( 35 | `aid` varchar(15) , 36 | `password` varchar(70), 37 | primary key(`aid`) 38 | ); 39 | """) 40 | # 创建书籍信息表 41 | cursor.execute("""CREATE TABLE `book`( 42 | `bno` char(15) PRIMARY KEY, 43 | `bname` text, 44 | `author` text, 45 | `date` char(17), 46 | `press` char(20), 47 | `position` char(10), 48 | `sum` int, 49 | `rest` int 50 | ); 51 | """) 52 | # 创建借书表 53 | cursor.execute("""CREATE TABLE `borrowing_book`( 54 | `bno` char(15), 55 | `sno` char(15), 56 | `borrow_date` char(17), 57 | `deadline` char(17), 58 | `punish_money` int, 59 | PRIMARY KEY(bno, sno) 60 | ); 61 | """) 62 | # 创建日志表 63 | cursor.execute("""CREATE TABLE `log`( 64 | `bno` char(15), 65 | `sno` char(15), 66 | `borrow_date` char(17), 67 | `return_date` char(17), 68 | `punish_money` int 69 | ); 70 | """) 71 | # 创建书籍分类表 72 | cursor.execute(""" CREATE TABLE `classification`( 73 | `bno` char(15), 74 | `class` varchar(15), 75 | PRIMARY KEY(bno, class) 76 | ); 77 | """) 78 | 79 | # 导入默认管理员账号密码:admin/123456,导入数据库的是加密之后的信息 80 | cursor.execute(""" 81 | INSERT 82 | INTO administrator 83 | VALUES('admin', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92') 84 | """) 85 | conn.commit() 86 | print("成功创建所有数据表") 87 | except Exception as e: 88 | print('数据库建立失败,报错信息如下:') 89 | print(e) 90 | finally: 91 | if conn: 92 | conn.close() 93 | 94 | 95 | if __name__ == '__main__': 96 | create_database() 97 | -------------------------------------------------------------------------------- /func.py: -------------------------------------------------------------------------------- 1 | import pymysql 2 | import time 3 | 4 | CONFIG = { 5 | "host": '127.0.0.1', 6 | "user": 'root', 7 | "pwd": '123456', 8 | 'db': 'library' 9 | } 10 | 11 | 12 | def signin(user_message: dict) -> dict: 13 | ans = None 14 | try: 15 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 16 | cursor = conn.cursor() 17 | cursor.execute(''' 18 | SELECT aid 19 | FROM administrator 20 | WHERE aid=%s AND password=%s 21 | ''', ( 22 | user_message['ID'], 23 | user_message['PASSWORD'] 24 | )) 25 | temp = cursor.fetchall() 26 | if len(temp) == 0: 27 | cursor.execute(''' 28 | SELECT sno, sname, dept, majority, max_book 29 | FROM student 30 | WHERE sno=%s AND password=%s 31 | ''', ( 32 | user_message['ID'], 33 | user_message['PASSWORD'] 34 | )) 35 | temp = cursor.fetchall() 36 | ans = temp 37 | conn.commit() 38 | except Exception as e: 39 | print('Signin error!') 40 | print(e) 41 | finally: 42 | if conn: 43 | conn.close() 44 | return convert(ans) 45 | 46 | 47 | # 去掉字符串末尾的0 48 | def remove_blank(val): 49 | if type(val) is not str: 50 | return val 51 | while len(val) != 0 and val[-1] == ' ': 52 | val = val[:-1] 53 | return val 54 | 55 | 56 | # 将元组列表转换为字典 57 | def convert(val: list): 58 | if len(val) == 0: 59 | return None 60 | val = val[0] 61 | if len(val) == 5: 62 | ans = { 63 | 'class': 'stu', 64 | 'sno': remove_blank(val[0]), 65 | 'sname': remove_blank(val[1]), 66 | 'dept': remove_blank(val[2]), 67 | 'majority': remove_blank(val[3]), 68 | 'max_book': val[4] 69 | } 70 | else: 71 | ans = { 72 | 'class': 'admin', 73 | 'aid': remove_blank(val[0]) 74 | } 75 | return ans 76 | 77 | 78 | def encrypt(val): 79 | import hashlib 80 | h = hashlib.sha256() 81 | password = val 82 | h.update(bytes(password, encoding='UTF-8')) 83 | result = h.hexdigest() 84 | return result 85 | 86 | 87 | # 检查注册信息 88 | def check_user_info(info: dict) -> dict: 89 | ''' 90 | info = { 91 | 'SID': self.accountInput.text(), 92 | 'PASSWORD': self.passwordInput.text(), 93 | 'REPASSWORD': self.repPasswordInput.text(), 94 | 'SNAME': self.nameInput.text(), 95 | 'DEPARTMENT': self.deptInput.text(), 96 | 'MAJOR': self.majorInput.text(), 97 | 'MAX': self.maxNumInput.text(), 98 | 'PUNISHED': 0 99 | } 100 | 返回 ans = { 101 | 'res':'fail|seccuss', 102 | 'reason':'' 103 | } 104 | ''' 105 | ans = { 106 | 'res':'fail', 107 | 'reason':'' 108 | } 109 | if len(info['sno']) > 15: 110 | ans['reason'] = 'ID长度超过15' 111 | return ans 112 | if not info['sno'].isalnum(): 113 | ans['reason'] = 'ID存在非法字符' 114 | return ans 115 | if info['password'] != info['repassword']: 116 | ans['reason'] = '两次输入密码不一致' 117 | return ans 118 | if not info['max_book'].isdigit(): 119 | ans['reason'] = '最大数量输入含有非法字符' 120 | return ans 121 | if int(info['max_book']) > 10: 122 | ans['reason'] = '最多只能借阅10本书' 123 | return ans 124 | if len(info['dept']) > 20: 125 | ans['reason'] = '学院名称过长' 126 | return ans 127 | if len(info['majority']) > 20: 128 | ans['reason'] = '专业名称过长' 129 | return ans 130 | ans['res'] = 'seccuss' 131 | return ans 132 | 133 | 134 | # 注册 135 | def signup(user_message: dict) -> bool: 136 | ''' 137 | 传入以下格式的字典 138 | user_message{ 139 | 'SID': str, 140 | 'PASSWORD': str, 141 | 'SNAME': str, 142 | 'DEPARTMENT': str, 143 | 'MAJOR': str, 144 | 'MAX': int 145 | } 146 | ''' 147 | res = True 148 | try: 149 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 150 | cursor = conn.cursor() 151 | cursor.execute(''' 152 | SELECT * 153 | FROM student 154 | WHERE sno=%s 155 | ''', (user_message['sno'])) 156 | if len(cursor.fetchall()) != 0: 157 | raise Exception('用户已存在!') 158 | cursor.execute(''' 159 | INSERT 160 | INTO student 161 | VALUES(%s, %s, %s, %s, %s, %s) 162 | ''', ( 163 | user_message['sno'], 164 | user_message['password'], 165 | user_message['sname'], 166 | user_message['dept'], 167 | user_message['majority'], 168 | user_message['max_book'] 169 | )) 170 | conn.commit() 171 | except Exception as e: 172 | print('Signup error!') 173 | print(e) 174 | res = False 175 | finally: 176 | if conn: 177 | conn.close() 178 | return res 179 | 180 | 181 | # 更新学生信息 182 | def update_student(user_message: dict) -> bool: 183 | ''' 184 | 传入字典格式如下 185 | user_message{ 186 | 'sno': str, 187 | 'password': str, 188 | 'sname': str, 189 | 'dept': str, 190 | 'majority': str, 191 | 'max_book': int 192 | } 193 | 返回bool 194 | ''' 195 | try: 196 | res = True 197 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 198 | cursor = conn.cursor() 199 | cursor.execute(''' 200 | UPDATE student 201 | SET sname=%s, dept=%s, majority=%s, max_book=%s 202 | WHERE sno=%s 203 | ''', ( 204 | user_message['sname'], 205 | user_message['dept'], 206 | user_message['majority'], 207 | user_message['max_book'], 208 | user_message['sno'] 209 | )) 210 | if 'password' in user_message: 211 | cursor.execute(''' 212 | UPDATE student 213 | SET password=%s 214 | WHERE sno=%s 215 | ''', ( 216 | user_message['password'], 217 | user_message['sno'] 218 | )) 219 | conn.commit() 220 | except Exception as e: 221 | print('Update error!') 222 | print(e) 223 | res = False 224 | finally: 225 | if conn: 226 | conn.close() 227 | return res 228 | 229 | 230 | # 获取学生信息 231 | def get_student_info(sno: str) -> dict: 232 | ''' 233 | 传入sno 234 | 返回stu_info{ 235 | 'class': stu, 236 | 'sno': str, 237 | 'sname': str, 238 | 'dept': str, 239 | 'majority': str, 240 | 'max_book': int 241 | } 242 | ''' 243 | try: 244 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 245 | cursor = conn.cursor() 246 | cursor.execute(''' 247 | SELECT sno, sname, dept, majority, max_book 248 | FROM student 249 | WHERE sno=%s 250 | ''', (sno)) 251 | ans = cursor.fetchall() 252 | except Exception as e: 253 | print(e) 254 | print('get student info error') 255 | finally: 256 | if conn: 257 | conn.close() 258 | return convert(ans) 259 | 260 | 261 | # 查找学生 262 | def search_student(info: str) -> list: 263 | ''' 264 | 传入sno或学生姓名进行查找 265 | 返回[[sno, sname, dept, majority, max_book],...] 266 | ''' 267 | try: 268 | res = [] 269 | val = info.split() 270 | val = [(i, '%'+i+'%') for i in val] 271 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 272 | cursor = conn.cursor() 273 | # 显示所有书信息 274 | if info == 'ID/姓名' or info == '': 275 | cursor.execute(''' 276 | SELECT sno, sname, dept, majority, max_book 277 | FROM student 278 | ''') 279 | res += cursor.fetchall() 280 | else: 281 | # 按条件查找 282 | for i in val: 283 | cursor.execute(''' 284 | SELECT sno, sname, dept, majority, max_book 285 | FROM student 286 | WHERE sno=%s OR sname LIKE %s 287 | ''', i) 288 | res += cursor.fetchall() 289 | res = list(set(res)) 290 | temp = [] 291 | for i in res: 292 | temp_ = [] 293 | for j in i: 294 | temp_.append(remove_blank(j)) 295 | temp.append(temp_) 296 | res = temp 297 | except Exception as e: 298 | print('Search student error!') 299 | print(e) 300 | res = [] 301 | finally: 302 | if conn: 303 | conn.close() 304 | return res 305 | 306 | 307 | # 删除学生信息 308 | def delete_student(sno: str) -> bool: 309 | ''' 310 | 传入sno 311 | 删除student表内记录, 312 | 找出book表内所借的书强制还书 313 | 删除log表内的记录 314 | ''' 315 | try: 316 | res = True 317 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 318 | cursor = conn.cursor() 319 | # 先强制把书还掉 320 | cursor.execute(''' 321 | SELECT bno 322 | FROM borrowing_book 323 | WHERE sno=%s 324 | ''', (sno)) 325 | BID_list = cursor.fetchall() 326 | for bno in BID_list: 327 | return_book(bno, sno) 328 | # 再删除学生信息 329 | cursor.execute(''' 330 | DELETE 331 | FROM student 332 | WHERE sno=%s''',(sno)) 333 | 334 | cursor.execute(''' 335 | DELETE 336 | FROM log 337 | WHERE sno=%s 338 | ''', (sno)) 339 | conn.commit() 340 | except Exception as e: 341 | print('delete book error!') 342 | print(e) 343 | res = False 344 | finally: 345 | if conn: 346 | conn.close() 347 | return res 348 | 349 | 350 | # 获取学生的借书信息 351 | def get_borrowing_books(ID: str, bno: bool = False) -> list: 352 | ''' 353 | 当BID为False以sno的方式查找否则以BID查找 354 | 返回此学生在借的书籍列表信息 355 | [[sno, bno, bname, borrow_date, deadline, punish_money, rest],[...],....] 356 | ''' 357 | try: 358 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 359 | cursor = conn.cursor() 360 | if ID == '' or ID == 'ID/姓名': 361 | cursor.execute(''' 362 | SELECT sno, book.bno, bname, borrow_date, deadline, punish_money, rest 363 | FROM borrowing_book, book 364 | WHERE book.bno=borrowing_book.bno 365 | ''') 366 | elif bno: 367 | cursor.execute(''' 368 | SELECT sno, book.bno, bname, borrow_date, deadline, punish_money, rest 369 | FROM borrowing_book, book 370 | WHERE book.bno=%s AND book.bno=borrowing_book.bno 371 | ''', (ID,)) 372 | else: 373 | cursor.execute(''' 374 | SELECT sno, book.bno, bname, borrow_date, deadline, punish_money, rest 375 | FROM borrowing_book, book 376 | WHERE sno=%s AND book.bno=borrowing_book.bno 377 | ''', (ID,)) 378 | res = cursor.fetchall() 379 | temp = [] 380 | for i in res: 381 | temp_ = [] 382 | for j in i: 383 | temp_.append(remove_blank(j)) 384 | temp.append(temp_) 385 | res = temp 386 | except Exception as e: 387 | print('get borrowing books error!') 388 | print(e) 389 | res = [] 390 | finally: 391 | if conn: 392 | conn.close() 393 | return res 394 | 395 | 396 | # 还书 397 | def return_book(bno: str, sno: str) -> bool: 398 | ''' 399 | 传入BID, sno,删除borrowing_book表内的记录在log表内新建记录 400 | 返回bool型 401 | ''' 402 | try: 403 | res = True 404 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 405 | cursor = conn.cursor() 406 | # 先把借书日期,书本剩余数量,罚金等信息找出 407 | cursor.execute(''' 408 | SELECT borrow_date, rest, punish_money 409 | FROM book, borrowing_book 410 | WHERE sno=%s AND borrowing_book.bno=%s AND borrowing_book.bno=book.bno 411 | ''', (sno, bno)) 412 | book_mes = cursor.fetchall() 413 | rest = book_mes[0][1] 414 | borrow_date = book_mes[0][0] 415 | punish_money = book_mes[0][2] 416 | return_date = time.strftime("%Y-%m-%d-%H:%M") 417 | 418 | # book表内NUM加一,删除borrowing_book表内的记录,把记录插入log表 419 | cursor.execute(''' 420 | UPDATE book 421 | SET rest=%s 422 | WHERE bno=%s''',(str(rest+1), bno)) 423 | 424 | cursor.execute(''' 425 | DELETE 426 | FROM borrowing_book 427 | WHERE sno=%s AND bno=%s''',(sno, bno)) 428 | 429 | cursor.execute(''' 430 | INSERT 431 | INTO log 432 | VALUES(%s, %s, %s, %s, %s) 433 | ''', (bno, sno, borrow_date, return_date, str(punish_money))) 434 | conn.commit() 435 | except Exception as e: 436 | print('Return error!') 437 | print(e) 438 | res = False 439 | finally: 440 | if conn: 441 | conn.close() 442 | return res 443 | 444 | 445 | # 交罚金 446 | def pay(bno: str, sno: str, punish_money: int) -> bool: 447 | ''' 448 | 传入BID, sno, PUNISH把当前数的DEADLINE往后延长两个月 449 | 返回bool型 450 | ''' 451 | try: 452 | res = True 453 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 454 | cursor = conn.cursor() 455 | 456 | # book表内NUM加一,删除borrowing_book表内的记录,把记录插入log表 457 | cursor.execute(''' 458 | UPDATE borrowing_book 459 | SET deadline=%s, punish_money=%d 460 | WHERE bno=%s AND sno=%s 461 | ''', (postpone(time.strftime('%Y-%m-%d-%H:%M')), punish_money, bno, sno)) 462 | conn.commit() 463 | except Exception as e: 464 | print('Pay error!') 465 | print(e) 466 | res = False 467 | finally: 468 | if conn: 469 | conn.close() 470 | return res 471 | 472 | 473 | # 获取历史记录 474 | def get_log(ID: str, bno: bool = False) -> list: 475 | ''' 476 | 传入sno 477 | 返回[[sno, bno, bname, borrow_date, return_date, punish_money],...] 478 | ''' 479 | try: 480 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 481 | cursor = conn.cursor() 482 | if ID == '' or ID == 'ID/姓名': 483 | cursor.execute(''' 484 | SELECT sno, book.bno, bname, borrow_date, return_date, punish_money 485 | FROM log, book 486 | WHERE book.bno=log.bno 487 | ORDER BY return_date 488 | ''') 489 | elif bno: 490 | cursor.execute(''' 491 | SELECT sno, book.bno, bname, borrow_date, return_date, punish_money 492 | FROM log, book 493 | WHERE log.bno=%s AND book.bno=log.bno 494 | ORDER BY return_date 495 | ''', (ID,)) 496 | else: 497 | cursor.execute(''' 498 | SELECT sno, book.bno, bname, borrow_date, return_date, punish_money 499 | FROM log, book 500 | WHERE sno=%s AND book.bno=log.bno 501 | ORDER BY return_date 502 | ''', (ID,)) 503 | res = cursor.fetchall() 504 | except Exception as e: 505 | print('get log error!') 506 | print(e) 507 | res = [] 508 | finally: 509 | if conn: 510 | conn.close() 511 | temp = [] 512 | for i in res: 513 | temp_ = [] 514 | for j in i: 515 | temp_.append(remove_blank(j)) 516 | temp.append(temp_) 517 | return temp 518 | 519 | 520 | # 加入新书 521 | def new_book(book_info: dict) -> bool: 522 | ''' 523 | 传入以下格式的字典 524 | book_msg{ 525 | 'bno': str, 526 | 'bname': str, 527 | 'author': str, 528 | 'date': str, 529 | 'press': str, 530 | 'position': str, 531 | 'sum': int, 532 | 'class': str 533 | } 534 | 返回bool 535 | ''' 536 | res = True 537 | try: 538 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 539 | cursor = conn.cursor() 540 | cursor.execute(''' 541 | SELECT * 542 | FROM book 543 | WHERE bno=%s 544 | ''', (book_info['bno'])) 545 | if len(cursor.fetchall()) != 0: 546 | raise Exception('书ID已存在!') 547 | # 插入新书 548 | cursor.execute(''' 549 | INSERT 550 | INTO book 551 | VALUES(%s, %s, %s, %s, %s, %s, %s, %s) 552 | ''', ( 553 | book_info['bno'], 554 | book_info['bname'], 555 | book_info['author'], 556 | book_info['date'], 557 | book_info['press'], 558 | book_info['position'], 559 | str(book_info['sum']), 560 | str(book_info['sum']) 561 | )) 562 | 563 | # 处理书本分类 564 | classifications = book_info['class'] 565 | classifications = classifications.split() 566 | classifications = list(set(classifications)) 567 | classifications = [(book_info['bno'], i) for i in classifications] 568 | # 插入分类 569 | cursor.executemany(''' 570 | INSERT 571 | INTO classification 572 | VALUES(%s, %s) 573 | ''', classifications) 574 | 575 | conn.commit() 576 | except Exception as e: 577 | print('add book error!') 578 | print(e) 579 | res = False 580 | finally: 581 | if conn: 582 | conn.close() 583 | return res 584 | 585 | 586 | # 获取新书详细信息 587 | def get_book_info(bno: str) -> dict: 588 | ''' 589 | 传入BID 590 | 返回book_msg{ 591 | 'bno': str, 592 | 'bname': str, 593 | 'author': str, 594 | 'date': str, 595 | 'press': str, 596 | 'position': str, 597 | 'sum': int, 598 | 'rest': int, 599 | 'class': str 600 | } 601 | ''' 602 | try: 603 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 604 | cursor = conn.cursor() 605 | # 获取book表内的书本信息 606 | cursor.execute(''' 607 | SELECT * 608 | FROM book 609 | WHERE bno=%s 610 | ''', (bno)) 611 | res = cursor.fetchall() 612 | if len(res) == 0: 613 | raise Exception('查无此书') 614 | 615 | # 获取分类 616 | cursor.execute(''' 617 | SELECT class 618 | FROM classification 619 | WHERE bno=%s 620 | ''', (bno)) 621 | classification = '' 622 | for i in cursor.fetchall(): 623 | classification += (remove_blank(i[0]) + ' ') 624 | # 把列表转换为字典 625 | res = list(res[0]) 626 | res.append(classification) 627 | key_list = ['bno', 'bname', 'author', 'date', 'press', 'position', 'sum', 'rest', 'class'] 628 | ans = {} 629 | for i, key in zip(res, key_list): 630 | ans[key] = i 631 | if type(i) is str: 632 | ans[key] = remove_blank(i) 633 | res = ans 634 | except Exception as e: 635 | print('get book info error!') 636 | print(e) 637 | res = None 638 | finally: 639 | if conn: 640 | conn.close() 641 | return res 642 | 643 | 644 | # 更新书籍信息 645 | def update_book(book_info: dict) -> bool: 646 | ''' 647 | 传入以下格式的字典 648 | book_msg{ 649 | 'bno': str, 650 | 'bname': str, 651 | 'author': str, 652 | 'date': str, 653 | 'press': str, 654 | 'position': str, 655 | 'sum': int, 656 | 'rest': int, 657 | 'class': str 658 | } 659 | 返回bool 660 | ''' 661 | try: 662 | res = True 663 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 664 | cursor = conn.cursor() 665 | # 更新book表 666 | cursor.execute(''' 667 | UPDATE book 668 | SET bname=%s, author=%s, date=%s, press=%s, position=%s, sum=%s, rest=%s 669 | WHERE bno=%s 670 | ''', ( 671 | book_info['bname'], 672 | book_info['author'], 673 | book_info['date'], 674 | book_info['press'], 675 | book_info['position'], 676 | str(book_info['sum']), 677 | str(book_info['rest']), 678 | book_info['bno'] 679 | )) 680 | 681 | # 更新classification表 682 | cursor.execute(''' 683 | DELETE 684 | FROM classification 685 | WHERE bno=%s''', (book_info['bno'])) 686 | # 处理书本分类 687 | classifications = book_info['class'] 688 | classifications = classifications.split() 689 | classifications = list(set(classifications)) 690 | classifications = [(book_info['bno'], i) for i in classifications] 691 | # 插入分类 692 | cursor.executemany(''' 693 | INSERT 694 | INTO classification 695 | VALUES(%s, %s) 696 | ''', classifications) 697 | 698 | conn.commit() 699 | except Exception as e: 700 | print('Update book error!') 701 | print(e) 702 | res = False 703 | finally: 704 | if conn: 705 | conn.close() 706 | return res 707 | 708 | 709 | # 删除书籍 710 | def delete_book(bno: str) -> bool: 711 | ''' 712 | 传入BID 713 | 返回bool 714 | 会删除book,borrowing_book,log, classification 表内所有对应的记录 715 | ''' 716 | try: 717 | res = True 718 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 719 | cursor = conn.cursor() 720 | cursor.execute(''' 721 | DELETE 722 | FROM book 723 | WHERE bno=%s''',(bno)) 724 | 725 | cursor.execute(''' 726 | DELETE 727 | FROM borrowing_book 728 | WHERE bno=%s''',(bno)) 729 | 730 | cursor.execute(''' 731 | DELETE 732 | FROM log 733 | WHERE bno=%s''',(bno)) 734 | 735 | cursor.execute(''' 736 | DELETE 737 | FROM classification 738 | WHERE bno=%s 739 | ''', (bno)) 740 | conn.commit() 741 | except Exception as e: 742 | print('delete book error!') 743 | print(e) 744 | res = False 745 | finally: 746 | if conn: 747 | conn.close() 748 | return res 749 | 750 | # 把book元组转换为list 751 | def tuple_to_list(val: list): 752 | ''' 753 | 传入tuple列表把里面的tuple都转换为list同时去掉字符串里的空格 754 | ''' 755 | ans = [] 756 | for tuple_ in val: 757 | temp = [] 758 | for item in tuple_: 759 | temp.append(item) 760 | if type(temp[-1]) is str: 761 | temp[-1] = remove_blank(temp[-1]) 762 | ans.append(temp) 763 | return ans 764 | 765 | # 搜索书籍 766 | def search_book(info: str, restrict: str, sno: str = '') -> list: 767 | ''' 768 | 传入搜索信息,并指明BID或AUTHOR或PRESS或BNAME或CLASSIFYICATION进行查找,如果传入sno则匹配这个学生的借书状态 769 | 返回[[bno, bname, author, date, press, position, sum, rest, class, STATE],...] 770 | ''' 771 | try: 772 | res = [] 773 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 774 | cursor = conn.cursor() 775 | 776 | # 显示所有书信息 777 | if info == 'ID/书名/作者/出版社' or info == '': 778 | cursor.execute(''' 779 | SELECT * 780 | FROM book 781 | ''') 782 | res = tuple_to_list(cursor.fetchall()) 783 | elif restrict != 'bno' and restrict != 'class': 784 | # AUTHOR或PRESS或BNAME 785 | cursor.execute(f''' 786 | SELECT * 787 | FROM book 788 | WHERE {restrict} LIKE %s 789 | ''', ('%' + info + '%')) 790 | res = tuple_to_list(cursor.fetchall()) 791 | elif restrict == 'bno': 792 | # bno 793 | cursor.execute(''' 794 | SELECT * 795 | FROM book 796 | WHERE bno = %s 797 | ''', (info)) 798 | res = tuple_to_list(cursor.fetchall()) 799 | elif restrict == 'class': 800 | # 通过分类搜书 801 | cursor.execute(''' 802 | SELECT bno 803 | FROM classification 804 | WHERE class = %s 805 | ''', (info)) 806 | for bno in cursor.fetchall(): 807 | cursor.execute(''' 808 | SELECT * 809 | FROM book 810 | WHERE bno = %s 811 | ''', (bno[0])) 812 | res.append(tuple_to_list(cursor.fetchall())[0]) 813 | # 把分类搜出来 814 | for book_info in res: 815 | CLASSIFICATIONS = '' 816 | bno = book_info[0] 817 | cursor.execute(''' 818 | SELECT class 819 | FROM classification 820 | WHERE bno = %s 821 | ''', (bno)) 822 | for classification in cursor.fetchall(): 823 | CLASSIFICATIONS += (remove_blank(classification[0]) + ' ') 824 | book_info.append(CLASSIFICATIONS) 825 | 826 | # 匹配学生信息判断每一本书是否可借 827 | if sno != '': 828 | # 获得学生最大借书数 829 | cursor.execute(''' 830 | SELECT max_book 831 | FROM student 832 | WHERE sno=%s 833 | ''', (sno)) 834 | max_num = cursor.fetchall()[0][0] 835 | # 获取已经借阅的书的列表 836 | borrowing_book = get_borrowing_books(sno) 837 | # 判断是否有罚金 838 | punish = False 839 | for i in borrowing_book: 840 | if i[4] < time.strftime("%Y-%m-%d-%H:%M"): 841 | punish = True 842 | break 843 | for book in res: 844 | # 有罚金没交 845 | if punish: 846 | book.append('未交罚金') 847 | continue 848 | # 如果已经借的书达到上限就不再可借 849 | if len(borrowing_book) >= max_num: 850 | book.append('借书达上限') 851 | continue 852 | if book[-2] == 0: 853 | book.append('没有剩余') 854 | continue 855 | # 判断是否有此书 856 | for borrow in borrowing_book: 857 | if book[0] == borrow[1]: 858 | book.append('已借此书') 859 | break 860 | if book[-1] != '已借此书': 861 | book.append('借书') 862 | except Exception as e: 863 | print('Search error!') 864 | print(e) 865 | res = [] 866 | finally: 867 | if conn: 868 | conn.close() 869 | return res 870 | 871 | # 将日期延后两个月 872 | def postpone(start: str): 873 | temp = start.split('-') 874 | temp[0] = int(temp[0]) 875 | temp[1] = int(temp[1]) 876 | temp[2] = int(temp[2]) 877 | temp[1] += 2 878 | if temp[1] > 12: 879 | temp[1] -= 12 880 | temp[0] += 1 881 | ans = '{:d}-{:0>2d}-{:0>2d}-{}'.format(temp[0], temp[1], temp[2], temp[3]) 882 | return ans 883 | 884 | 885 | # 借书 886 | def borrow_book(bno: str, sno: str) -> bool: 887 | ''' 888 | 传入BID和sno 889 | 返回bool 890 | book的NUM减一 891 | 在borrowing_book表内新建记录 892 | ''' 893 | try: 894 | res = True 895 | conn = pymysql.connect(host=CONFIG['host'], user=CONFIG['user'], password=CONFIG['pwd'], database=CONFIG['db']) 896 | cursor = conn.cursor() 897 | # 先把借书日期,书本剩余数量,罚金等信息找出 898 | cursor.execute(''' 899 | SELECT rest 900 | FROM book 901 | WHERE bno=%s 902 | ''', (bno)) 903 | book_mes = cursor.fetchall() 904 | # print(book_mes) 905 | rest = book_mes[0][0] 906 | borrow_date = time.strftime("%Y-%m-%d-%H:%M") 907 | deadline = postpone(borrow_date) 908 | 909 | # book表内NUM减一,新建borrowing_book表内的记录 910 | cursor.execute(''' 911 | UPDATE book 912 | SET rest=%s 913 | WHERE bno=%s''',(str(rest-1), bno)) 914 | conn.commit() 915 | 916 | cursor.execute(''' 917 | INSERT 918 | INTO borrowing_book 919 | VALUES(%s, %s, %s, %s, 0) 920 | ''', (bno, sno, borrow_date, deadline)) 921 | conn.commit() 922 | 923 | except Exception as e: 924 | print('borrow error!') 925 | print(e) 926 | res = False 927 | finally: 928 | if conn: 929 | conn.close() 930 | return res 931 | 932 | # 两个日期之间间隔的天数 933 | def days_between(start: str, end: str): 934 | start = start.split('-') 935 | end = end.split('-') 936 | start[0] = int(start[0]) 937 | start[1] = int(start[1]) 938 | start[2] = int(start[2]) 939 | 940 | end[0] = int(end[0]) 941 | end[1] = int(end[1]) 942 | end[2] = int(end[2]) 943 | 944 | s = start[0]*365+start[1]*30+start[2] 945 | e = end[0]*365+end[1]*30+end[2] 946 | return e-s 947 | 948 | # res = encrypt('123456') 949 | # print(res) -------------------------------------------------------------------------------- /icon/book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BecauseY/Library-Management-System/fdaed1165517f11728ff6d86a5c8c4c6e8553726/icon/book.png -------------------------------------------------------------------------------- /icon/borrowing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BecauseY/Library-Management-System/fdaed1165517f11728ff6d86a5c8c4c6e8553726/icon/borrowing.png -------------------------------------------------------------------------------- /icon/detial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BecauseY/Library-Management-System/fdaed1165517f11728ff6d86a5c8c4c6e8553726/icon/detial.png -------------------------------------------------------------------------------- /icon/history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BecauseY/Library-Management-System/fdaed1165517f11728ff6d86a5c8c4c6e8553726/icon/history.png -------------------------------------------------------------------------------- /icon/person.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BecauseY/Library-Management-System/fdaed1165517f11728ff6d86a5c8c4c6e8553726/icon/person.png -------------------------------------------------------------------------------- /image/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BecauseY/Library-Management-System/fdaed1165517f11728ff6d86a5c8c4c6e8553726/image/bg.jpg -------------------------------------------------------------------------------- /image/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BecauseY/Library-Management-System/fdaed1165517f11728ff6d86a5c8c4c6e8553726/image/image.png -------------------------------------------------------------------------------- /login.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QLabel, QLineEdit, QToolButton, QPushButton 3 | from PyQt5.QtCore import Qt 4 | 5 | 6 | class Login(QWidget): 7 | def __init__(self): 8 | super().__init__() 9 | self.bodyLayout = QGridLayout() 10 | 11 | # 欢迎登陆图书馆系统标题 12 | self.titleText = QLabel(self) 13 | self.titleText.setText('登录我的图书馆') 14 | self.titleText.setAlignment(Qt.AlignCenter) 15 | self.titleText.setFixedSize(480, 60) 16 | 17 | account = QLabel() 18 | account.setText('读者证号(学工号)') 19 | 20 | password = QLabel() 21 | password.setText('图书馆密码') 22 | 23 | # 学号输入框 24 | self.accountInput = QLineEdit() 25 | self.accountInput.setFixedSize(400, 50) 26 | self.accountInput.setTextMargins(5, 5, 5, 5) 27 | self.accountInput.mousePressEvent = lambda x: self.inputClick(self.accountInput) 28 | # self.accountInput.setClearButtonEnabled(True) 29 | 30 | # 密码输入框 31 | self.passwordInput = QLineEdit() 32 | self.passwordInput.setFixedSize(400, 50) 33 | self.passwordInput.setTextMargins(5, 5, 5, 5) 34 | self.passwordInput.mousePressEvent = lambda x: self.inputClick(self.passwordInput) 35 | self.passwordInput.setEchoMode(QLineEdit.Password) 36 | # self.passwordInput.setClearButtonEnabled(True) 37 | 38 | # 注册按钮 39 | self.signup = QToolButton() 40 | self.signup.setText('注册') 41 | self.signup.setFixedSize(80, 40) 42 | 43 | # 登录按钮 44 | self.loginButton = QToolButton() 45 | self.loginButton.setText('登录') 46 | self.loginButton.setFixedSize(80, 40) 47 | 48 | # 把上面定义的元素加入大框 49 | self.inputBoxLayout = QVBoxLayout() 50 | self.inputBoxLayout.addWidget(account) 51 | self.inputBoxLayout.addWidget(self.accountInput) 52 | self.inputBoxLayout.addWidget(password) 53 | self.inputBoxLayout.addWidget(self.passwordInput) 54 | 55 | self.inputBoxLayout2 = QHBoxLayout() 56 | self.inputBoxLayout2.addWidget(self.signup) 57 | self.inputBoxLayout2.addWidget(self.loginButton) 58 | 59 | # 下面一个大框 60 | self.inputBox = QWidget() 61 | self.inputBox.setObjectName('inputBox') 62 | self.inputBox.setContentsMargins(30, 30, 30, 30) 63 | self.inputBox.setFixedSize(480, 250) 64 | self.inputBox.setLayout(self.inputBoxLayout) 65 | 66 | self.inputBox2 = QWidget() 67 | self.inputBox2.setObjectName('inputBox2') 68 | self.inputBox2.setContentsMargins(30, 30, 30, 30) 69 | self.inputBox2.setFixedSize(480, 150) 70 | self.inputBox2.setLayout(self.inputBoxLayout2) 71 | 72 | # 把大标题和下面输入框加入self 73 | self.bodyLayout.addWidget(self.titleText, 0, 0) 74 | self.bodyLayout.addWidget(self.inputBox, 1, 0) 75 | self.bodyLayout.addWidget(self.inputBox2, 2, 0) 76 | self.setLayout(self.bodyLayout) 77 | self.setFixedSize(480, 450) 78 | self.setMyStyle() 79 | 80 | def inputClick(self, e): 81 | if e.text() == '学号' or e.text() == '******': 82 | e.setText('') 83 | 84 | def setMyStyle(self): 85 | self.setStyleSheet(''' 86 | QWidget{ 87 | background-color:white; 88 | } 89 | ''') 90 | self.titleText.setStyleSheet(''' 91 | *{ 92 | color: rgba(3, 54, 73); 93 | width: 200px; 94 | background-color: #8CC7B5; 95 | font-size: 20px; 96 | font-family: 微软雅黑; 97 | } 98 | ''') 99 | self.inputBox.setStyleSheet(''' 100 | 101 | QLineEdit{ 102 | color: black; 103 | font-size: 25px; 104 | font-family: 微软雅黑; 105 | } 106 | QLabel{ 107 | font-size: 20px; 108 | font-family: 微软雅黑; 109 | } 110 | QToolButton{ 111 | background-color:#8CC7B5; 112 | color: black; 113 | font-size: 20px; 114 | font-family: 微软雅黑; 115 | } 116 | QPushButton{ 117 | color:black; 118 | font-weight:300; 119 | border:1; 120 | background-color:#8CC7B5; 121 | font-size: 20px; 122 | font-family: 微软雅黑; 123 | } 124 | ''') 125 | 126 | 127 | if __name__ == '__main__': 128 | app = QApplication(sys.argv) 129 | ex = Login() 130 | ex.show() 131 | sys.exit(app.exec_()) 132 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PyQt5.QtWidgets import (QApplication, QWidget, QMessageBox) 3 | from PyQt5 import QtGui 4 | import login 5 | import func 6 | import signup 7 | import student 8 | import administrator 9 | 10 | 11 | class MainWindow(QWidget): 12 | 13 | def __init__(self): 14 | super().__init__() 15 | self.login_win() 16 | self.setGeometry(200, 200, 1280, 720) 17 | self.setFixedSize(1280, 720) 18 | self.setMyStyle() 19 | # 创建登录菜单 20 | 21 | def login_win(self): 22 | self.login = login.Login() 23 | self.login.setParent(self) 24 | self.login.move(390, 120) 25 | self.login.loginButton.clicked.connect(self.login_button_function) 26 | self.login.signup.clicked.connect(self.signup_button_function) 27 | # 登录按钮按下 28 | 29 | def login_button_function(self): 30 | user_mes = { 31 | 'ID': self.login.accountInput.text(), 32 | 'PASSWORD': func.encrypt(self.login.passwordInput.text()) 33 | } 34 | self.user = func.signin(user_mes) 35 | if self.user is not None: 36 | self.login.setVisible(False) 37 | self.display() 38 | else: 39 | print('登录失败!') 40 | 41 | # 显示注册界面 42 | def signup_button_function(self): 43 | self.login.setVisible(False) 44 | self.signup_win() 45 | 46 | # 创建注册菜单 47 | def signup_win(self): 48 | self.signup = signup.Signup() 49 | self.signup.setParent(self) 50 | self.signup.setVisible(True) 51 | self.signup.move(425, 110) 52 | self.signup.back.clicked.connect(self.back) 53 | self.signup.submit.clicked.connect(self.signup_function) 54 | 55 | # 后退按钮 56 | def back(self): 57 | self.signup.setVisible(False) 58 | self.login.setVisible(True) 59 | 60 | # 注册按钮按下 61 | def signup_function(self): 62 | self.user = self.signup.getInfo() 63 | res = func.check_user_info(self.user) 64 | if res['res'] == 'fail': 65 | self.errorBox(res['reason']) 66 | return 67 | self.user['max_book'] = int(self.user['max_book']) 68 | self.user['password'] = func.encrypt(self.user['password']) 69 | 70 | ans = func.signup(self.user) 71 | self.user['class'] = 'stu' 72 | self.user.pop('password') 73 | if ans: 74 | self.signup.setVisible(False) 75 | print('成功') 76 | self.display() 77 | else: 78 | self.errorBox('注册失败') 79 | 80 | def display(self): 81 | # 显示学生信息 82 | if self.user['class'] == 'stu': 83 | self.body = student.StudentPage(self.user) 84 | self.body.setParent(self) 85 | self.body.setVisible(True) 86 | self.body.out.clicked.connect(self.logout) 87 | else: 88 | self.body = administrator.AdministratorPage(self.user) 89 | self.body.setParent(self) 90 | self.body.setVisible(True) 91 | self.body.out.clicked.connect(self.logout) 92 | 93 | 94 | def logout(self): 95 | self.body.close() 96 | self.login.setVisible(True) 97 | 98 | def errorBox(self, mes: str): 99 | msgBox = QMessageBox( 100 | QMessageBox.Warning, 101 | "警告!", 102 | mes, 103 | QMessageBox.NoButton, 104 | self 105 | ) 106 | msgBox.addButton("确认", QMessageBox.AcceptRole) 107 | msgBox.exec_() 108 | 109 | def setMyStyle(self): 110 | window_pale = QtGui.QPalette() 111 | window_pale.setBrush(self.backgroundRole(), QtGui.QBrush(QtGui.QPixmap("image/bg.jpg").scaled(1280, 720))) 112 | self.setPalette(window_pale) 113 | 114 | 115 | if __name__ == '__main__': 116 | app = QApplication(sys.argv) 117 | mainwindow = MainWindow() 118 | mainwindow.setWindowTitle("图书馆管理系统") 119 | mainwindow.show() 120 | sys.exit(app.exec_()) 121 | 122 | -------------------------------------------------------------------------------- /signup.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PyQt5.QtWidgets import (QApplication, QVBoxLayout, QLabel, QLineEdit, QToolButton, QGroupBox) 3 | from PyQt5.QtCore import Qt 4 | 5 | class Signup(QGroupBox): 6 | def __init__(self): 7 | super().__init__() 8 | 9 | self.title = QLabel() 10 | self.title.setText('注册用户') 11 | self.title.setAlignment(Qt.AlignCenter) 12 | self.subTitle = QLabel() 13 | self.subTitle.setText('创建一个新的账户') 14 | 15 | account = QLabel() 16 | account.setText('学号') 17 | 18 | name = QLabel() 19 | name.setText('姓名') 20 | 21 | password = QLabel() 22 | password.setText('密码') 23 | 24 | repPassword = QLabel() 25 | repPassword.setText('重复密码') 26 | 27 | maxNum = QLabel() 28 | maxNum.setText('最大借书数') 29 | 30 | dept = QLabel() 31 | dept.setText('学院') 32 | 33 | major = QLabel() 34 | major.setText('专业') 35 | 36 | # 学号输入框 37 | self.accountInput = QLineEdit() 38 | self.accountInput.setFixedSize(400, 40) 39 | self.accountInput.setText('请输入学号') 40 | self.accountInput.initText = '请输入学号' 41 | self.accountInput.setTextMargins(5, 5, 5, 5) 42 | self.accountInput.mousePressEvent = lambda x: self.inputClick(self.accountInput) 43 | 44 | # 姓名输入框 45 | self.nameInput = QLineEdit() 46 | self.nameInput.setFixedSize(400, 40) 47 | self.nameInput.setText('请输入姓名') 48 | self.nameInput.initText = '请输入姓名' 49 | self.nameInput.setTextMargins(5, 5, 5, 5) 50 | self.nameInput.mousePressEvent = lambda x: self.inputClick(self.nameInput) 51 | 52 | # 密码 53 | self.passwordInput = QLineEdit() 54 | self.passwordInput.setFixedSize(400, 40) 55 | self.passwordInput.setText('请输入密码') 56 | self.passwordInput.initText = '请输入密码' 57 | self.passwordInput.setTextMargins(5, 5, 5, 5) 58 | self.passwordInput.mousePressEvent = lambda x: self.inputClick(self.passwordInput) 59 | 60 | # 重复密码 61 | self.repPasswordInput = QLineEdit() 62 | self.repPasswordInput.setFixedSize(400, 40) 63 | self.repPasswordInput.setText('请重复输入密码') 64 | self.repPasswordInput.initText = '请重复输入密码' 65 | self.repPasswordInput.setTextMargins(5, 5, 5, 5) 66 | self.repPasswordInput.mousePressEvent = lambda x: self.inputClick(self.repPasswordInput) 67 | 68 | # 最大借书数 69 | self.maxNumInput = QLineEdit() 70 | self.maxNumInput.setFixedSize(400, 40) 71 | self.maxNumInput.setText('请输入最大借书数') 72 | self.maxNumInput.initText = '请输入最大借书数' 73 | self.maxNumInput.setTextMargins(5, 5, 5, 5) 74 | self.maxNumInput.mousePressEvent = lambda x: self.inputClick(self.maxNumInput) 75 | 76 | # 学院 77 | self.deptInput = QLineEdit() 78 | self.deptInput.setFixedSize(400, 40) 79 | self.deptInput.setText('请输入所在学院') 80 | self.deptInput.initText = '请输入所在学院' 81 | self.deptInput.setTextMargins(5, 5, 5, 5) 82 | self.deptInput.mousePressEvent = lambda x: self.inputClick(self.deptInput) 83 | 84 | # 专业 85 | self.majorInput = QLineEdit() 86 | self.majorInput.setFixedSize(400, 40) 87 | self.majorInput.setText('请输入所在专业') 88 | self.majorInput.initText = '请输入所在专业' 89 | self.majorInput.setTextMargins(5, 5, 5, 5) 90 | self.majorInput.mousePressEvent = lambda x: self.inputClick(self.majorInput) 91 | 92 | # 提交 93 | self.submit = QToolButton() 94 | self.submit.setText('提交') 95 | self.submit.setFixedSize(400, 40) 96 | 97 | # 返回登录 98 | self.back = QToolButton() 99 | self.back.setText('返回登录') 100 | self.back.setFixedSize(400, 40) 101 | 102 | self.bodyLayout = QVBoxLayout() 103 | self.bodyLayout.addWidget(self.title) 104 | self.bodyLayout.addWidget(self.subTitle) 105 | self.bodyLayout.addWidget(self.accountInput) 106 | self.bodyLayout.addWidget(self.nameInput) 107 | self.bodyLayout.addWidget(self.passwordInput) 108 | self.bodyLayout.addWidget(self.repPasswordInput) 109 | self.bodyLayout.addWidget(self.deptInput) 110 | self.bodyLayout.addWidget(self.majorInput) 111 | self.bodyLayout.addWidget(self.maxNumInput) 112 | self.bodyLayout.addWidget(self.submit) 113 | self.bodyLayout.addWidget(self.back) 114 | 115 | self.setLayout(self.bodyLayout) 116 | self.initUI() 117 | 118 | def inputClick(self, e): 119 | for i in range(2, 9): 120 | item = self.bodyLayout.itemAt(i).widget() 121 | if item.text() == '': 122 | item.setText(item.initText) 123 | if item is self.passwordInput or item is self.repPasswordInput: 124 | item.setEchoMode(QLineEdit.Normal) 125 | 126 | if e.text() == e.initText: 127 | e.setText('') 128 | if e is self.passwordInput or e is self.repPasswordInput: 129 | e.setEchoMode(QLineEdit.Password) 130 | 131 | def initUI(self): 132 | self.setFixedSize(422, 500) 133 | self.setWindowTitle('注册') 134 | self.setMyStyle() 135 | 136 | def getInfo(self): 137 | for i in range(2, 9): 138 | item = self.bodyLayout.itemAt(i).widget() 139 | if item.text() == item.initText: 140 | item.setText('') 141 | 142 | info = { 143 | 'sno': self.accountInput.text(), 144 | 'password': self.passwordInput.text(), 145 | 'repassword': self.repPasswordInput.text(), 146 | 'sname': self.nameInput.text(), 147 | 'dept': self.deptInput.text(), 148 | 'majority': self.majorInput.text(), 149 | 'max_book': self.maxNumInput.text(), 150 | 'punish_money': 0 151 | } 152 | return info 153 | 154 | def setMyStyle(self): 155 | self.setStyleSheet(''' 156 | QWidget{ 157 | background-color: white; 158 | } 159 | QLineEdit{ 160 | border:0px; 161 | border-bottom: 1px solid rgba(229, 229, 229, 1); 162 | color: grey; 163 | } 164 | QToolButton{ 165 | border:0; 166 | background-color:#19caad; 167 | color: white; 168 | font-size: 20px; 169 | font-family: 微软雅黑; 170 | } 171 | QGroupBox{ 172 | border: 1px solid rgba(229, 229, 229, 1); 173 | border-radius: 5px; 174 | } 175 | ''') 176 | self.title.setStyleSheet(''' 177 | *{ 178 | color: rgba(113, 118, 121, 1); 179 | font-size: 30px; 180 | font-family: 微软雅黑; 181 | } 182 | ''') 183 | self.subTitle.setStyleSheet(''' 184 | *{ 185 | color: rgba(184, 184, 184, 1); 186 | } 187 | ''') 188 | 189 | 190 | if __name__ == '__main__': 191 | app = QApplication(sys.argv) 192 | ex = Signup() 193 | ex.show() 194 | sys.exit(app.exec_()) 195 | -------------------------------------------------------------------------------- /student.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | import os 4 | from PyQt5.QtWidgets import (QApplication, QWidget, QGridLayout, QGroupBox, 5 | QToolButton, QSplitter, QVBoxLayout, QHBoxLayout, 6 | QLabel, QTableWidget, QTableWidgetItem, QAbstractItemView, 7 | QLineEdit, QFileDialog, QToolTip, QComboBox) 8 | from PyQt5.QtGui import QIcon, QFont 9 | from PyQt5.QtCore import Qt, QSize 10 | import func 11 | # import func 12 | 13 | 14 | class StudentPage(QWidget): 15 | def __init__(self, stu_mes): 16 | super().__init__() 17 | self.focus = 0 18 | self.stu_mes = stu_mes 19 | self.initUI() 20 | 21 | def initUI(self): 22 | # 标题栏 23 | self.titleBar = QWidget() 24 | self.titleBar.setFixedSize(1250, 50) 25 | self.setTitleBar() 26 | 27 | # 分割 28 | self.body = QSplitter(Qt.Vertical,self) 29 | self.setLeftMunu() 30 | self.content = None 31 | self.setContent() 32 | 33 | self.bodyLayout = QGridLayout() 34 | self.bodyLayout.addWidget(self.titleBar, 0, 0, 1, 7) 35 | self.bodyLayout.addWidget(self.body, 1, 0, 7, 7) 36 | self.setContentsMargins(0, 0, 0, 0) 37 | self.setLayout(self.bodyLayout) 38 | self.setFixedSize(1280, 720) 39 | self.setMyStyle() 40 | 41 | # 设置标题栏 42 | def setTitleBar(self): 43 | self.title = QLabel() 44 | self.title.setText('欢迎使用图书馆管理系统') 45 | self.title.setFixedHeight(30) 46 | 47 | self.account = QToolButton() 48 | self.account.setIcon(QIcon('icon/person.png')) 49 | self.account.setText(self.stu_mes['sno']+self.stu_mes['sname']+',你好!') 50 | self.account.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) 51 | self.account.setFixedHeight(20) 52 | self.account.setEnabled(False) 53 | 54 | self.out = QToolButton() 55 | self.out.setText('退出') 56 | self.out.setFixedHeight(30) 57 | 58 | titleLayout = QHBoxLayout() 59 | titleLayout.addWidget(self.account) 60 | titleLayout.addSpacing(120) 61 | titleLayout.addWidget(self.title) 62 | titleLayout.addWidget(self.out) 63 | self.titleBar.setLayout(titleLayout) 64 | 65 | # 左侧菜单栏 66 | def setLeftMunu(self): 67 | # 查询按钮 68 | self.bookSearch = QToolButton() 69 | self.bookSearch.setText('图书查询') 70 | self.bookSearch.setFixedSize(160, 50) 71 | self.bookSearch.setIcon(QIcon('icon/book.png')) 72 | self.bookSearch.setIconSize(QSize(30, 30)) 73 | self.bookSearch.clicked.connect( 74 | lambda: self.switch(0, self.bookSearch)) 75 | self.bookSearch.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) 76 | 77 | # 借阅按钮 78 | self.borrow = QToolButton() 79 | self.borrow.setText('借阅信息') 80 | self.borrow.setFixedSize(160, 50) 81 | self.borrow.setIcon(QIcon('icon/borrowing.png')) 82 | self.borrow.setIconSize(QSize(30, 30)) 83 | self.borrow.clicked.connect(lambda: self.switch(1, self.borrow)) 84 | self.borrow.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) 85 | 86 | # 借阅历史 87 | self.history = QToolButton() 88 | self.history.setText('借阅历史') 89 | self.history.setFixedSize(160, 50) 90 | self.history.setIcon(QIcon('icon/history.png')) 91 | self.history.setIconSize(QSize(30, 30)) 92 | self.history.clicked.connect(lambda: self.switch(2, self.history)) 93 | self.history.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) 94 | 95 | # 个人信息 96 | self.detial = QToolButton() 97 | self.detial.setText('个人信息') 98 | self.detial.setFixedSize(160, 50) 99 | self.detial.setIcon(QIcon('icon/detial.png')) 100 | self.detial.setIconSize(QSize(30, 30)) 101 | self.detial.clicked.connect(lambda: self.switch(3, self.detial)) 102 | self.detial.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) 103 | 104 | self.btnList = [self.bookSearch, 105 | self.borrow, self.history, self.detial] 106 | 107 | self.layout = QHBoxLayout() 108 | self.layout.addStretch() 109 | self.layout.addWidget(self.bookSearch) 110 | self.layout.addStretch() 111 | self.layout.addWidget(self.borrow) 112 | self.layout.addStretch() 113 | self.layout.addWidget(self.history) 114 | self.layout.addStretch() 115 | self.layout.addWidget(self.detial) 116 | self.layout.addStretch() 117 | self.layout.setContentsMargins(0, 0, 0, 0) 118 | self.layout.setSpacing(0) 119 | 120 | self.menu = QGroupBox() 121 | self.menu.setFixedSize(1250, 50) 122 | self.menu.setLayout(self.layout) 123 | self.menu.setContentsMargins(0, 0, 0, 0) 124 | self.body.addWidget(self.menu) 125 | 126 | def switch(self, index, btn): 127 | self.focus = index 128 | for i in self.btnList: 129 | i.setStyleSheet(''' 130 | *{ 131 | background: white; 132 | } 133 | QToolButton:hover{ 134 | background-color: rgba(230, 230, 230, 0.3); 135 | } 136 | ''') 137 | 138 | btn.setStyleSheet(''' 139 | QToolButton{ 140 | background-color: rgba(230, 230, 230, 0.7); 141 | } 142 | ''') 143 | self.setContent() 144 | 145 | # 设置右侧信息页 146 | def setContent(self): 147 | if self.content is not None: 148 | self.content.deleteLater() 149 | if self.focus == 0: 150 | self.content = Books(self.stu_mes) 151 | elif self.focus == 1: 152 | self.content = BorrowingBooks(self.stu_mes) 153 | elif self.focus == 2: 154 | self.content = History(self.stu_mes) 155 | else: 156 | self.content = Detial(self.stu_mes) 157 | self.body.addWidget(self.content) 158 | 159 | def setMyStyle(self): 160 | self.setStyleSheet(''' 161 | QWidget{ 162 | background-color: white; 163 | } 164 | ''') 165 | self.titleBar.setStyleSheet(''' 166 | QWidget{ 167 | background-color: rgba(44,44,44,1); 168 | border:1px solid black; 169 | 170 | } 171 | ''') 172 | self.menu.setStyleSheet(''' 173 | QWidget{ 174 | border: 0px; 175 | border-right: 1px solid rgba(227, 227, 227, 1); 176 | } 177 | QToolButton{ 178 | color: rgba(51, 90, 129, 1); 179 | font-family: 微软雅黑; 180 | font-size: 25px; 181 | border-right: 1px solid rgba(227, 227, 227, 1); 182 | } 183 | QToolButton:hover{ 184 | background-color: rgba(230, 230, 230, 0.3); 185 | } 186 | ''') 187 | self.title.setStyleSheet(''' 188 | *{ 189 | color: white; 190 | font-family: 微软雅黑; 191 | font-size: 25px; 192 | border: 0px; 193 | } 194 | ''') 195 | self.account.setStyleSheet(''' 196 | *{ 197 | color: white; 198 | font-weight: 微软雅黑; 199 | font-size: 25px; 200 | border: 0px; 201 | } 202 | ''') 203 | self.out.setStyleSheet(''' 204 | QToolButton{ 205 | color: white; 206 | border:0px; 207 | font-size: 12px; 208 | } 209 | QToolButton:hover{ 210 | color: rgba(11, 145, 255, 1); 211 | } 212 | ''') 213 | 214 | 215 | class Books(QGroupBox): 216 | def __init__(self, stu_mes): 217 | super().__init__() 218 | self.stu_mes = stu_mes 219 | self.book_list = [] 220 | self.body = QVBoxLayout() 221 | self.table = None 222 | self.setTitleBar() 223 | self.setSearchBar() 224 | self.searchFunction() 225 | 226 | self.setLayout(self.body) 227 | self.setFixedSize(1280, 600) 228 | self.setMyStyle() 229 | 230 | # 标题栏 231 | def setTitleBar(self): 232 | self.title = QLabel() 233 | self.title.setText('书籍信息') 234 | self.title.setFixedHeight(25) 235 | titleLayout = QHBoxLayout() 236 | titleLayout.addStretch() 237 | titleLayout.addWidget(self.title) 238 | titleLayout.addStretch() 239 | self.titleBar = QWidget() 240 | self.titleBar.setFixedSize(1250, 50) 241 | self.titleBar.setLayout(titleLayout) 242 | self.body.addWidget(self.titleBar) 243 | 244 | # 设置搜索框 245 | def setSearchBar(self): 246 | self.selectBox = QComboBox() 247 | self.selectBox.addItems(['书号', '分类', '出版社', '作者', '书名']) 248 | self.selectBox.setFixedHeight(30) 249 | self.searchTitle = QLabel() 250 | self.searchTitle.setText('搜索书籍') 251 | self.searchInput = QLineEdit() 252 | self.searchInput.setText('') 253 | self.searchInput.setClearButtonEnabled(True) 254 | self.searchInput.setFixedSize(400, 40) 255 | self.searchButton = QToolButton() 256 | self.searchButton.setFixedSize(100, 40) 257 | self.searchButton.setText('搜索') 258 | self.searchButton.clicked.connect(self.searchFunction) 259 | searchLayout = QHBoxLayout() 260 | searchLayout.addStretch() 261 | searchLayout.addWidget(self.selectBox) 262 | searchLayout.addWidget(self.searchTitle) 263 | searchLayout.addWidget(self.searchInput) 264 | searchLayout.addWidget(self.searchButton) 265 | searchLayout.addStretch() 266 | self.searchWidget = QWidget() 267 | self.searchWidget.setLayout(searchLayout) 268 | self.body.addWidget(self.searchWidget) 269 | 270 | # 搜索方法 271 | def searchFunction(self): 272 | convert = {'书号': 'bno', '分类': 'class', '出版社': 'press', '作者': 'author', '书名': 'bname', '': 'bname'} 273 | self.book_list = func.search_book(self.searchInput.text(), convert[self.selectBox.currentText()], self.stu_mes['sno']) 274 | if self.book_list == []: 275 | print('未找到') 276 | if self.table is not None: 277 | self.table.deleteLater() 278 | self.setTable() 279 | 280 | # 设置表格 281 | def setTable(self): 282 | self.table = QTableWidget(1, 9) 283 | self.table.setContentsMargins(10, 10, 10, 10) 284 | self.table.verticalHeader().setVisible(False) 285 | self.table.horizontalHeader().setVisible(False) 286 | self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) 287 | self.table.setFocusPolicy(Qt.NoFocus) 288 | self.table.setColumnWidth(0, 80) 289 | # self.table.setColumnWidth(1, 150) 290 | # self.table.setColumnWidth(2, 125) 291 | # self.table.setColumnWidth(3, 125) 292 | # self.table.setColumnWidth(4, 100) 293 | self.table.setColumnWidth(6, 80) 294 | 295 | self.table.setItem(0, 0, QTableWidgetItem('书号')) 296 | self.table.setItem(0, 1, QTableWidgetItem('书名')) 297 | self.table.setItem(0, 2, QTableWidgetItem('作者')) 298 | self.table.setItem(0, 3, QTableWidgetItem('出版日期')) 299 | self.table.setItem(0, 4, QTableWidgetItem('出版社')) 300 | self.table.setItem(0, 5, QTableWidgetItem('分类')) 301 | self.table.setItem(0, 6, QTableWidgetItem('位置')) 302 | self.table.setItem(0, 7, QTableWidgetItem('总数/剩余')) 303 | self.table.setItem(0, 8, QTableWidgetItem('操作')) 304 | 305 | for i in range(9): 306 | self.table.item(0, i).setTextAlignment(Qt.AlignCenter) 307 | self.table.item(0, i).setFont(QFont('微软雅黑', 15)) 308 | 309 | # 显示借阅详情 310 | for i in self.book_list: 311 | self.insertRow(i) 312 | self.body.addWidget(self.table) 313 | 314 | # 插入行 315 | def insertRow(self, val: list): 316 | itemBID = QTableWidgetItem(val[0]) 317 | itemBID.setTextAlignment(Qt.AlignCenter) 318 | 319 | itemNAME = QTableWidgetItem('《' + val[1] + '》') 320 | itemNAME.setTextAlignment(Qt.AlignCenter) 321 | 322 | itemAUTHOR = QTableWidgetItem(val[2]) 323 | itemAUTHOR.setTextAlignment(Qt.AlignCenter) 324 | 325 | itemDATE = QTableWidgetItem(val[3]) 326 | itemDATE.setTextAlignment(Qt.AlignCenter) 327 | 328 | itemPRESS = QTableWidgetItem(val[4]) 329 | itemPRESS.setTextAlignment(Qt.AlignCenter) 330 | 331 | itemPOSITION = QTableWidgetItem(val[5]) 332 | itemPOSITION.setTextAlignment(Qt.AlignCenter) 333 | 334 | itemSUM = QTableWidgetItem(str(val[6])+'/'+str(val[7])) 335 | itemSUM.setTextAlignment(Qt.AlignCenter) 336 | 337 | itemCLASSIFICATION = QTableWidgetItem(val[8]) 338 | itemCLASSIFICATION.setTextAlignment(Qt.AlignCenter) 339 | 340 | itemOPERATE = QToolButton(self.table) 341 | itemOPERATE.setFixedSize(70, 25) 342 | if val[-1] == '借书': 343 | itemOPERATE.setText('借书') 344 | itemOPERATE.clicked.connect(lambda: self.borrowBook(val[0])) 345 | itemOPERATE.setStyleSheet(''' 346 | *{ 347 | color: white; 348 | font-family: 微软雅黑; 349 | background: rgba(131, 175, 155, 1); 350 | border: 0; 351 | 352 | font-size:18px; 353 | } 354 | ''') 355 | else: 356 | itemOPERATE.setText('不可借') 357 | itemOPERATE.setEnabled(False) 358 | itemOPERATE.setToolTip(val[-1]) 359 | QToolTip.setFont(QFont('微软雅黑', 15)) 360 | itemOPERATE.setStyleSheet(''' 361 | QToolButton{ 362 | color: white; 363 | font-family: 微软雅黑; 364 | background: rgba(200, 200, 200, 1); 365 | border: 0; 366 | 367 | font-size:18px; 368 | } 369 | QToolTip{ 370 | color: black; 371 | border: 1px solid rgba(200, 200, 200, 1); 372 | } 373 | ''') 374 | 375 | itemLayout = QHBoxLayout() 376 | itemLayout.setContentsMargins(0, 0, 0, 0) 377 | itemLayout.addWidget(itemOPERATE) 378 | itemWidget = QWidget() 379 | itemWidget.setLayout(itemLayout) 380 | 381 | self.table.insertRow(1) 382 | self.table.setItem(1, 0, itemBID) 383 | self.table.setItem(1, 1, itemNAME) 384 | self.table.setItem(1, 2, itemAUTHOR) 385 | self.table.setItem(1, 3, itemDATE) 386 | self.table.setItem(1, 4, itemPRESS) 387 | self.table.setItem(1, 5, itemCLASSIFICATION) 388 | self.table.setItem(1, 6, itemPOSITION) 389 | self.table.setItem(1, 7, itemSUM) 390 | self.table.setCellWidget(1, 8, itemWidget) 391 | 392 | def borrowBook(self, bno: str): 393 | ans = func.borrow_book(bno, self.stu_mes['sno']) 394 | # 刷新表格 395 | if ans: 396 | self.searchFunction() 397 | 398 | def setMyStyle(self): 399 | self.setStyleSheet(''' 400 | *{ 401 | background-color: white; 402 | border:0px; 403 | } 404 | ''') 405 | self.titleBar.setStyleSheet(''' 406 | QWidget { 407 | border:0; 408 | background-color: rgba(216, 216, 216, 1); 409 | color: rgba(113, 118, 121, 1); 410 | } 411 | QLabel{ 412 | font-size: 25px; 413 | font-family: 微软雅黑; 414 | } 415 | ''') 416 | self.searchTitle.setStyleSheet(''' 417 | QLabel{ 418 | font-size:20px; 419 | color: black; 420 | font-family: 微软雅黑; 421 | } 422 | ''') 423 | self.searchInput.setStyleSheet(''' 424 | QLineEdit{ 425 | border: 1px solid rgba(201, 201, 201, 1); 426 | color: rgba(120, 120, 120, 1) 427 | } 428 | ''') 429 | self.searchButton.setStyleSheet(''' 430 | QToolButton{ 431 | 432 | background-color:rgba(131, 175, 155, 1); 433 | color: white; 434 | font-size: 25px; 435 | font-family: 微软雅黑; 436 | } 437 | ''') 438 | self.selectBox.setStyleSheet(''' 439 | *{ 440 | border: 0px; 441 | } 442 | QComboBox{ 443 | border: 1px solid rgba(201, 201, 201, 1); 444 | } 445 | ''') 446 | 447 | 448 | # 正在借阅的书 449 | class BorrowingBooks(QGroupBox): 450 | def __init__(self, stu_mes): 451 | super().__init__() 452 | self.stu_mes = stu_mes 453 | self.body = QVBoxLayout() 454 | self.setTitleBar() 455 | self.setTable() 456 | 457 | self.setLayout(self.body) 458 | self.initUI() 459 | 460 | # 标题栏 461 | def setTitleBar(self): 462 | self.title = QLabel() 463 | self.title.setText('借阅信息') 464 | self.title.setFixedHeight(25) 465 | titleLayout = QHBoxLayout() 466 | titleLayout.addStretch() 467 | titleLayout.addWidget(self.title) 468 | titleLayout.addStretch() 469 | self.titleBar = QWidget() 470 | self.titleBar.setFixedSize(1250, 50) 471 | self.titleBar.setLayout(titleLayout) 472 | self.body.addWidget(self.titleBar) 473 | 474 | def setTable(self, val: dict = None): 475 | self.table = QTableWidget(1, 6) 476 | self.table.setContentsMargins(10, 10, 10, 10) 477 | self.table.verticalHeader().setVisible(False) 478 | self.table.horizontalHeader().setVisible(False) 479 | self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) 480 | self.table.setFocusPolicy(Qt.NoFocus) 481 | self.table.setColumnWidth(0, 150) 482 | self.table.setColumnWidth(1, 150) 483 | self.table.setColumnWidth(2, 175) 484 | self.table.setColumnWidth(3, 175) 485 | self.table.setColumnWidth(4, 100) 486 | self.table.setColumnWidth(5, 150) 487 | 488 | self.table.setItem(0, 0, QTableWidgetItem('书号')) 489 | self.table.setItem(0, 1, QTableWidgetItem('书名')) 490 | self.table.setItem(0, 2, QTableWidgetItem('借书日期')) 491 | self.table.setItem(0, 3, QTableWidgetItem('还书日期')) 492 | self.table.setItem(0, 4, QTableWidgetItem('罚金')) 493 | self.table.setItem(0, 5, QTableWidgetItem('操作')) 494 | 495 | for i in range(6): 496 | self.table.item(0, i).setTextAlignment(Qt.AlignCenter) 497 | self.table.item(0, i).setFont(QFont('微软雅黑', 15)) 498 | self.body.addWidget(self.table) 499 | 500 | # 显示借阅详情 501 | self.book_list = func.get_borrowing_books(self.stu_mes['sno']) 502 | for i in self.book_list: 503 | self.insertRow(i) 504 | self.table.setStyleSheet(''' 505 | *{ 506 | font-size:18px; 507 | color: black; 508 | background-color: white; 509 | font-family: 微软雅黑; 510 | } 511 | ''') 512 | 513 | # 插入行 514 | def insertRow(self, val: list): 515 | itemBID = QTableWidgetItem(val[1]) 516 | itemBID.setTextAlignment(Qt.AlignCenter) 517 | itemNAME = QTableWidgetItem('《' + val[2] + '》') 518 | itemNAME.setTextAlignment(Qt.AlignCenter) 519 | itemBEGIN = QTableWidgetItem(val[3]) 520 | itemBEGIN.setTextAlignment(Qt.AlignCenter) 521 | itemBACK = QTableWidgetItem(val[4]) 522 | itemBACK.setTextAlignment(Qt.AlignCenter) 523 | itemPUNISHED = QLabel() 524 | itemPUNISHED.setText('0') 525 | itemPUNISHED.setAlignment(Qt.AlignCenter) 526 | isPunished = func.days_between( 527 | val[4], time.strftime("%Y-%m-%d-%H:%M")) 528 | if isPunished <= 0: 529 | itemPUNISHED.setStyleSheet(''' 530 | *{ 531 | color: green; 532 | font-size:20px; 533 | font-family: 微软雅黑; 534 | } 535 | ''') 536 | else: 537 | itemPUNISHED.setText(str(isPunished)) 538 | itemPUNISHED.setStyleSheet(''' 539 | *{ 540 | color: red; 541 | font-size:20px; 542 | font-family: 微软雅黑; 543 | } 544 | ''') 545 | itemOPERATE = QToolButton(self.table) 546 | itemOPERATE.setFixedSize(70, 25) 547 | if isPunished <= 0: 548 | itemOPERATE.setText('还书') 549 | itemOPERATE.clicked.connect(lambda: self.retrurnBook(val[1])) 550 | itemOPERATE.setStyleSheet(''' 551 | *{ 552 | color: white; 553 | font-family: 微软雅黑; 554 | background: rgba(38, 175, 217, 1); 555 | border: 0; 556 | 557 | font-size:18px; 558 | } 559 | ''') 560 | else: 561 | itemOPERATE.setText('交罚金') 562 | itemOPERATE.clicked.connect( 563 | lambda: self.pay(val[1], isPunished)) 564 | itemOPERATE.setStyleSheet(''' 565 | *{ 566 | color: white; 567 | font-family: 微软雅黑; 568 | background: rgba(222, 52, 65, 1); 569 | border: 0; 570 | 571 | font-size:18px; 572 | } 573 | ''') 574 | 575 | itemLayout = QHBoxLayout() 576 | itemLayout.setContentsMargins(0, 0, 0, 0) 577 | itemLayout.addWidget(itemOPERATE) 578 | itemWidget = QWidget() 579 | itemWidget.setLayout(itemLayout) 580 | 581 | self.table.insertRow(1) 582 | self.table.setItem(1, 0, itemBID) 583 | self.table.setItem(1, 1, itemNAME) 584 | self.table.setItem(1, 2, itemBEGIN) 585 | self.table.setItem(1, 3, itemBACK) 586 | self.table.setCellWidget(1, 4, itemPUNISHED) 587 | self.table.setCellWidget(1, 5, itemWidget) 588 | 589 | def retrurnBook(self, bno: str): 590 | ans = func.return_book(bno, self.stu_mes['sno']) 591 | # 刷新表格 592 | if ans: 593 | self.book_list = func.get_borrowing_books(self.stu_mes['sno']) 594 | self.table.deleteLater() 595 | self.setTable() 596 | 597 | def pay(self, bno: str, PUNISH): 598 | ans = func.pay(bno, self.stu_mes['sno'], PUNISH) 599 | # 刷新表格 600 | if ans: 601 | self.book_list = func.get_borrowing_books(self.stu_mes['sno']) 602 | self.table.deleteLater() 603 | self.setTable() 604 | 605 | def initUI(self): 606 | self.setFixedSize(1280, 600) 607 | self.setStyleSheet(''' 608 | *{ 609 | background-color: white; 610 | border:0px; 611 | } 612 | ''') 613 | self.titleBar.setStyleSheet(''' 614 | QWidget { 615 | border:0; 616 | background-color: rgba(216, 216, 216, 1); 617 | 618 | color: rgba(113, 118, 121, 1); 619 | } 620 | QLabel{ 621 | font-size: 25px; 622 | font-family: 微软雅黑; 623 | } 624 | ''') 625 | 626 | 627 | class History(QGroupBox): 628 | def __init__(self, stu_mes): 629 | super().__init__() 630 | self.stu_mes = stu_mes 631 | self.body = QVBoxLayout() 632 | self.setTitleBar() 633 | self.setTable() 634 | self.setOut() 635 | self.body.addStretch() 636 | 637 | self.setLayout(self.body) 638 | self.initUI() 639 | 640 | # 标题栏 641 | def setTitleBar(self): 642 | self.title = QLabel() 643 | self.title.setText('借阅记录') 644 | self.title.setFixedHeight(25) 645 | titleLayout = QHBoxLayout() 646 | titleLayout.addStretch() 647 | titleLayout.addWidget(self.title) 648 | titleLayout.addStretch() 649 | self.titleBar = QWidget() 650 | self.titleBar.setFixedSize(1250, 50) 651 | self.titleBar.setLayout(titleLayout) 652 | self.body.addWidget(self.titleBar) 653 | 654 | # 创建表格 655 | def setTable(self, val: dict = None): 656 | self.table = QTableWidget(1, 5) 657 | self.table.setFixedHeight(400) 658 | self.table.setContentsMargins(10, 10, 10, 10) 659 | self.table.verticalHeader().setVisible(False) 660 | self.table.horizontalHeader().setVisible(False) 661 | self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) 662 | self.table.setFocusPolicy(Qt.NoFocus) 663 | self.table.setColumnWidth(0, 200) 664 | self.table.setColumnWidth(1, 250) 665 | self.table.setColumnWidth(2, 175) 666 | self.table.setColumnWidth(3, 175) 667 | self.table.setColumnWidth(4, 100) 668 | 669 | self.table.setItem(0, 0, QTableWidgetItem('书号')) 670 | self.table.setItem(0, 1, QTableWidgetItem('书名')) 671 | self.table.setItem(0, 2, QTableWidgetItem('借书日期')) 672 | self.table.setItem(0, 3, QTableWidgetItem('还书日期')) 673 | self.table.setItem(0, 4, QTableWidgetItem('罚金')) 674 | 675 | for i in range(5): 676 | self.table.item(0, i).setTextAlignment(Qt.AlignCenter) 677 | self.table.item(0, i).setFont(QFont('微软雅黑', 15)) 678 | 679 | self.list = func.get_log(self.stu_mes['sno']) 680 | for i in self.list: 681 | self.insertRow(i) 682 | self.body.addWidget(self.table) 683 | 684 | # 插入行 685 | def insertRow(self, val: list): 686 | itemBID = QTableWidgetItem(val[1]) 687 | itemBID.setTextAlignment(Qt.AlignCenter) 688 | itemNAME = QTableWidgetItem('《' + val[2] + '》') 689 | itemNAME.setTextAlignment(Qt.AlignCenter) 690 | itemBEGIN = QTableWidgetItem(val[3]) 691 | itemBEGIN.setTextAlignment(Qt.AlignCenter) 692 | itemBACK = QTableWidgetItem(val[4]) 693 | itemBACK.setTextAlignment(Qt.AlignCenter) 694 | itemPUNISHED = QLabel() 695 | itemPUNISHED.setText(str(val[5])) 696 | itemPUNISHED.setAlignment(Qt.AlignCenter) 697 | if val[5] == 0: 698 | itemPUNISHED.setStyleSheet(''' 699 | *{ 700 | color: green; 701 | font-size: 20px; 702 | } 703 | ''') 704 | else: 705 | itemPUNISHED.setStyleSheet(''' 706 | *{ 707 | color: red; 708 | font-size: 20px; 709 | } 710 | ''') 711 | 712 | self.table.insertRow(1) 713 | self.table.setItem(1, 0, itemBID) 714 | self.table.setItem(1, 1, itemNAME) 715 | self.table.setItem(1, 2, itemBEGIN) 716 | self.table.setItem(1, 3, itemBACK) 717 | self.table.setCellWidget(1, 4, itemPUNISHED) 718 | 719 | # 导出文件 720 | def setOut(self): 721 | self.outButton = QToolButton() 722 | self.outButton.setText('导出') 723 | self.outButton.clicked.connect(self.outFunction) 724 | self.outButton.setFixedSize(100, 50) 725 | outLayout = QHBoxLayout() 726 | outLayout.addStretch() 727 | outLayout.addWidget(self.outButton) 728 | outWidget = QWidget() 729 | outWidget.setLayout(outLayout) 730 | 731 | self.body.addWidget(outWidget) 732 | 733 | def outFunction(self): 734 | import csv 735 | dirName = QFileDialog.getExistingDirectory(self, '选择文件夹') 736 | 737 | title = ['sno', 'bno', 'bname', 'borrow_date', 'return_date', 'punish_money'] 738 | with open(os.path.join(dirName, self.stu_mes['sno'] + '.csv'), 'w', newline='') as f: 739 | writer = csv.writer(f) 740 | writer.writerow(title) 741 | for row in self.list: 742 | writer.writerow(row) 743 | 744 | def initUI(self): 745 | self.setFixedSize(1280, 600) 746 | self.setStyleSheet(''' 747 | *{ 748 | background-color: white; 749 | border:0px; 750 | } 751 | ''') 752 | self.titleBar.setStyleSheet(''' 753 | QWidget { 754 | border:0; 755 | background-color: rgba(216, 216, 216, 1); 756 | 757 | color: rgba(113, 118, 121, 1); 758 | } 759 | QLabel{ 760 | font-size: 25px; 761 | font-family: 微软雅黑; 762 | } 763 | ''') 764 | self.table.setStyleSheet(''' 765 | font-size:18px; 766 | color: black; 767 | background-color: white; 768 | font-family: 微软雅黑; 769 | ''') 770 | self.outButton.setStyleSheet(''' 771 | QToolButton{ 772 | 773 | background-color:rgba(131, 175, 155, 1); 774 | color: white; 775 | font-size: 25px; 776 | font-family: 微软雅黑; 777 | } 778 | ''') 779 | 780 | 781 | class Detial(QWidget): 782 | def __init__(self, stu_mes): 783 | super().__init__() 784 | self.stu_mes = func.get_student_info(stu_mes['sno']) 785 | 786 | # 学号输入框 787 | account = QLabel() 788 | account.setText('学号') 789 | self.accountInput = QLineEdit() 790 | self.accountInput.setFixedSize(1250, 40) 791 | self.accountInput.setText(self.stu_mes['sno']) 792 | self.accountInput.setTextMargins(5, 5, 5, 5) 793 | self.accountInput.setEnabled(False) 794 | accountLayout = QHBoxLayout() 795 | accountLayout.addStretch() 796 | accountLayout.addWidget(account) 797 | accountLayout.addWidget(self.accountInput) 798 | accountLayout.addStretch() 799 | 800 | # 姓名输入框 801 | name = QLabel() 802 | name.setText('姓名') 803 | self.nameInput = QLineEdit() 804 | self.nameInput.setFixedSize(1250, 40) 805 | self.nameInput.setText(self.stu_mes['sname']) 806 | self.nameInput.setTextMargins(5, 5, 5, 5) 807 | self.nameInput.setEnabled(False) 808 | nameLayout = QHBoxLayout() 809 | nameLayout.addStretch() 810 | nameLayout.addWidget(name) 811 | nameLayout.addWidget(self.nameInput) 812 | nameLayout.addStretch() 813 | 814 | # 密码 815 | password = QLabel() 816 | password.setText('密码') 817 | self.passwordInput = QLineEdit() 818 | self.passwordInput.setFixedSize(1250, 40) 819 | self.passwordInput.setText('******') 820 | self.passwordInput.setEchoMode(QLineEdit.Password) 821 | self.passwordInput.setTextMargins(5, 5, 5, 5) 822 | self.passwordInput.setEnabled(False) 823 | passwordLayout = QHBoxLayout() 824 | passwordLayout.addStretch() 825 | passwordLayout.addWidget(password) 826 | passwordLayout.addWidget(self.passwordInput) 827 | passwordLayout.addStretch() 828 | 829 | # 重复密码 830 | repPassword = QLabel() 831 | repPassword.setText('重复密码') 832 | self.repPasswordInput = QLineEdit() 833 | self.repPasswordInput.setFixedSize(1250, 40) 834 | self.repPasswordInput.setText('******') 835 | self.repPasswordInput.setEchoMode(QLineEdit.Password) 836 | self.repPasswordInput.setTextMargins(5, 5, 5, 5) 837 | self.repPasswordInput.setEnabled(False) 838 | repPasswordLayout = QHBoxLayout() 839 | repPasswordLayout.addStretch() 840 | repPasswordLayout.addWidget(repPassword) 841 | repPasswordLayout.addWidget(self.repPasswordInput) 842 | repPasswordLayout.addStretch() 843 | 844 | # 最大借书数 845 | maxNum = QLabel() 846 | maxNum.setText('最大借书数') 847 | self.maxNumInput = QLineEdit() 848 | self.maxNumInput.setFixedSize(1250, 40) 849 | self.maxNumInput.setText(str(self.stu_mes['max_book'])) 850 | self.maxNumInput.setTextMargins(5, 5, 5, 5) 851 | self.maxNumInput.setEnabled(False) 852 | maxNumLayout = QHBoxLayout() 853 | maxNumLayout.addStretch() 854 | maxNumLayout.addWidget(maxNum) 855 | maxNumLayout.addWidget(self.maxNumInput) 856 | maxNumLayout.addStretch() 857 | 858 | # 学院 859 | dept = QLabel() 860 | dept.setText('学院') 861 | self.deptInput = QLineEdit() 862 | self.deptInput.setFixedSize(1250, 40) 863 | self.deptInput.setText(self.stu_mes['dept']) 864 | self.deptInput.setTextMargins(5, 5, 5, 5) 865 | self.deptInput.setEnabled(False) 866 | deptLayout = QHBoxLayout() 867 | deptLayout.addStretch() 868 | deptLayout.addWidget(dept) 869 | deptLayout.addWidget(self.deptInput) 870 | deptLayout.addStretch() 871 | 872 | # 专业 873 | major = QLabel() 874 | major.setText('专业') 875 | self.majorInput = QLineEdit() 876 | self.majorInput.setFixedSize(1250, 40) 877 | self.majorInput.setText(self.stu_mes['majority']) 878 | self.majorInput.setTextMargins(5, 5, 5, 5) 879 | self.majorInput.setEnabled(False) 880 | majorLayout = QHBoxLayout() 881 | majorLayout.addStretch() 882 | majorLayout.addWidget(major) 883 | majorLayout.addWidget(self.majorInput) 884 | majorLayout.addStretch() 885 | 886 | # 保存 887 | self.save = QToolButton() 888 | self.save.setText('保存') 889 | self.save.setFixedSize(100, 40) 890 | self.save.setEnabled(False) 891 | self.save.clicked.connect(self.saveFunction) 892 | 893 | # 修改 894 | self.modify = QToolButton() 895 | self.modify.setText('修改') 896 | self.modify.setFixedSize(100, 40) 897 | self.modify.clicked.connect(self.modifyFunction) 898 | 899 | btnLayout = QHBoxLayout() 900 | btnLayout.addStretch() 901 | btnLayout.addWidget(self.modify) 902 | btnLayout.addWidget(self.save) 903 | btnLayout.addStretch() 904 | 905 | self.bodyLayout = QVBoxLayout() 906 | self.bodyLayout.addLayout(accountLayout) 907 | self.bodyLayout.addLayout(nameLayout) 908 | self.bodyLayout.addLayout(passwordLayout) 909 | self.bodyLayout.addLayout(repPasswordLayout) 910 | self.bodyLayout.addLayout(deptLayout) 911 | self.bodyLayout.addLayout(majorLayout) 912 | self.bodyLayout.addLayout(maxNumLayout) 913 | self.bodyLayout.addLayout(btnLayout) 914 | self.bodyLayout.addStretch() 915 | self.setLayout(self.bodyLayout) 916 | self.initUI() 917 | 918 | def saveFunction(self): 919 | if self.passwordInput.text() != self.repPasswordInput.text(): 920 | print('密码不一致') 921 | return 922 | if not self.maxNumInput.text().isalnum(): 923 | print('最大数量输入错误') 924 | return 925 | if self.passwordInput.text() != '******': 926 | self.stu_mes['password'] = func.encrypt(self.passwordInput.text()) 927 | self.stu_mes['sname'] = self.nameInput.text() 928 | self.stu_mes['dept'] = self.deptInput.text() 929 | self.stu_mes['majority'] = self.majorInput.text() 930 | self.stu_mes['max_book'] = int(self.maxNumInput.text()) 931 | if not func.update_student(self.stu_mes): 932 | print('更新失败') 933 | return 934 | self.save.setEnabled(False) 935 | self.nameInput.setEnabled(False) 936 | self.passwordInput.setEnabled(False) 937 | self.repPasswordInput.setEnabled(False) 938 | self.deptInput.setEnabled(False) 939 | self.majorInput.setEnabled(False) 940 | self.maxNumInput.setEnabled(False) 941 | self.setMyStyle() 942 | 943 | def modifyFunction(self): 944 | self.save.setEnabled(True) 945 | self.nameInput.setEnabled(True) 946 | self.passwordInput.setEnabled(True) 947 | self.repPasswordInput.setEnabled(True) 948 | self.deptInput.setEnabled(True) 949 | self.majorInput.setEnabled(True) 950 | self.maxNumInput.setEnabled(True) 951 | self.setStyleSheet(''' 952 | QWidget{ 953 | background-color: white; 954 | } 955 | QLabel{ 956 | font-size: 20px; 957 | font-family: 微软雅黑; 958 | } 959 | QLineEdit{ 960 | border: 1px solid rgba(229, 229, 229, 1); 961 | 962 | color: black; 963 | } 964 | QToolButton{ 965 | 966 | background-color:rgba(52, 118, 176, 1); 967 | color: white; 968 | font-size: 25px; 969 | font-family: 微软雅黑; 970 | } 971 | ''') 972 | self.save.setStyleSheet(''' 973 | *{ 974 | background-color:rgba(52, 118, 176, 1); 975 | } 976 | ''') 977 | 978 | def initUI(self): 979 | self.setFixedSize(550, 600) 980 | self.setMyStyle() 981 | 982 | def setMyStyle(self): 983 | self.setStyleSheet(''' 984 | QWidget{ 985 | background-color: white; 986 | } 987 | QLabel{ 988 | font-size: 20px; 989 | font-family: 微软雅黑; 990 | } 991 | QLineEdit{ 992 | border: 1px solid rgba(229, 229, 229, 1); 993 | 994 | color: grey; 995 | } 996 | QToolButton{ 997 | 998 | background-color:rgba(52, 118, 176, 1); 999 | color: white; 1000 | font-size: 25px; 1001 | font-family: 微软雅黑; 1002 | } 1003 | ''') 1004 | self.save.setStyleSheet(''' 1005 | *{ 1006 | background-color: gray; 1007 | } 1008 | ''') 1009 | 1010 | 1011 | if __name__ == '__main__': 1012 | app = QApplication(sys.argv) 1013 | user_message = { 1014 | 'sno': '1', 1015 | 'sname': '1', 1016 | 'dept': '1', 1017 | 'majority': '1', 1018 | 'max_book': 5 1019 | } 1020 | ex = StudentPage(user_message) 1021 | ex.show() 1022 | sys.exit(app.exec_()) 1023 | -------------------------------------------------------------------------------- /student_information.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PyQt5.QtWidgets import ( 3 | QApplication, QVBoxLayout, QLabel, QLineEdit, QToolButton, QGroupBox, QMessageBox) 4 | from PyQt5.QtCore import pyqtSignal 5 | from PyQt5.QtGui import QIcon 6 | import func 7 | # import database 8 | 9 | 10 | class StudentInfo(QGroupBox): 11 | ''' 12 | 编辑书本信息的界面 13 | 传入{ 14 | 'sno': str, 15 | 'sname': str, 16 | 'dept': str, 17 | 'majority': str, 18 | 'max_book': int 19 | } 20 | 返回{ 21 | 'sno': str, 22 | 'sname': str, 23 | 'password': str, 24 | 'dept': str, 25 | 'majority': str, 26 | 'max_book': int 27 | } 28 | ''' 29 | after_close = pyqtSignal(dict) 30 | 31 | def __init__(self, stu_info: dict): 32 | super().__init__() 33 | self.stu_info = stu_info 34 | 35 | self.title = QLabel() 36 | self.title.setText('学生信息') 37 | 38 | self.subTitle = QLabel() 39 | self.subTitle.setText('编辑学生信息') 40 | 41 | # 学号输入框 42 | self.SIDInput = QLineEdit() 43 | self.SIDInput.setFixedSize(400, 40) 44 | self.SIDInput.setText(self.stu_info['sno']) 45 | self.SIDInput.initText = '请输入学号' 46 | self.SIDInput.setEnabled(False) 47 | 48 | # 姓名输入框 49 | self.nameInput = QLineEdit() 50 | self.nameInput.setFixedSize(400, 40) 51 | self.nameInput.setText(self.stu_info['sname']) 52 | self.nameInput.initText = '请输入姓名' 53 | self.nameInput.setTextMargins(5, 5, 5, 5) 54 | self.nameInput.mousePressEvent = lambda x: self.inputClick(self.nameInput) 55 | 56 | # 密码 57 | self.passwordInput = QLineEdit() 58 | self.passwordInput.setFixedSize(400, 40) 59 | self.passwordInput.setText('请输入密码') 60 | self.passwordInput.initText = '请输入密码' 61 | self.passwordInput.setTextMargins(5, 5, 5, 5) 62 | self.passwordInput.mousePressEvent = lambda x: self.inputClick(self.passwordInput) 63 | 64 | # 重复密码 65 | self.repPasswordInput = QLineEdit() 66 | self.repPasswordInput.setFixedSize(400, 40) 67 | self.repPasswordInput.setText('请重复输入密码') 68 | self.repPasswordInput.initText = '请重复输入密码' 69 | self.repPasswordInput.setTextMargins(5, 5, 5, 5) 70 | self.repPasswordInput.mousePressEvent = lambda x: self.inputClick(self.repPasswordInput) 71 | 72 | # 最大借书数 73 | self.maxNumInput = QLineEdit() 74 | self.maxNumInput.setFixedSize(400, 40) 75 | self.maxNumInput.setText(str(self.stu_info['max_book'])) 76 | self.maxNumInput.initText = '请输入最大借书数' 77 | self.maxNumInput.setTextMargins(5, 5, 5, 5) 78 | self.maxNumInput.mousePressEvent = lambda x: self.inputClick(self.maxNumInput) 79 | 80 | # 学院 81 | self.deptInput = QLineEdit() 82 | self.deptInput.setFixedSize(400, 40) 83 | self.deptInput.setText(self.stu_info['dept']) 84 | self.deptInput.initText = '请输入所在学院' 85 | self.deptInput.setTextMargins(5, 5, 5, 5) 86 | self.deptInput.mousePressEvent = lambda x: self.inputClick(self.deptInput) 87 | 88 | # 专业 89 | self.majorInput = QLineEdit() 90 | self.majorInput.setFixedSize(400, 40) 91 | self.majorInput.setText(self.stu_info['majority']) 92 | self.majorInput.initText = '请输入所在专业' 93 | self.majorInput.setTextMargins(5, 5, 5, 5) 94 | self.majorInput.mousePressEvent = lambda x: self.inputClick(self.majorInput) 95 | 96 | # 提交 97 | self.submit = QToolButton() 98 | self.submit.setText('提交') 99 | self.submit.setFixedSize(400, 40) 100 | self.submit.clicked.connect(self.submitFunction) 101 | 102 | # 退出 103 | self.back = QToolButton() 104 | self.back.setText('退出') 105 | self.back.setFixedSize(400, 40) 106 | self.back.clicked.connect(self.close) 107 | 108 | self.btnList = [ 109 | self.SIDInput, 110 | self.nameInput, 111 | self.passwordInput, 112 | self.repPasswordInput, 113 | self.deptInput, 114 | self.majorInput, 115 | self.maxNumInput 116 | ] 117 | 118 | self.bodyLayout = QVBoxLayout() 119 | self.bodyLayout.addWidget(self.title) 120 | self.bodyLayout.addWidget(self.subTitle) 121 | for i in self.btnList: 122 | self.bodyLayout.addWidget(i) 123 | self.bodyLayout.addWidget(self.submit) 124 | self.bodyLayout.addWidget(self.back) 125 | 126 | self.setLayout(self.bodyLayout) 127 | self.initUI() 128 | 129 | def inputClick(self, e): 130 | for i in range(2, 9): 131 | item = self.bodyLayout.itemAt(i).widget() 132 | if item.text() == '': 133 | item.setText(item.initText) 134 | if item is self.passwordInput or item is self.repPasswordInput: 135 | item.setEchoMode(QLineEdit.Normal) 136 | 137 | if e.text() == e.initText: 138 | e.setText('') 139 | if e is self.passwordInput or e is self.repPasswordInput: 140 | e.setEchoMode(QLineEdit.Password) 141 | 142 | def submitFunction(self): 143 | if not self.maxNumInput.text().isalnum(): 144 | print('最大数量输入错误') 145 | return 146 | if self.passwordInput.text() != self.passwordInput.initText: 147 | if self.passwordInput.text() != self.repPasswordInput.text(): 148 | msgBox = QMessageBox(QMessageBox.Warning, "错误!", '两次输入密码不一致!', QMessageBox.NoButton, self) 149 | msgBox.addButton("确认", QMessageBox.AcceptRole) 150 | msgBox.exec_() 151 | return 152 | self.stu_info['password'] = func.encrypt(self.passwordInput.text()) 153 | self.stu_info['sname'] = self.nameInput.text() 154 | self.stu_info['dept'] = self.deptInput.text() 155 | self.stu_info['majority'] = self.majorInput.text() 156 | self.stu_info['max_book'] = int(self.maxNumInput.text()) 157 | self.close() 158 | self.after_close.emit(self.stu_info) 159 | 160 | def initUI(self): 161 | self.setFixedSize(422, 500) 162 | self.setWindowTitle('编辑学生信息') 163 | self.setWindowIcon(QIcon('icon/person.png')) 164 | self.setMyStyle() 165 | 166 | def setMyStyle(self): 167 | self.setStyleSheet(''' 168 | QWidget{ 169 | background-color: white; 170 | } 171 | QLineEdit{ 172 | border:0px; 173 | border-bottom: 1px solid rgba(229, 229, 229, 1); 174 | color: grey; 175 | } 176 | QToolButton{ 177 | border: 0px; 178 | background-color:rgba(52, 118, 176, 1); 179 | color: white; 180 | font-size: 25px; 181 | font-family: 微软雅黑; 182 | } 183 | QGroupBox{ 184 | border: 1px solid rgba(229, 229, 229, 1); 185 | border-radius: 5px; 186 | } 187 | ''') 188 | self.title.setStyleSheet(''' 189 | *{ 190 | color: rgba(113, 118, 121, 1); 191 | font-size: 30px; 192 | font-family: 微软雅黑; 193 | } 194 | ''') 195 | self.subTitle.setStyleSheet(''' 196 | *{ 197 | color: rgba(184, 184, 184, 1); 198 | } 199 | ''') 200 | 201 | 202 | if __name__ == '__main__': 203 | stu_msg = temp = { 204 | 'sno': '201602', 205 | 'sname': '小王', 206 | 'dept': '数学与信息科学学院', 207 | 'majority': 'SE', 208 | 'max_book': 5 209 | } 210 | app = QApplication(sys.argv) 211 | ex = StudentInfo(stu_msg) 212 | ex.show() 213 | sys.exit(app.exec_()) 214 | -------------------------------------------------------------------------------- /演示视频.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BecauseY/Library-Management-System/fdaed1165517f11728ff6d86a5c8c4c6e8553726/演示视频.mp4 -------------------------------------------------------------------------------- /说明.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BecauseY/Library-Management-System/fdaed1165517f11728ff6d86a5c8c4c6e8553726/说明.pdf --------------------------------------------------------------------------------