山东大学软件学院项目实训纪实(七)

一、个人任务

本周我的任务主要有以下两个

  • 后台登录界面设计
  • 后台代码整合与测试

二、任务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、后台登录界面设计

本周,我主要负责了后台登录界面的设计工作。在设计过程中,我遵循了用户友好的原则,确保界面简洁明了,同时兼顾了安全性和易用性。

  1. 界面布局:我采用了经典的登录界面布局,包括用户名输入框、密码输入框以及登录按钮。为了提升用户体验,我还增加了验证码功能,有效防止了恶意登录尝试。

  2. 安全性考虑:在设计过程中,我特别注意了密码的加密处理。用户输入的密码在传输过程中会被加密,确保用户信息的安全性。同时,我还考虑了密码的复杂度要求,通过前端验证确保用户设置足够强度的密码。

  3. 用户体验优化:为了提升用户登录的便捷性,我增加了“忘记密码”和“注册新账号”的链接,方便用户找回密码或注册新账号。同时,我也优化了输入框的样式和提示信息,使得用户在填写信息时更加得心应手。

  4. 兼容性测试:在设计完成后,我进行了多种浏览器和设备的兼容性测试,确保登录界面在不同环境下都能正常显示和使用。

2、后台代码整合与测试

除了登录界面设计外,本周我还进行了后台代码的整合与测试工作。

  1. 代码整合:我仔细梳理了现有的后台代码,将各个功能模块的代码进行了整合和优化。通过合理的代码结构设计和命名规范,提高了代码的可读性和可维护性。

  2. 功能测试:在代码整合完成后,我进行了详细的功能测试。我按照需求文档的要求,逐一测试了各个功能模块的功能点,确保每个功能都能正常运行并满足预期效果。

  3. 性能测试:除了功能测试外,我还对后台进行了性能测试。我模拟了多种并发场景和负载情况,测试了后台的响应时间和处理能力。通过性能测试,我发现了潜在的性能瓶颈并进行了相应的优化。

  4. 安全性测试:在测试过程中,我特别关注了后台的安全性。我进行了SQL注入、跨站脚本攻击等常见的安全漏洞测试,确保后台具有足够的安全性。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值