diff --git a/Assignments/Assignment5/source/主页.png b/Assignments/Assignment5/source/主页.png
new file mode 100644
index 0000000..35b447c
Binary files /dev/null and b/Assignments/Assignment5/source/主页.png differ
diff --git a/Assignments/Assignment5/source/作业5_21281280_柯劲帆.md b/Assignments/Assignment5/source/作业5_21281280_柯劲帆.md
new file mode 100644
index 0000000..fbcb93e
--- /dev/null
+++ b/Assignments/Assignment5/source/作业5_21281280_柯劲帆.md
@@ -0,0 +1,527 @@
+
课程作业
+
+
+
课程名称:数据库系统原理
+
作业次数:作业#5
+
学号:21281280
+
姓名:柯劲帆
+
班级:物联网2101班
+
指导老师:郝爽
+
修改日期:2024年5月12日
+
+
+
+
+---
+
+[TOC]
+
+# 1. 实验案例描述
+
+本实验我实现的案例是12306系统的用户注册、修改账号信息。
+
+注册需要用户填写:
+
+- **用户名**:设置成功后不可修改
+- **登陆密码**:6-20位字母数字或符号
+- **确认密码**:须与登陆密码一致
+- **姓名**
+- **身份证号**:需满足身份证号格式
+- **手机号码**:需满足手机号码格式
+
+支持**注销账号**及修改:
+
+- **登陆密码**
+- **手机号码**
+
+
+
+# 2. 实验过程
+
+## 2.1. 项目架构设计
+
+对于前端,我使用 `B/S架构` 和原生的 `HTML5` + `CSS` + `JavaScript` 代码实现。
+
+对于后端,我使用 `Python` + `Flask`作为Web服务器和应用服务器,并且调用相同服务器中的 `MySQL` 实现任务。
+
+## 2.2. 项目实现
+
+对于前后端的代码实现,请见附件。
+
+配置环境方面,我新建了 `conda` 环境,并使用 `pip` 安装了项目所需依赖,包括 `Flask` 、`PyMySQL` 等。依赖列表我已导出至附件中的 `requirements.txt`。
+
+另外,为了快速启动服务,我编写了启动脚本 `run.sh`,见附件。
+
+最终目录树如下:
+
+```sh
+$ tree
+.
+├── db.sql
+├── init_db.py
+├── main.py
+├── requirements.txt
+├── run.sh
+├── static
+│ ├── css
+│ │ └── style.css
+│ └── js
+│ ├── checkInfo.js
+│ └── modify.js
+└── templates
+ ├── index.html
+ ├── modify.html
+ └── signup.html
+
+4 directories, 11 files
+```
+
+
+
+# 3. 实验结果
+
+## 3.1. 前端
+
+本实现实现了 3 个前端页面:
+
+- 主页
+- 注册
+- 修改账号信息
+
+### 3.1.1. 主页
+
+主页主要提供 *注册* 和 *修改账号信息* 两个超链接的跳转。
+
+
+
+### 3.1.2. 注册页面
+
+
+
+该页面将对输入进行如下检查:
+
+- **检查身份证格式**
+
+ ```javascript
+ checkInfo.checkCardCode = function() {
+ let cardCode = document.getElementById('cardCode').value
+ let regexCardCode = /^([1-6][1-9]|50)\d{4}(18|19|20)\d{2}((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
+ if(!regexCardCode.test(cardCode)) {
+ alert('身份证号格式有误')
+ return false
+ }
+ return true
+ }
+ ```
+
+ 如果格式不正确,将弹出警告:
+
+
+
+- **检查手机号格式**
+
+ ```javascript
+ checkInfo.checkMobileNo = function() {
+ let mobileNo = document.getElementById('mobileNo').value
+ let regexMobileNo = /^1[3-9]\d{9}$/
+ if (!regexMobileNo.test(mobileNo)) {
+ alert('手机号格式有误')
+ return false
+ }
+ return true
+ }
+ ```
+
+ 如果格式不正确,将弹出警告:
+
+
+
+- **检查密码格式**
+
+ 如果格式不正确,将弹出警告:
+
+
+
+- **检查确认密码是否与第一次输入的密码匹配**
+
+ ```javascript
+ checkInfo.checkPassword = function() {
+ let password = document.getElementById('password')
+ let regexPassword = /^[A-Za-z0-9\W_]{6,20}$/
+ if (!regexPassword.test(password.value)) {
+ alert("密码须为长度为6-20位字母、数字或符号")
+ return false
+ }
+ let confirmPassword = document.getElementById('confirmPassword')
+ if (password.value !== confirmPassword.value) {
+ alert("两次输入的密码不一致")
+ return false
+ }
+ return true
+ }
+ ```
+
+ 如果不匹配,将弹出警告:
+
+
+
+页面会对密码使用 `md5码` 加密传输至后端(效果见 `3.2.1.2. 注册页面请求处理函数` 部分的数据库查询结果截图)。
+
+```javascript
+document.getElementById('encryptedPassword').value = md5(
+ document.getElementById('password').value
+)
+```
+
+注册成功后,页面跳转回主页,并弹出注册成功通知:
+
+
+
+### 3.1.3. 修改账户信息页面
+
+修改账户信息页面可以选择三种修改方式,通过点击下拉框即可选择:
+
+- 删除账户:
+
+
+
+- 修改密码:
+
+
+
+- 修改手机号码:
+
+
+
+这里使用了 Javasript 代码操作列表的 `display` 属性,从而控制列表项的显示:
+
+```javascript
+modify.showModifyPassword = function() {
+ let modifyType = document.getElementById('modifyType').value
+ let info = {
+ modifyPasswordLis: document.getElementsByClassName('modifyPassword'),
+ modifymobileNoLis: document.getElementsByClassName('modifymobileNo'),
+ }
+ // 遍历隐藏所有元素
+ for (let key in info) {
+ let elements = info[key];
+ for (let item of elements) {
+ item.style.display = 'none'; // 确保所有相关元素被隐藏
+ }
+ }
+ // 根据 modifyType 显示相关元素
+ if (modifyType === "2") {
+ for (let item of info.modifyPasswordLis) {
+ item.style.display = 'block';
+ }
+ } else if (modifyType === "3") {
+ for (let item of info.modifymobileNoLis) {
+ item.style.display = 'block';
+ }
+ }
+}
+```
+
+上述修改都会在后端检查证件号码和登录密码是否匹配(见后端部分实验结果)。
+
+修改密码将会做密码二次匹配检查、密码格式检查,修改手机号将会做手机号格式化检查。弹出的提示和注册页面提示一样,这里不作赘述。
+
+## 3.2. 后端
+
+### 3.2.1. Flask 框架
+
+Flask 框架负责作为 Web 服务器、应用服务器的实现方式。
+
+我在代码代码中实现了一个函数,用于连接数据库,以便后续获取 cursor 以及关闭连接。
+
+```python
+def get_db():
+ return pymysql.connect(
+ host='localhost', user='kejingfan',
+ password='PASSWORD', database='TESTDB'
+ )
+```
+
+对于每一个前端页面,都需要在 Flask 的调用代码中编写一个函数来处理该页面的 GET / POST 请求。
+
+#### 3.2.1.1. 主页请求处理函数
+
+主页目前只有 GET 请求,因此只需要返回 `index.html` 即可。
+
+```python
+@app.route("/")
+def index():
+ return render_template("index.html")
+```
+
+#### 3.2.1.2. 注册页面请求处理函数
+
+注册页面中,收到 GET 请求,返回 `signup.html` ;
+
+```python
+@app.route("/signup.html", methods=('GET', 'POST'))
+def signup():
+ if request.method == 'GET':
+ return render_template('signup.html')
+```
+
+收到 POST 请求,需要处理返回的表单。表单一共有 4 项:`'cardCode', 'name', 'mobileNo', 'encryptedPassword'` 。
+
+```python
+if request.method == 'POST':
+ id = request.form['cardCode']
+ name = request.form['name']
+ phone_number = request.form['mobileNo']
+ password = request.form['encryptedPassword']
+
+ db = get_db()
+ cursor = db.cursor()
+```
+
+首先使用身份证号 `'cardCode'` 项,对数据库进行查询,检查用户是否正在重复注册。
+
+若重复注册,弹出:
+
+
+
+```python
+sql = """
+SELECT COUNT(*) FROM passengers \
+WHERE ID = %s;
+"""
+try:
+ cursor.execute(sql, (id,))
+ id_exist = cursor.fetchall()[0][0]
+except Exception as e:
+ flash("数据库异常,查询失败")
+ print(e)
+ return redirect(url_for('signup'))
+if (id_exist != 0):
+ flash("您已注册过,请勿重复注册")
+ db.close()
+ return redirect(url_for('index'))
+```
+
+如果没有检索到已注册信息,则插入注册信息:
+
+```python
+sql = '''
+INSERT INTO passengers (ID, `Name`, Phone_number, `Password`) \
+VALUES (%s, %s, %s, %s); \
+'''
+try:
+ cursor.execute(sql, (id, name, phone_number, password))
+ db.commit()
+ flash("注册成功")
+except Exception as e:
+ db.rollback()
+ print(e)
+ flash("数据库异常,注册失败")
+db.close()
+return redirect(url_for('index'))
+```
+
+此时数据库可以查询到:
+
+
+
+#### 3.2.1.3. 修改账户信息页面请求处理函数
+
+修改账户信息页面中,收到 GET 请求,返回 `modify.html` ;
+
+```python
+@app.route("/modify.html", methods=('GET', 'POST'))
+def modify():
+ if request.method == 'GET':
+ return render_template('modify.html')
+```
+
+收到 POST 请求,需要处理返回的表单。表单一共有 5 项:
+
+`'cardCode', 'encryptedPassword', 'modifyType', ''encryptedNewPassword'', 'mobileNo'` 。
+
+首先需要验证用户是否存在,且密码正确。这里需要做两个查询操作,分别查询 `ID` 的数量以及 `Password` 的值。
+
+将验证过程封装成函数:
+
+```python
+def verify_user(cursor:Cursor, id:str, password:str) -> str:
+ # 检查已有用户
+ sql = """
+ SELECT COUNT(*) FROM passengers \
+ WHERE ID = %s;
+ """
+ try:
+ cursor.execute(sql, (id,))
+ id_exist = cursor.fetchall()[0][0]
+ except Exception as e:
+ flash("数据库异常,查询失败")
+ print(e)
+ return redirect(url_for('signup'))
+ if (id_exist == 0):
+ return "NO_USER"
+
+ # 检查密码
+ sql = """
+ SELECT `Password` FROM passengers \
+ WHERE ID = %s;
+ """
+ try:
+ cursor.execute(sql, (id,))
+ record_password = cursor.fetchall()[0][0]
+ except Exception as e:
+ flash("数据库异常,查询失败")
+ print(e)
+ return redirect(url_for('modify'))
+ if (record_password != password):
+ return "WRONG_PASSWORD"
+
+ return "USER_VERIFIED"
+```
+
+判断验证结果,作出响应:
+
+```python
+id = request.form['cardCode']
+password = request.form['encryptedPassword']
+db = get_db()
+cursor = db.cursor()
+
+verify_info = verify_user(cursor, id, password)
+if (verify_info == "NO_USER"):
+ flash("您未注册过,无法修改账号")
+ db.close()
+ return redirect(url_for('signup'))
+elif (verify_info == "WRONG_PASSWORD"):
+ flash("密码错误")
+ db.close()
+ return redirect(url_for('modify'))
+```
+
+如果用户没有注册:
+
+
+
+如果密码错误:
+
+
+
+验证通过后,需要根据请求对数据库进行更改。
+
+编写了一个类专门用来处理修改内容、数据库修改指令和提示信息:
+
+```python
+class ModifyInfo:
+ def __init__(self, form:Dict[str, str]):
+ self.id = form['cardCode']
+ modifyType = form['modifyType']
+ self.new_password = form['encryptedNewPassword']
+ self.phone_number = form['mobileNo']
+ modifyType2command = {
+ '1':'delete account',
+ '2':'modify Password',
+ '3':'modify Phone_Number'
+ }
+ self.sql_dict = {
+ 'delete account': 'DELETE FROM passengers WHERE ID = %s;',
+ 'modify Password': 'UPDATE passengers SET `Password` = %s WHERE ID = %s;',
+ 'modify Phone_Number': 'UPDATE passengers SET Phone_number = %s WHERE ID = %s;'
+ }
+ self.sql_args_dict = {
+ 'delete account': (self.id,),
+ 'modify Password': (self.new_password, self.id),
+ 'modify Phone_Number': (self.phone_number, self.id)
+ }
+ self.ok_message_dict = {
+ 'delete account': "删除账户成功",
+ 'modify Password': "修改密码成功",
+ 'modify Phone_Number': "修改手机号成功"
+ }
+ self.fail_message_dict = {
+ 'delete account': "数据库异常,删除账户失败",
+ 'modify Password': "数据库异常,修改密码失败",
+ 'modify Phone_Number': "数据库异常,修改手机号失败"
+ }
+ self.command = modifyType2command[modifyType]
+ def get_sql(self):
+ return self.sql_dict[self.command]
+ def get_args(self):
+ return self.sql_args_dict[self.command]
+ def get_ok_message(self):
+ return self.ok_message_dict[self.command]
+ def get_fail_message(self):
+ return self.fail_message_dict[self.command]
+```
+
+在处理函数中创建该类对象,并调用该对象方法获取操作参数:
+
+```python
+modifyInfo = ModifyInfo(request.form)
+try:
+ cursor.execute(modifyInfo.get_sql(), modifyInfo.get_args())
+ db.commit()
+ flash(modifyInfo.get_ok_message())
+except Exception as e:
+ db.rollback()
+ print(e)
+ flash(modifyInfo.get_fail_message())
+db.close()
+return redirect(url_for('index'))
+```
+
+修改密码成功后:
+
+
+
+
+
+修改手机号成功后:
+
+
+
+
+
+删除账号成功后:
+
+
+
+
+
+### 3.2.2. 数据库服务器
+
+本实验使用 MySQL 作为数据库。
+
+编写了一个 SQL 脚本和一个 Python 文件用于初始化测试数据库:
+
+```mysql
+DROP TABLE IF EXISTS passengers;
+
+CREATE TABLE passengers (
+ ID BIGINT PRIMARY KEY,
+ `Name` VARCHAR (255) NOT NULL,
+ Phone_number BIGINT UNIQUE NOT NULL,
+ `Password` VARCHAR (255) NOT NULL,
+ CHECK (ID REGEXP '^\\d{18}$'),
+ CHECK (Phone_number REGEXP '^\\d{11}$')
+);
+```
+
+```python
+import pymysql
+
+db = pymysql.connect(
+ host='localhost', user='kejingfan',
+ password='PASSWORD', database='TESTDB'
+)
+
+cursor = db.cursor()
+
+with open('db.sql', 'r') as f:
+ sql_commands = f.read().split(';')
+ for command in sql_commands:
+ if command.strip(): # 确保不执行空命令
+ cursor.execute(command)
+
+db.close()
+```
+
diff --git a/Assignments/Assignment5/source/修改密码界面.png b/Assignments/Assignment5/source/修改密码界面.png
new file mode 100644
index 0000000..da559d6
Binary files /dev/null and b/Assignments/Assignment5/source/修改密码界面.png differ
diff --git a/Assignments/Assignment5/source/修改手机号界面.png b/Assignments/Assignment5/source/修改手机号界面.png
new file mode 100644
index 0000000..8f54f9d
Binary files /dev/null and b/Assignments/Assignment5/source/修改手机号界面.png differ
diff --git a/Assignments/Assignment5/source/删除账号成功.png b/Assignments/Assignment5/source/删除账号成功.png
new file mode 100644
index 0000000..a93e021
Binary files /dev/null and b/Assignments/Assignment5/source/删除账号成功.png differ
diff --git a/Assignments/Assignment5/source/删除账户界面.png b/Assignments/Assignment5/source/删除账户界面.png
new file mode 100644
index 0000000..6caf9b1
Binary files /dev/null and b/Assignments/Assignment5/source/删除账户界面.png differ
diff --git a/Assignments/Assignment5/source/密码不匹配警告.png b/Assignments/Assignment5/source/密码不匹配警告.png
new file mode 100644
index 0000000..6b08ba4
Binary files /dev/null and b/Assignments/Assignment5/source/密码不匹配警告.png differ
diff --git a/Assignments/Assignment5/source/密码修改成功.png b/Assignments/Assignment5/source/密码修改成功.png
new file mode 100644
index 0000000..f398791
Binary files /dev/null and b/Assignments/Assignment5/source/密码修改成功.png differ
diff --git a/Assignments/Assignment5/source/密码格式警告.png b/Assignments/Assignment5/source/密码格式警告.png
new file mode 100644
index 0000000..e50ad66
Binary files /dev/null and b/Assignments/Assignment5/source/密码格式警告.png differ
diff --git a/Assignments/Assignment5/source/密码错误警告.png b/Assignments/Assignment5/source/密码错误警告.png
new file mode 100644
index 0000000..b4395e2
Binary files /dev/null and b/Assignments/Assignment5/source/密码错误警告.png differ
diff --git a/Assignments/Assignment5/source/手机号修改成功.png b/Assignments/Assignment5/source/手机号修改成功.png
new file mode 100644
index 0000000..cb9e49d
Binary files /dev/null and b/Assignments/Assignment5/source/手机号修改成功.png differ
diff --git a/Assignments/Assignment5/source/手机号格式警告.png b/Assignments/Assignment5/source/手机号格式警告.png
new file mode 100644
index 0000000..c9559a5
Binary files /dev/null and b/Assignments/Assignment5/source/手机号格式警告.png differ
diff --git a/Assignments/Assignment5/source/数据库中密码变化.png b/Assignments/Assignment5/source/数据库中密码变化.png
new file mode 100644
index 0000000..20dd90c
Binary files /dev/null and b/Assignments/Assignment5/source/数据库中密码变化.png differ
diff --git a/Assignments/Assignment5/source/数据库中手机号变化.png b/Assignments/Assignment5/source/数据库中手机号变化.png
new file mode 100644
index 0000000..d814e6a
Binary files /dev/null and b/Assignments/Assignment5/source/数据库中手机号变化.png differ
diff --git a/Assignments/Assignment5/source/数据库中账号信息变化.png b/Assignments/Assignment5/source/数据库中账号信息变化.png
new file mode 100644
index 0000000..d98d78d
Binary files /dev/null and b/Assignments/Assignment5/source/数据库中账号信息变化.png differ
diff --git a/Assignments/Assignment5/source/新建用户后.png b/Assignments/Assignment5/source/新建用户后.png
new file mode 100644
index 0000000..8d763d8
Binary files /dev/null and b/Assignments/Assignment5/source/新建用户后.png differ
diff --git a/Assignments/Assignment5/source/未注册警告.png b/Assignments/Assignment5/source/未注册警告.png
new file mode 100644
index 0000000..3b9ce18
Binary files /dev/null and b/Assignments/Assignment5/source/未注册警告.png differ
diff --git a/Assignments/Assignment5/source/注册成功.png b/Assignments/Assignment5/source/注册成功.png
new file mode 100644
index 0000000..251987e
Binary files /dev/null and b/Assignments/Assignment5/source/注册成功.png differ
diff --git a/Assignments/Assignment5/source/注册页面.png b/Assignments/Assignment5/source/注册页面.png
new file mode 100644
index 0000000..15af18b
Binary files /dev/null and b/Assignments/Assignment5/source/注册页面.png differ
diff --git a/Assignments/Assignment5/source/身份证格式警告.png b/Assignments/Assignment5/source/身份证格式警告.png
new file mode 100644
index 0000000..16b7369
Binary files /dev/null and b/Assignments/Assignment5/source/身份证格式警告.png differ
diff --git a/Assignments/Assignment5/source/重复注册警告.png b/Assignments/Assignment5/source/重复注册警告.png
new file mode 100644
index 0000000..d83f6b3
Binary files /dev/null and b/Assignments/Assignment5/source/重复注册警告.png differ
diff --git a/Assignments/Assignment5/src/db.sql b/Assignments/Assignment5/src/db.sql
new file mode 100644
index 0000000..3a0b4ff
--- /dev/null
+++ b/Assignments/Assignment5/src/db.sql
@@ -0,0 +1,10 @@
+DROP TABLE IF EXISTS passengers;
+
+CREATE TABLE passengers (
+ ID BIGINT PRIMARY KEY,
+ `Name` VARCHAR (255) NOT NULL,
+ Phone_number BIGINT UNIQUE NOT NULL,
+ `Password` VARCHAR (255) NOT NULL,
+ CHECK (ID REGEXP '^\\d{18}$'),
+ CHECK (Phone_number REGEXP '^\\d{11}$')
+);
\ No newline at end of file
diff --git a/Assignments/Assignment5/src/init_db.py b/Assignments/Assignment5/src/init_db.py
new file mode 100644
index 0000000..e3bf6e1
--- /dev/null
+++ b/Assignments/Assignment5/src/init_db.py
@@ -0,0 +1,17 @@
+import pymysql
+
+db = pymysql.connect(
+ host='localhost', user='kejingfan',
+ password='PASSWORD', database='TESTDB'
+)
+
+cursor = db.cursor()
+
+with open('db.sql', 'r') as f:
+ sql_commands = f.read().split(';')
+ for command in sql_commands:
+ if command.strip(): # 确保不执行空命令
+ cursor.execute(command)
+
+db.close()
+
diff --git a/Assignments/Assignment5/src/main.py b/Assignments/Assignment5/src/main.py
new file mode 100644
index 0000000..8772cd6
--- /dev/null
+++ b/Assignments/Assignment5/src/main.py
@@ -0,0 +1,179 @@
+from flask import Flask, render_template, request, flash, redirect, url_for
+import pymysql
+from pymysql.cursors import Cursor
+import os
+from typing import Dict
+
+
+app = Flask(__name__)
+app.secret_key = os.environ.get('SECRET_KEY', 'OPTIONALSECRETKEY')
+
+
+def get_db():
+ return pymysql.connect(
+ host='localhost', user='kejingfan',
+ password='PASSWORD', database='TESTDB'
+ )
+
+
+@app.route("/")
+def index():
+ return render_template("index.html")
+
+
+@app.route("/signup.html", methods=('GET', 'POST'))
+def signup():
+ if request.method == 'GET':
+ return render_template('signup.html')
+
+ if request.method == 'POST':
+ id = request.form['cardCode']
+ name = request.form['name']
+ phone_number = request.form['mobileNo']
+ password = request.form['encryptedPassword']
+
+ db = get_db()
+ cursor = db.cursor()
+
+ # 检查已有用户
+ sql = """
+ SELECT COUNT(*) FROM passengers \
+ WHERE ID = %s;
+ """
+ try:
+ cursor.execute(sql, (id,))
+ id_exist = cursor.fetchall()[0][0]
+ except Exception as e:
+ flash("数据库异常,查询失败")
+ print(e)
+ return redirect(url_for('signup'))
+ if (id_exist != 0):
+ flash("您已注册过,请勿重复注册")
+ db.close()
+ return redirect(url_for('index'))
+
+ # 插入
+ sql = '''
+ INSERT INTO passengers (ID, `Name`, Phone_number, `Password`) \
+ VALUES (%s, %s, %s, %s); \
+ '''
+ try:
+ cursor.execute(sql, (id, name, phone_number, password))
+ db.commit()
+ flash("注册成功")
+ except Exception as e:
+ db.rollback()
+ print(e)
+ flash("数据库异常,注册失败")
+ db.close()
+ return redirect(url_for('index'))
+
+
+def verify_user(cursor:Cursor, id:str, password:str) -> str:
+ # 检查已有用户
+ sql = """
+ SELECT COUNT(*) FROM passengers \
+ WHERE ID = %s;
+ """
+ try:
+ cursor.execute(sql, (id,))
+ id_exist = cursor.fetchall()[0][0]
+ except Exception as e:
+ flash("数据库异常,查询失败")
+ print(e)
+ return redirect(url_for('signup'))
+ if (id_exist == 0):
+ return "NO_USER"
+
+ # 检查密码
+ sql = """
+ SELECT `Password` FROM passengers \
+ WHERE ID = %s;
+ """
+ try:
+ cursor.execute(sql, (id,))
+ record_password = cursor.fetchall()[0][0]
+ except Exception as e:
+ flash("数据库异常,查询失败")
+ print(e)
+ return redirect(url_for('modify'))
+ if (record_password != password):
+ return "WRONG_PASSWORD"
+
+ return "USER_VERIFIED"
+
+
+class ModifyInfo:
+ def __init__(self, form:Dict[str, str]):
+ self.id = form['cardCode']
+ modifyType = form['modifyType']
+ self.new_password = form['encryptedNewPassword']
+ self.phone_number = form['mobileNo']
+ modifyType2command = {
+ '1':'delete account',
+ '2':'modify Password',
+ '3':'modify Phone_Number'
+ }
+ self.sql_dict = {
+ 'delete account': 'DELETE FROM passengers WHERE ID = %s;',
+ 'modify Password': 'UPDATE passengers SET `Password` = %s WHERE ID = %s;',
+ 'modify Phone_Number': 'UPDATE passengers SET Phone_number = %s WHERE ID = %s;'
+ }
+ self.sql_args_dict = {
+ 'delete account': (self.id,),
+ 'modify Password': (self.new_password, self.id),
+ 'modify Phone_Number': (self.phone_number, self.id)
+ }
+ self.ok_message_dict = {
+ 'delete account': "删除账户成功",
+ 'modify Password': "修改密码成功",
+ 'modify Phone_Number': "修改手机号成功"
+ }
+ self.fail_message_dict = {
+ 'delete account': "数据库异常,删除账户失败",
+ 'modify Password': "数据库异常,修改密码失败",
+ 'modify Phone_Number': "数据库异常,修改手机号失败"
+ }
+ self.command = modifyType2command[modifyType]
+ def get_sql(self):
+ return self.sql_dict[self.command]
+ def get_args(self):
+ return self.sql_args_dict[self.command]
+ def get_ok_message(self):
+ return self.ok_message_dict[self.command]
+ def get_fail_message(self):
+ return self.fail_message_dict[self.command]
+
+
+@app.route("/modify.html", methods=('GET', 'POST'))
+def modify():
+ if request.method == 'GET':
+ return render_template('modify.html')
+
+ if request.method == 'POST':
+ id = request.form['cardCode']
+ password = request.form['encryptedPassword']
+ db = get_db()
+ cursor = db.cursor()
+
+ verify_info = verify_user(cursor, id, password)
+ if (verify_info == "NO_USER"):
+ flash("您未注册过,无法修改账号")
+ db.close()
+ return redirect(url_for('signup'))
+ elif (verify_info == "WRONG_PASSWORD"):
+ flash("密码错误")
+ db.close()
+ return redirect(url_for('modify'))
+
+ modifyInfo = ModifyInfo(request.form)
+ try:
+ cursor.execute(modifyInfo.get_sql(), modifyInfo.get_args())
+ db.commit()
+ flash(modifyInfo.get_ok_message())
+ except Exception as e:
+ db.rollback()
+ print(e)
+ flash(modifyInfo.get_fail_message())
+ db.close()
+ return redirect(url_for('index'))
\ No newline at end of file
diff --git a/Assignments/Assignment5/src/requirements.txt b/Assignments/Assignment5/src/requirements.txt
new file mode 100644
index 0000000..e79ebbc
--- /dev/null
+++ b/Assignments/Assignment5/src/requirements.txt
@@ -0,0 +1,12 @@
+blinker==1.8.1
+cffi==1.16.0
+click==8.1.7
+configparser==7.0.0
+cryptography==42.0.6
+Flask==3.0.3
+itsdangerous==2.2.0
+Jinja2==3.1.3
+MarkupSafe==2.1.5
+pycparser==2.22
+PyMySQL==1.1.0
+Werkzeug==3.0.2
diff --git a/Assignments/Assignment5/src/run.sh b/Assignments/Assignment5/src/run.sh
new file mode 100644
index 0000000..dc861d9
--- /dev/null
+++ b/Assignments/Assignment5/src/run.sh
@@ -0,0 +1 @@
+SECRET_KEY='ILOVEDATABASETECH' FLASK_APP=main FLASK_ENV=development flask run
\ No newline at end of file
diff --git a/Assignments/Assignment5/src/static/css/style.css b/Assignments/Assignment5/src/static/css/style.css
new file mode 100644
index 0000000..34abe50
--- /dev/null
+++ b/Assignments/Assignment5/src/static/css/style.css
@@ -0,0 +1,9 @@
+/* h1, ul, li, a, body {
+ margin: 0;
+ padding: 0;
+ text-decoration: none;
+} */
+
+li {
+ list-style: none;
+}
\ No newline at end of file
diff --git a/Assignments/Assignment5/src/static/js/checkInfo.js b/Assignments/Assignment5/src/static/js/checkInfo.js
new file mode 100644
index 0000000..641c012
--- /dev/null
+++ b/Assignments/Assignment5/src/static/js/checkInfo.js
@@ -0,0 +1,51 @@
+var checkInfo = {}
+
+checkInfo.checkCardCode = function() {
+ let cardCode = document.getElementById('cardCode').value
+ let regexCardCode = /^([1-6][1-9]|50)\d{4}(18|19|20)\d{2}((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
+ if(!regexCardCode.test(cardCode)) {
+ alert('身份证号格式有误')
+ return false
+ }
+ return true
+}
+
+checkInfo.checkMobileNo = function() {
+ let mobileNo = document.getElementById('mobileNo').value
+ let regexMobileNo = /^1[3-9]\d{9}$/
+ if (!regexMobileNo.test(mobileNo)) {
+ alert('手机号格式有误')
+ return false
+ }
+ return true
+}
+
+checkInfo.checkPassword = function() {
+ let password = document.getElementById('password')
+ let regexPassword = /^[A-Za-z0-9\W_]{6,20}$/
+ if (!regexPassword.test(password.value)) {
+ alert("密码须为长度为6-20位字母、数字或符号")
+ return false
+ }
+ let confirmPassword = document.getElementById('confirmPassword')
+ if (password.value !== confirmPassword.value) {
+ alert("两次输入的密码不一致")
+ return false
+ }
+ return true
+}
+
+checkInfo.checkNewPassword = function() {
+ let password = document.getElementById('newPassword')
+ let regexPassword = /^[A-Za-z0-9\W_]{6,20}$/
+ if (!regexPassword.test(password.value)) {
+ alert("密码须为长度为6-20位字母、数字或符号")
+ return false
+ }
+ let confirmPassword = document.getElementById('confirmNewPassword')
+ if (password.value !== confirmPassword.value) {
+ alert("两次输入的密码不一致")
+ return false
+ }
+ return true
+}
\ No newline at end of file
diff --git a/Assignments/Assignment5/src/static/js/modify.js b/Assignments/Assignment5/src/static/js/modify.js
new file mode 100644
index 0000000..084e9f4
--- /dev/null
+++ b/Assignments/Assignment5/src/static/js/modify.js
@@ -0,0 +1,28 @@
+var modify = {}
+
+modify.showModifyPassword = function() {
+ let modifyType = document.getElementById('modifyType').value
+ let info = {
+ modifyPasswordLis: document.getElementsByClassName('modifyPassword'),
+ modifymobileNoLis: document.getElementsByClassName('modifymobileNo'),
+ }
+
+ // 遍历隐藏所有元素
+ for (let key in info) {
+ let elements = info[key];
+ for (let item of elements) {
+ item.style.display = 'none'; // 确保所有相关元素被隐藏
+ }
+ }
+
+ // 根据 modifyType 显示相关元素
+ if (modifyType === "2") {
+ for (let item of info.modifyPasswordLis) {
+ item.style.display = 'block';
+ }
+ } else if (modifyType === "3") {
+ for (let item of info.modifymobileNoLis) {
+ item.style.display = 'block';
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assignments/Assignment5/src/templates/index.html b/Assignments/Assignment5/src/templates/index.html
new file mode 100644
index 0000000..a08a5b8
--- /dev/null
+++ b/Assignments/Assignment5/src/templates/index.html
@@ -0,0 +1,24 @@
+
+
+
+ 我的12306官网
+
+
+
+ Coming soon~
+
+
+
+
\ No newline at end of file
diff --git a/Assignments/Assignment5/src/templates/modify.html b/Assignments/Assignment5/src/templates/modify.html
new file mode 100644
index 0000000..dcd57dc
--- /dev/null
+++ b/Assignments/Assignment5/src/templates/modify.html
@@ -0,0 +1,96 @@
+
+
+
+ 修改账户
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assignments/Assignment5/src/templates/signup.html b/Assignments/Assignment5/src/templates/signup.html
new file mode 100644
index 0000000..518e500
--- /dev/null
+++ b/Assignments/Assignment5/src/templates/signup.html
@@ -0,0 +1,115 @@
+
+
+
+ 我的12306注册
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assignments/Assignment5/作业5_21281280_柯劲帆.pdf b/Assignments/Assignment5/作业5_21281280_柯劲帆.pdf
new file mode 100644
index 0000000..c4d9363
Binary files /dev/null and b/Assignments/Assignment5/作业5_21281280_柯劲帆.pdf differ