diff --git a/Project/__pycache__/main.cpython-311.pyc b/Project/__pycache__/main.cpython-311.pyc new file mode 100644 index 0000000..5e510a5 Binary files /dev/null and b/Project/__pycache__/main.cpython-311.pyc differ diff --git a/Project/db.sql b/Project/db.sql new file mode 100644 index 0000000..3a0b4ff --- /dev/null +++ b/Project/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/Project/init_db.py b/Project/init_db.py new file mode 100644 index 0000000..1957f23 --- /dev/null +++ b/Project/init_db.py @@ -0,0 +1,17 @@ +import pymysql + +db = pymysql.connect( + host='localhost', user='kejingfan', + password='KJF2811879', 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/Project/main.py b/Project/main.py new file mode 100644 index 0000000..f2677d9 --- /dev/null +++ b/Project/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='KJF2811879', 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/Project/requirements.txt b/Project/requirements.txt new file mode 100644 index 0000000..e79ebbc --- /dev/null +++ b/Project/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/Project/run.sh b/Project/run.sh new file mode 100644 index 0000000..dc861d9 --- /dev/null +++ b/Project/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/Project/static/css/style.css b/Project/static/css/style.css new file mode 100644 index 0000000..34abe50 --- /dev/null +++ b/Project/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/Project/static/js/checkInfo.js b/Project/static/js/checkInfo.js new file mode 100644 index 0000000..641c012 --- /dev/null +++ b/Project/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/Project/static/js/modify.js b/Project/static/js/modify.js new file mode 100644 index 0000000..084e9f4 --- /dev/null +++ b/Project/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/Project/templates/index.html b/Project/templates/index.html new file mode 100644 index 0000000..a08a5b8 --- /dev/null +++ b/Project/templates/index.html @@ -0,0 +1,24 @@ + + + + 我的12306官网 + + + +

Coming soon~

+
点击跳转注册
+
点击跳转修改账号
+ + \ No newline at end of file diff --git a/Project/templates/modify.html b/Project/templates/modify.html new file mode 100644 index 0000000..dcd57dc --- /dev/null +++ b/Project/templates/modify.html @@ -0,0 +1,96 @@ + + + + 修改账户 + + + + + + +
+ + +
+ + + + + + \ No newline at end of file diff --git a/Project/templates/signup.html b/Project/templates/signup.html new file mode 100644 index 0000000..518e500 --- /dev/null +++ b/Project/templates/signup.html @@ -0,0 +1,115 @@ + + + + 我的12306注册 + + + + + + +
+ + +
+ + + + + \ No newline at end of file