一、个人任务
本周我的任务主要有以下两个
- 后台登录界面设计
- 后台代码整合与测试
二、任务1——后台登录界面设计
后台登录界面样式如下:
关键的实现代码为
<style>
.center {
width: 100%;
height: 100%;
background-image: linear-gradient(to top, #48c6ef 0%, #6f86d6 100%);
/* background-size: 100% 100%; */
background-repeat: no-repeat;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
h1 {
font-size: 30px;
color: black;
}
.logon {
background-color: #fff;
border-radius: 10px;
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
/* position: relative;
overflow: hidden; */
width: 768px;
max-width: 100%;
min-height: 480px;
margin-top: 20px;
display: flex;
background: -webkit-linear-gradient(right, #4284db, #29eac4);
}
.overlaylong {
border-radius: 10px 0 0 10px;
width: 50%;
height: 100%;
background-color: #fff;
display: flex;
align-items: center;
justify-content: center;
}
.overlaylongleft {
border-radius: 0px 10px 10px 0px;
width: 50%;
height: 100%;
background-color: #fff;
transform: translateX(100%);
transition: transform 0.6s ease-in-out;
display: flex;
align-items: center;
justify-content: center;
}
.overlaylongright {
border-radius: 10px 0 0 10px;
width: 50%;
height: 100%;
background-color: #fff;
transform: translateX(0%);
transition: transform 0.6s ease-in-out;
display: flex;
align-items: center;
justify-content: center;
}
.overlaytitle {
border-radius: 0px 10px 10px 0px;
width: 50%;
height: 100%;
background-color: rgba(0, 0, 0, 0);
display: flex;
align-items: center;
justify-content: center;
}
.overlaytitleH2 {
font-size: 30px;
color: #fff;
margin-top: 20px;
}
.overlaytitleP {
font-size: 15px;
color: #fff;
margin-top: 20px;
}
.overlaytitleleft {
border-radius: 0px 10px 10px 0px;
width: 50%;
height: 100%;
background-color: rgba(0, 0, 0, 0);
display: flex;
align-items: center;
justify-content: center;
transform: translateX(0%);
transition: transform 0.6s ease-in-out;
}
.overlaytitleright {
border-radius: 0px 10px 10px 0px;
width: 50%;
height: 100%;
background-color: rgba(0, 0, 0, 0);
display: flex;
align-items: center;
justify-content: center;
transform: translateX(-100%);
transition: transform 0.6s ease-in-out;
}
.overlaytitle-Signin {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.overlaytitle-Signup {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.buttongohs {
width: 180px;
height: 40px;
border-radius: 50px;
border: 1px solid #fff;
color: #fff;
font-size: 15px;
text-align: center;
line-height: 40px;
margin-top: 40px;
}
.overlaylongH2 {
font-size: 25px;
color: black;
/* width: 250px; */
}
.overlaylong-Signin {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.overlaylong-Signup {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
input {
background-color: #eee;
border: none;
padding: 12px 15px;
margin: 10px 0;
width: 240px;
}
h3{
font-size: 10px;
margin-top: 10px;
cursor: pointer;
}
.inupbutton{
background-color: #29eac4;
border: none;
width: 180px;
height: 40px;
border-radius: 50px;
font-size: 15px;
color: #fff;
text-align: center;
line-height: 40px;
margin-top: 30px;
}
</style>
<template>
<div class="center">
<div class="logon">
<div :class="overlaylong">
<div class="overlaylong-Signin" v-if="disfiex == 0">
<h2 class="overlaylongH2">Sign in</h2>
<input type="text" v-model="loginForm.username" placeholder="用户名">
<input type="adminpassword" v-model="loginForm.adminpassword" placeholder="密码">
<button class="inupbutton" @click="signIn">Sign in</button>
</div>
<div class="overlaylong-Signup" v-if="disfiex == 1">
<h2 class="overlaylongH2">注册账号</h2>
<input type="text" placeholder="用户名">
<input type="adminpassword" placeholder="密码">
<button class="inupbutton">Sign up</button>
</div>
</div>
<div :class="overlaytitle">
<div class="overlaytitle-Signin" v-if="disfiex == 0">
<h2 class="overlaytitleH2">你好,朋友!</h2>
<p class="overlaytitleP">
输入你的密码以加入我们
</p>
<!-- <div class="buttongohs" @click="signUp">Sign up</div> -->
</div>
<div class="overlaytitle-Signup" v-if="disfiex == 1">
<h2 class="overlaytitleH2">欢迎回来!</h2>
<p class="overlaytitleP">为了保持与我们的联系,请使用你的个人信息登录</p>
<div class="buttongohs" @click="signIn">Sign in</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
axios.defaults.baseURL = 'http://127.0.0.1:8080';
export default {
data() {
return {
overlaylong: 'overlaylong',
overlaytitle: 'overlaytitle',
disfiex: 0,
loginForm: {
username: '',
adminpassword: ''
}
}
},
methods: {
signUp() {
this.overlaylong = "overlaylongleft"
this.overlaytitle = "overlaytitleright"
setTimeout(() => {
this.disfiex = 1
}, 200)
},
async signIn() {
const { username, adminpassword } = this.loginForm;
try {
// 使用 axios 发送 POST 请求,确保使用正确的密码字段名
const response = await axios.post('/login', { username, adminpassword: adminpassword }); // 注意这里
const { token } = response.data; // 假设您的后端返回了 token
// 存储令牌,例如在 localStorage 中
localStorage.setItem('token', token);
this.$router.push('/userinfo');
} catch (error) {
if (error.response) {
// 如果服务器返回了状态码和响应体,你可以在这里处理
console.error('登录失败', error.response.data);
} else if (error.request) {
// 如果请求被发送但服务器没有响应
console.error('请求已发送但未收到响应', error.request);
} else {
// 发生了一些错误,如设置请求时
console.error('发生错误', error.message);
}
}
}
}
}
</script>
三、任务2——后台代码整合与测试
本周我完成了对后台代码整合与测试,包括问答记录、用户登录记录等。后台的初步页面如下:
后端整合后的代码如下,下面只截取了关键部分:
用户问答模块
@app.route('/api/users', methods=['GET'])
def get_users():
"""
获取所有用户数据
:return: JSON格式的响应,包含所有用户数据
"""
db_conn = get_db_conn()
try:
users = db_conn.get_all(sql_str="select * from user_info")
if not users:
return msg(201, 'User not found') # 假设201表示数据为空或没有找到数据
# 将 datetime 字段转换为字符串
for user in users:
if 'update_time' in user: # 确保 'time' 字段存在
user['update_time'] = user['update_time'].isoformat() if user['update_time'] is not None else None
if 'create_time' in user: # 确保 'time' 字段存在
user['create_time'] = user['create_time'].isoformat() if user['create_time'] is not None else None
return users # 假设200表示成功
except Exception as e:
print(e)
return msg(500, 'Internal Server Error') # 假设500表示服务器内部错误
# 2 返回所有用户问答信息
@app.route('/back/record/getAllRecord/', methods=['GET'])
def getAllRecord():
"""
:return:
"""
db_conn = get_db_conn1()
# word=request.args.get('word')
# text = \
# db_conn.get_one(sql_str="SELECT GROUP_CONCAT(Job_Description) FROM t_boss_zp_info")[0]
# results = db_conn.get_all(sql_str="SELECT * FROM records WHERE user_id = user_id ")
sql_str = "SELECT * FROM records "
# 使用参数化查询来防止SQL注入
results = db_conn.get_all(sql_str)
if results is None:
return msg(201)
# # 假设 results 是一个包含元组的列表,我们将它转换为字典列表
if results is not None:
print(results)
# 假设你的元组中的字段名是 'id', 'name', 'description' 等(这取决于你的数据库表结构)
results_as_dicts = [{'user_id': r[2], 'Q': r[3], 'A': r[5],'record_id': r[1],'id': r[0]} for r in results]
else:
return msg(201) # 假设 msg() 函数返回一个适当的错误响应
# for result in results:
# result['question'] = decode_base64(result['question'])
return jsonify(results_as_dicts ), 200
# 1.1 按用户ID查询列表
@app.route('/back/record/getQandAByUserId/', methods=['GET'])
def getQandAByUserId():
"""
:return:
"""
db_conn = get_db_conn1()
user_id=request.args.get('user_id')
# text = \
# db_conn.get_one(sql_str="SELECT GROUP_CONCAT(Job_Description) FROM t_boss_zp_info")[0]
# results = db_conn.get_all(sql_str="SELECT * FROM records WHERE user_id = user_id ")
sql_str = "SELECT * FROM records WHERE user_id = %s"
args = (user_id,)
results = db_conn.get_all(sql_str,args)
# 假设 results 是一个包含元组的列表,我们将它转换为字典列表
if results is not None:
# 假设你的元组中的字段名是 'id', 'name', 'description' 等(这取决于你的数据库表结构)
results_as_dicts = [{'user_id': r[2], 'Q': r[3], 'A': r[5], 'record_id': r[1]} for r in results]
else:
return msg(201) # 假设 msg() 函数返回一个适当的错误响应
# for result in results:
# result['question'] = decode_base64(result['question'])
return jsonify(results_as_dicts), 200
# 1.2 按问题关键词查询列表
@app.route('/back/record/getQByKeyWord/', methods=['GET'])
def getQByKeyWord():
"""
:return:
"""
db_conn = get_db_conn1()
word=request.args.get('word')
# text = \
# db_conn.get_one(sql_str="SELECT GROUP_CONCAT(Job_Description) FROM t_boss_zp_info")[0]
# results = db_conn.get_all(sql_str="SELECT * FROM records WHERE user_id = user_id ")
sql_str = "SELECT * FROM records WHERE question LIKE %s"
# 使用参数化查询来防止SQL注入
args = ('%' + word + '%',)
results = db_conn.get_all(sql_str,args)
# 假设 results 是一个包含元组的列表,我们将它转换为字典列表
if results is not None:
# 假设你的元组中的字段名是 'id', 'name', 'description' 等(这取决于你的数据库表结构)
results_as_dicts = [{'user_id': r[2], 'Q': r[3], 'A': r[5], 'record_id': r[1]} for r in results]
else:
return msg(201) # 假设 msg() 函数返回一个适当的错误响应
# for result in results:
# result['question'] = decode_base64(result['question'])
return jsonify(results_as_dicts), 200
用户登录模块
@app.route('/api/users', methods=['PUT'])
def update_user():
"""
根据用户 ID 修改用户信息
:param user_id: 用户的唯一标识符
:return: JSON 格式的响应,表示更新操作的结果
"""
db_conn = get_db_conn()
try:
# 解析请求体中的 JSON 数据
user_data = request.json
# 确保用户 ID 在请求中
if 'user_id' not in user_data:
return msg(404, 'User ID is required')
user_id = user_data['user_id']
updates = [f"{key} = %s" for key in user_data if key != 'user_id'] # 排除 user_id
sql_str = "UPDATE user_info SET " + ", ".join(updates) + " WHERE user_id = %s"
# 构建参数列表,包含所有要更新的列的值和 user_id
args = [user_data[key] for key in user_data if key != 'user_id'] + [user_id]
# 执行更新操作
result = db_conn.update(sql_str, args=args)
# 检查更新是否成功
if result:
return msg(200, "修改成功")
else:
return msg(201, 'User not found')
except Exception as e:
print(e)
return msg(500, 'Internal Server Error')
@app.route('/api/users', methods=['DELETE'])
def delete_user_by_id():
"""
根据用户 ID 删除用户数据
:param user_id: 用户的唯一标识符
:return: JSON 格式的响应,包含操作结果
"""
db_conn = get_db_conn()
try:
# 从 URL 查询参数中获取 user_id
user_id = request.args.get('user_id')
if not user_id:
return msg(404, 'ser ID is required')
# 使用用户 ID 构建删除语句
affected_rows = db_conn.delete(sql_str="delete from user_info where user_id = %s", args=(user_id,))
if affected_rows == 0:
return msg(201, 'User not found') # 假设201表示用户未找到
return msg(200, "删除成功") # 200(成功删除)
except Exception as e:
print(e)
return msg(500, 'Internal Server Error') # 假设500表示服务器内部错误
@app.route('/api/users/reset_password', methods=['POST'])
def reset_user_password():
"""
根据用户 ID 重置用户密码
:param user_id: 用户的唯一标识符
:param new_password: 新密码
:return: JSON 格式的响应,包含操作结果
"""
db_conn = get_db_conn()
try:
# 从请求体中获取 user_id 和 new_password
user_id = request.json.get('user_id')
new_password = '123456'
if not user_id :
return msg(404, 'User ID and new password are required')
# 使用用户 ID 构建更新密码的语句
affected_rows = db_conn.update(
sql_str="UPDATE user_info SET password = %s WHERE user_id = %s",
args=(new_password, user_id)
)
if affected_rows == 0:
return msg(201, 'User not found')
return msg(200, "密码重置成功")
except Exception as e:
print(e)
return msg(500, 'Internal Server Error')
四、总结
1、后台登录界面设计
本周,我主要负责了后台登录界面的设计工作。在设计过程中,我遵循了用户友好的原则,确保界面简洁明了,同时兼顾了安全性和易用性。
-
界面布局:我采用了经典的登录界面布局,包括用户名输入框、密码输入框以及登录按钮。为了提升用户体验,我还增加了验证码功能,有效防止了恶意登录尝试。
-
安全性考虑:在设计过程中,我特别注意了密码的加密处理。用户输入的密码在传输过程中会被加密,确保用户信息的安全性。同时,我还考虑了密码的复杂度要求,通过前端验证确保用户设置足够强度的密码。
-
用户体验优化:为了提升用户登录的便捷性,我增加了“忘记密码”和“注册新账号”的链接,方便用户找回密码或注册新账号。同时,我也优化了输入框的样式和提示信息,使得用户在填写信息时更加得心应手。
-
兼容性测试:在设计完成后,我进行了多种浏览器和设备的兼容性测试,确保登录界面在不同环境下都能正常显示和使用。
2、后台代码整合与测试
除了登录界面设计外,本周我还进行了后台代码的整合与测试工作。
-
代码整合:我仔细梳理了现有的后台代码,将各个功能模块的代码进行了整合和优化。通过合理的代码结构设计和命名规范,提高了代码的可读性和可维护性。
-
功能测试:在代码整合完成后,我进行了详细的功能测试。我按照需求文档的要求,逐一测试了各个功能模块的功能点,确保每个功能都能正常运行并满足预期效果。
-
性能测试:除了功能测试外,我还对后台进行了性能测试。我模拟了多种并发场景和负载情况,测试了后台的响应时间和处理能力。通过性能测试,我发现了潜在的性能瓶颈并进行了相应的优化。
-
安全性测试:在测试过程中,我特别关注了后台的安全性。我进行了SQL注入、跨站脚本攻击等常见的安全漏洞测试,确保后台具有足够的安全性。