GVic云槿
发布于 2024-10-06 / 87 阅读
4

数字化作业统计平台V1.0-文档


我们已经发布了最新的ReleaseV1.2版本:数字化作业统计平台V1.2-文档 - GVic云槿的博客此版本已不再维护!


前言

尊敬的评委:

您好!非常荣幸能够向您展示我们的科创项目。在此,我们衷心感谢您拨冗审阅我们的文档,给予我们这个宝贵的机会来分享我们的努力与成果。

我们的团队怀着对科技创新的热忱与执着,投入了大量的时间和精力,致力于打造一个具有创新性、实用性和前瞻性的项目。这个项目凝聚着我们的智慧与汗水,也承载着我们对未来的憧憬与期望。

在接下来的文档中,您将了解到我们项目的详细内容,包括项目的背景与意义、创新点与核心技术、实施过程与成果展示,以及未来的发展规划等方面。我们相信,这个项目将为相关领域带来新的思路和解决方案,为推动科技创新和社会进步贡献一份力量。

1.灵感

在日常的学习生活中,家庭作业是学生巩固知识、提升能力的重要环节。然而,收作业却常常成为一个令人头疼的问题。每天课代表在收作业时,总有部分同学不交,导致作业收不齐。老师为了检查谁没交作业,不得不花费大量时间与精力,这严重影响了上课进度和办公效率。

为了解决这一问题,我们团队经过深入思考和反复讨论,提出了一个创新的解决方案。我们设想让同学们在书的侧面贴上条形码,并将信息录入系统。当作业收起后,课代表只需把作业本摞成一摞,老师对着侧面的一堆条码进行拍照,上传到系统中。系统便会迅速分析出谁没有交作业,同时记录这些数据,并且在每周还能进行数据汇总。

通过这个智能作业管理系统,我们可以极大地简化检查和统计作业的复杂环节,减少所需时间,从而显著提高效率。这不仅能让老师更专注于教学工作,也能培养学生的自律意识和责任感。

2.使用方法

2.1.重要:

*为便于您评审我们的作品,我们将项目部署在了我们的自营服务器上。因为是自营服务器,稳定性方面可能无法完全保障。为确保服务在线,我们将项目部署在了两台服务器上。由于缺乏公网,我们采用了内网穿透,以便您能在公网访问我们的项目。鉴于经费问题,我们使用了较为廉价的 FRP 服务器,该服务器不具备端口转发功能。因此,在您访问项目网址时,请务必在后面加上端口22222,否则网页无法打开。同时,因经费有限租用了廉价服务器,访问速度可能会稍慢,还望您海涵。此外,考虑到廉价服务器可能出现问题导致服务无法访问,我们设置了两个节点,分别交叉对应两台服务器上的项目,如此便形成了四条访问线路,最大程度确保我们的服务能够持续在线。

2.2.链接:

我们已经将项目部署在我们的服务器上,一下链接均通往我们的项目:

http://kc.gvicyunjin.cn:22222/

http://kc2.gvicyunjin.cn:61419/

http://kc3.gvicyunjin.cn:22224/

http://kc4.gvicyunjin.cn:2617/

2.3.使用详情:

1.如果是首次使用,需要先注册班级,输入班级同学姓名,一行一个,完成后点击注册。

2.注册完成后会显示班级成员及条码,这时需要班主任截图并打印,将条码贴到同学们的作业册子的侧面。

3.点击注销班级选项可注销班级,重新注册,适用于分班,或有新同学转入。

4.课代表收作业后,将作业摞成一摞交给班主任,班主任对着侧面拍照后,传入系统点击检查作业,系统就能快速检测出谁没有提交作业。

3.实现过程

3.1文件结构

/homework-chack
│
├── Dockerfile	       # docker文件,用于docker部署
├── app.py		       # 后端文件,用于数据存储,生码解码
├── class_data.pkl     # 数据文件
├── requirements.txt   # 列出依赖包
├── /templates
│   └── index.html     # 前端 HTML 模板,用于用户交互
├── /static
│   └── /barcodes      # 条码图片保存路径
└── /uploads           # 上传的作业条码图片

3.2.app.py

源码:

from flask import Flask, render_template, request, redirect, url_for, flash, send_from_directory
from pyzbar.pyzbar import decode
from PIL import Image
import os
import pickle
import barcode
from barcode.writer import ImageWriter

app = Flask(__name__)
app.secret_key = 'your_secret_key'

# 数据文件路径
data_file = "class_data.pkl"

# 加载班级数据
def load_class_data():
    if os.path.exists(data_file):
        try:
            with open(data_file, 'rb') as f:
                return pickle.load(f)
        except EOFError:
            return {}
    return {}

# 保存班级数据
def save_class_data(class_data):
    with open(data_file, 'wb') as f:
        pickle.dump(class_data, f)

# 条码生成
def generate_barcode(student_id, student_name):
    barcode_dir = "static/barcodes"
    if not os.path.exists(barcode_dir):
        os.makedirs(barcode_dir)

    ean = barcode.get('code128', str(student_id), writer=ImageWriter())
    filename = f"{barcode_dir}/{student_name}_{student_id}"
    ean.save(filename)
    filename += ".png"
    return filename

# Flask 路由
@app.route('/')
def index():
    class_data = load_class_data()
    barcodes = {}
    if class_data:
        for student_id, student_name in class_data.items():
            barcode_path = f"barcodes/{student_name}_{student_id}.png"
            barcodes[student_id] = barcode_path
    return render_template('index.html', class_data=class_data, barcodes=barcodes)

@app.route('/register', methods=['POST'])
def register():
    student_names = request.form['student_names'].strip()
    if student_names:
        students = student_names.splitlines()
        class_data = {i+1: name for i, name in enumerate(students)}
        save_class_data(class_data)

        # 自动为所有学生生成条码
        for student_id, student_name in class_data.items():
            generate_barcode(student_id, student_name)

        flash("班级成员注册成功并生成条码!", "success")
    else:
        flash("请输入班级成员姓名!", "error")
    return redirect(url_for('index'))

@app.route('/unregister', methods=['POST'])
def unregister():
    if os.path.exists(data_file):
        os.remove(data_file)
    flash("班级数据已删除。", "success")
    return redirect(url_for('index'))

@app.route('/check_homework', methods=['POST'])
def check_homework():
    file = request.files['barcode_image']
    if file:
        file_path = os.path.join('uploads', file.filename)
        file.save(file_path)

        # 解码条码图片
        img = Image.open(file_path)
        barcodes = decode(img)

        if not barcodes:
            flash("未检测到任何条码!", "error")
        else:
            class_data = load_class_data()
            submitted_ids = [int(barcode_obj.data.decode('utf-8')) for barcode_obj in barcodes if barcode_obj.type == 'CODE128']
            missing_students = [name for student_id, name in class_data.items() if student_id not in submitted_ids]

            if missing_students:
                missing_list = "\n".join(missing_students)
                flash(f"未交作业的学生:\n{missing_list}", "info")
            else:
                flash("所有学生都已提交作业。", "success")
    else:
        flash("请上传条码图片!", "error")

    return redirect(url_for('index'))

if __name__ == '__main__':
    if not os.path.exists('static/barcodes'):
        os.makedirs('static/barcodes')
    if not os.path.exists('uploads'):
        os.makedirs('uploads')
    app.run(host='0.0.0.0', port=44441)

解释:

一、整体概述

使用 Flask 框架构建了一个简单的 Web 应用程序,用于班级成员注册、生成条形码、检查作业提交情况。

二、导入模块

from flask import Flask, render_template, request, redirect, url_for, flash, send_from_directory
from pyzbar.pyzbar import decode
from PIL import Image
import os
import pickle
import barcode
from barcode.writer import ImageWriter
  • Flask等来自 Flask 框架的模块用于构建 Web 应用。

  • decode用于解码条形码图片。

  • Image来自 PIL 库,用于处理图像。

  • os用于操作系统相关的操作,如文件路径检查、创建目录等。

  • pickle用于序列化和反序列化数据。

  • barcodeImageWriter用于生成条形码。

三、定义数据文件路径和应用实例

app = Flask(__name__)
app.secret_key = 'your_secret_key'

# 数据文件路径
data_file = "class_data.pkl"
  • 创建了一个 Flask 应用实例,并设置了一个密钥用于加密会话数据。

  • 定义了数据文件的路径,用于存储班级数据。

四、加载和保存班级数据的函数

# 加载班级数据
def load_class_data():
    if os.path.exists(data_file):
        try:
            with open(data_file, 'rb') as f:
                return pickle.load(f)
        except EOFError:
            return {}
    return {}

# 保存班级数据
def save_class_data(class_data):
    with open(data_file, 'wb') as f:
        pickle.dump(class_data, f)
  • load_class_data函数用于从数据文件中加载班级数据,如果文件存在且读取成功,则返回反序列化后的班级数据字典,否则返回一个空字典。

  • save_class_data函数用于将班级数据字典序列化后保存到数据文件中。

五、生成条形码的函数

# 条码生成
def generate_barcode(student_id, student_name):
    barcode_dir = "static/barcodes"
    if not os.path.exists(barcode_dir):
        os.makedirs(barcode_dir)

    ean = barcode.get('code128', str(student_id), writer=ImageWriter())
    filename = f"{barcode_dir}/{student_name}_{student_id}"
    ean.save(filename)
    filename += ".png"
    return filename
  • 该函数接受学生的 ID 和姓名作为参数,用于生成条形码。

  • 首先检查用于存储条形码的目录是否存在,如果不存在则创建。

  • 然后使用barcode库生成一个code128类型的条形码,将学生 ID 作为条形码的数据。

  • 保存条形码图片,并返回生成的条形码图片的文件名。

六、Flask 路由定义

  1. 首页路由

@app.route('/')
def index():
    class_data = load_class_data()
    barcodes = {}
    if class_data:
        for student_id, student_name in class_data.items():
            barcode_path = f"barcodes/{student_name}_{student_id}.png"
            barcodes[student_id] = barcode_path
    return render_template('index.html', class_data=class_data, barcodes=barcodes)
  • 当访问根路径时,调用这个函数。

  • 加载班级数据,为每个学生生成对应的条形码路径,并将班级数据和条形码路径传递给模板进行渲染,显示在网页上。

  1. 注册路由

@app.route('/register', methods=['POST'])
def register():
    student_names = request.form['student_names'].strip()
    if student_names:
        students = student_names.splitlines()
        class_data = {i + 1: name for i, name in enumerate(students)}
        save_class_data(class_data)

        # 自动为所有学生生成条码
        for student_id, student_name in class_data.items():
            generate_barcode(student_id, student_name)

        flash("班级成员注册成功并生成条码!", "success")
    else:
        flash("请输入班级成员姓名!", "error")
    return redirect(url_for('index'))
  • 处理 POST 请求,用于班级成员注册。

  • 从表单中获取学生姓名列表,去除两端的空白字符。如果有学生姓名,则将其按行分割成列表,创建一个字典,其中键为学生的序号,值为学生姓名,并保存到数据文件中。

  • 为每个学生生成条形码。最后,显示注册成功的消息,并重定向到首页。

  1. 注销路由

@app.route('/unregister', methods=['POST'])
def unregister():
    if os.path.exists(data_file):
        os.remove(data_file)
    flash("班级数据已删除。", "success")
    return redirect(url_for('index'))
  • 处理 POST 请求,用于删除班级数据。

  • 如果数据文件存在,则删除该文件,并显示班级数据已删除的消息,重定向到首页。

  1. 检查作业路由

@app.route('/check_homework', methods=['POST'])
def check_homework():
    file = request.files['barcode_image']
    if file:
        file_path = os.path.join('uploads', file.filename)
        file.save(file_path)

        # 解码条码图片
        img = Image.open(file_path)
        barcodes = decode(img)

        if not barcodes:
            flash("未检测到任何条码!", "error")
        else:
            class_data = load_class_data()
            submitted_ids = [int(barcode_obj.data.decode('utf-8')) for barcode_obj in barcodes if barcode_obj.type == 'CODE128']
            missing_students = [name for student_id, name in class_data.items() if student_id not in submitted_ids]

            if missing_students:
                missing_list = "\n".join(missing_students)
                flash(f"未交作业的学生:\n{missing_list}", "info")
            else:
                flash("所有学生都已提交作业。", "success")
    else:
        flash("请上传条码图片!", "error")

    return redirect(url_for('index'))
  • 处理 POST 请求,用于检查作业提交情况。

  • 从上传的文件中获取条形码图片,如果有图片,则保存到uploads目录下。

  • 使用pyzbar库解码条形码图片,获取其中的学生 ID。

  • 加载班级数据,对比提交的学生 ID 和班级中的学生 ID,找出未提交作业的学生姓名。

  • 如果有未提交作业的学生,则显示未提交作业的学生名单;如果所有学生都已提交作业,则显示相应的消息。最后重定向到首页。

七、主程序部分

if __name__ == '__main__':
    if not os.path.exists('static/barcodes'):
        os.makedirs('static/barcodes')
    if not os.path.exists('uploads'):
        os.makedirs('uploads')
    app.run(host='0.0.0.0', port=44441)
  • 在主程序中,检查用于存储条形码和上传文件的目录是否存在,如果不存在则创建。

  • 启动 Flask 应用,监听指定的端口和 IP 地址。

3.3.requirements.txt

用于列出python所有依赖库或模块,便于构建docker容器时安装

Flask
Pillow
pyzbar
python-barcode

3.4.dockerfile

# 使用基础镜像
FROM python:3.9-slim

# 安装 zbar 库的依赖
RUN apt-get update && apt-get install -y \
    zbar-tools \
    libzbar0 \
    && rm -rf /var/lib/apt/lists/*

# 设置工作目录
WORKDIR /app

# 复制当前目录的内容到工作目录
COPY . /app

# 使用阿里云 pypi 镜像源安装依赖
RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ --no-cache-dir Flask Pillow pyzbar python-barcode

# 暴露端口 44441
EXPOSE 44441

# 运行 Flask 应用
CMD ["python", "app.py"]

一、基础镜像选择

FROM python:3.9-slim

使用 Python 3.9 的 slim 版本作为基础镜像,这个镜像通常比较小,包含了基本的 Python 运行环境,可以减少最终构建的 Docker 镜像的大小。

二、安装 zbar 库依赖

RUN apt-get update && apt-get install -y \
    zbar-tools \
    libzbar0 \
    && rm -rf /var/lib/apt/lists/*

这一步更新了软件包列表并安装了 zbar-toolslibzbar0,这些是用于在容器中处理条形码的依赖库。安装完成后,清理了软件包列表缓存以减小镜像大小。

三、设置工作目录

WORKDIR /app

将容器内的工作目录设置为 /app,后续的操作都将在这个目录下进行。

四、复制项目文件

COPY. /app

将当前目录(构建上下文)下的所有文件复制到容器的 /app 目录中,确保项目的代码和相关文件在容器内可用。

五、安装项目依赖

RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ --no-cache-dir Flask Pillow pyzbar python-barcode

使用阿里云的 PyPI 镜像源安装项目所需的依赖库,包括 Flask、Pillow、pyzbar 和 python-barcode。--no-cache-dir 参数确保不使用缓存,每次构建都重新安装依赖,以保证依赖的一致性。

六、暴露端口

EXPOSE 44441

声明容器将在运行时监听 44441 端口,以便外部可以访问容器内运行的应用程序。

七、运行应用

CMD ["python", "app.py"]

在容器启动时,执行 python app.py 命令来运行 Flask 应用程序。

3.5./templates/index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>数字化作业统计平台</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background: linear-gradient(to right, #4facfe, #00f2fe);
            color: white;
            text-align: center;
        }

        h1 {
            margin-top: 30px;
            font-size: 2.5em;
        }

        form {
            margin: 20px 0;
        }

        textarea {
            padding: 10px;
            border-radius: 10px;
            border: none;
            width: 50%;
            font-size: 16px;
        }

        button {
            padding: 10px 20px;
            border: none;
            background-color: #ff6a00;
            color: white;
            border-radius: 20px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.3s ease;
        }

        button:hover {
            background-color: #ff9000;
        }

        .grid-container {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin: 20px;
            padding: 20px;
        }

        .grid-item {
            background-color: rgba(255, 255, 255, 0.1);
            border-radius: 15px;
            padding: 20px;
            transition: transform 0.3s ease;
        }

        .grid-item:hover {
            transform: scale(1.05);
        }

        img {
            max-width: 100%;
            height: auto;
        }
    </style>
</head>
<body>
    <h1>数字化作业统计平台</h1>

    {% with messages = get_flashed_messages(with_categories=true) %}
        {% if messages %}
            <ul>
                {% for category, message in messages %}
                    <li><strong>{{ category }}:</strong> {{ message }}</li>
                {% endfor %}
            </ul>
        {% endif %}
    {% endwith %}

    {% if not class_data %}
    <h2>注册班级</h2>
    <form action="/register" method="post">
        <textarea name="student_names" rows="10" placeholder="每行输入一个学生姓名"></textarea><br><br>
        <button type="submit">注册班级并生成条码</button>
    </form>
    {% endif %}

    {% if class_data %}
    <h2>班级成员及条码</h2>
    <div class="grid-container">
        {% for student_id, student_name in class_data.items() %}
        <div class="grid-item">
            <p>{{ student_id }}. {{ student_name }}</p>
            <img src="/static/{{ barcodes[student_id] }}" alt="条码">
        </div>
        {% endfor %}
    </div>

    <form action="/unregister" method="post">
        <button type="submit">注销班级</button>
    </form>

    <h2>上传作业条码图片</h2>
    <form action="/check_homework" method="post" enctype="multipart/form-data">
        <input type="file" name="barcode_image" accept="image/*"><br><br>
        <button type="submit">检查作业</button>
    </form>
    {% endif %}
</body>
</html>

一、文档结构和语言设置

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>数字化作业统计平台</title>
   ...
</head>
<body>
   ...
</body>
</html>

这是一个标准的 HTML5 文档结构,设置页面语言为中文简体(zh-CN),定义了文档的标题为 “数字化作业统计平台”,并在 <head> 标签中包含了页面的样式定义。

二、页面样式

  1. 整体背景和字体

   body {
       font-family: Arial, sans-serif;
       background: linear-gradient(to right, #4facfe, #00f2fe);
       color: white;
       text-align: center;
   }
  • 设置页面的字体为 Arial 或无衬线字体,背景为从蓝色到浅蓝色的线性渐变,文本颜色为白色,内容居中显示。

  1. 标题样式

   h1 {
       margin-top: 30px;
       font-size: 2.5em;
   }
  • 标题 h1 元素距离页面顶部有 30 像素的边距,字体大小为 2.5 倍。

  1. 表单元素样式

    • 文本区域

     textarea {
         padding: 10px;
         border-radius: 10px;
         border: none;
         width: 50%;
         font-size: 16px;
     }
  • 文本区域有 10 像素的内边距,圆角边框为 10 像素,无边框,宽度为页面的 50%,字体大小为 16 像素。

  • 按钮

     button {
         padding: 10px 20px;
         border: none;
         background-color: #ff6a00;
         color: white;
         border-radius: 20px;
         cursor: pointer;
         font-size: 16px;
         transition: background-color 0.3s ease;
     }

     button:hover {
         background-color: #ff9000;
     }
  • 按钮有 10 像素的上下内边距和 20 像素的左右内边距,无边框,背景颜色为橙色(#ff6a00),文本颜色为白色,圆角边框为 20 像素,鼠标指针为手型,字体大小为 16 像素。当鼠标悬停在按钮上时,背景颜色变为更亮的橙色(#ff9000),通过过渡效果在 0.3 秒内平滑变化。

  1. 网格容器样式

  .grid-container {
       display: grid;
       grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
       gap: 20px;
       margin: 20px;
       padding: 20px;
   }

  .grid-item {
       background-color: rgba(255, 255, 255, 0.1);
       border-radius: 15px;
       padding: 20px;
       transition: transform 0.3s ease;
   }

  .grid-item:hover {
       transform: scale(1.05);
   }
  • 定义了一个网格容器 .grid-container,使用 CSS Grid 布局,自动适应内容宽度,每列最小宽度为 200 像素,间隔为 20 像素,有边距和内边距。

  • 网格项 .grid-item 有半透明的白色背景,圆角边框为 15 像素,内边距为 20 像素,当鼠标悬停在网格项上时,通过过渡效果在 0.3 秒内放大到 1.05 倍。

  1. 图片样式

   img {
       max-width: 100%;
       height: auto;
   }
  • 确保图片最大宽度不超过其父元素宽度,高度自动调整以保持比例。

三、页面内容

  1. 标题

   <h1>数字化作业统计平台</h1>
  • 显示页面的主要标题。

  1. 显示 Flash 消息

   {% with messages = get_flashed_messages(with_categories=true) %}
       {% if messages %}
           <ul>
               {% for category, message in messages %}
                   <li><strong>{{ category }}:</strong> {{ message }}</li>
               {% endfor %}
           </ul>
       {% endif %}
   {% endwith %}
  • 使用 Jinja2 模板语法获取 Flask 的 Flash 消息,并根据消息的类别和内容进行显示。如果有消息,则以列表形式展示,每个消息都带有类别标签并加粗显示。

  1. 注册班级表单(如果班级未注册)

   {% if not class_data %}
   <h2>注册班级</h2>
   <form action="/register" method="post">
       <textarea name="student_names" rows="10" placeholder="每行输入一个学生姓名"></textarea><br><br>
       <button type="submit">注册班级并生成条码</button>
   </form>
   {% endif %}
  • 如果没有班级数据(class_data),则显示一个注册班级的表单。表单包含一个文本区域,用于输入学生姓名,每行一个学生,以及一个提交按钮。表单的提交地址为 /register,使用 POST 方法。

  1. 班级成员及条码展示(如果班级已注册)

   {% if class_data %}
   <h2>班级成员及条码</h2>
   <div class="grid-container">
       {% for student_id, student_name in class_data.items() %}
       <div class="grid-item">
           <p>{{ student_id }}. {{ student_name }}</p>
           <img src="/static/{{ barcodes[student_id] }}" alt="条码">
       </div>
       {% endfor %}
   </div>

   <form action="/unregister" method="post">
       <button type="submit">注销班级</button>
   </form>

   <h2>上传作业条码图片</h2>
   <form action="/check_homework" method="post" enctype="multipart/form-data">
       <input type="file" name="barcode_image" accept="image/*"><br><br>
       <button type="submit">检查作业</button>
   </form>
   {% endif %}
  • 如果有班级数据,则显示班级成员及对应的条码。使用 CSS Grid 布局展示每个学生的信息,包括学生编号、姓名和条码图片。同时提供一个注销班级的表单和一个上传作业条码图片的表单。注销班级表单提交地址为 /unregister,使用 POST 方法;上传作业条码图片表单提交地址为 /check_homework,使用 POST 方法,并设置 enctype="multipart/form-data" 以支持文件上传。表单包含一个文件选择输入框,只接受图片文件,以及一个提交按钮。

4.私有化部署

/以ubuntu22.04live为例,默认有docker环境/

4.1.通过finalshell或其他shh工具连接到你的服务器连接到你的服务器

4.2.上传文件夹【homework-ckack】到你的服务器任意位置,并授予777权限(root用户请忽略)

4.3.获取根用户权限

su root

4.4. cd到上传文件的根目录,ls确定能看到dockerfile即可

4.5.在终端输入以下指令构建docker容器:

docker build -t homework-checker .

dockerfile已经配置好国内镜像,根据网络波动,构建大约需要3-10分钟

4.6.在终端输入以下指令启动docker容器:

docker run -d -p 44441:44441 --name homework-checker homework-checker

4.7.在安全组/防火墙放行44441端口,以保证请求不会被拦截

4.8.通过 http://{服务器ip}:44441 访问应用程序

4.9.若没有公网,可选择进行内网穿透。

5.未来计划

目前,我们的程序已基本实现通过在同学们的书侧面贴条码,老师拍照条码即可快速确定未交作业的学生,极大地减轻了收作业的工作负担。

对于未来的计划:

1.我们将引入设置多班级功能,可注册多个班级,让更多的师生共同使用我们这套系统。同时,我们还会为每科老师分别设置独立的账号密码,例如,语文老师有专属的语文账号密码,数学老师有自己的数学账号密码。不同老师上传作业情况后,班主任将拥有一个管理平台,在该平台上可以清晰地看到哪个同学具体哪一科未交作业。

2.我们将采用 token 技术与服务器进行验证。这样,老师在一次登录后,在特定时间段内可凭借 token 验证无需再次登录直接打开系统。

3.此外,后续我们还会引入每周、每月、每学期的统计量,并运用图表、折线等数据统计方式,直观地展示学生的作业完成情况,为教学管理提供更有力的支持。

4.为了保证这个数据安全,我们后续还会进行数据容灾方面的优化。在数据冗余方面,我们会对服务器设置 RAID 阵列,将数据存在阵列中,以保证即使硬盘损坏,数据也不会丢失。同时,我们还会进行数据灾备,设置两个异地服务器,让数据在异地服务器之间进行同步。这样,即使有一台服务器由于一些不可控因素如断电、火灾、海啸等问题损坏,我们的数据还能在另外一台服务器上恢复,服务也可以在另外一台服务器上继续进行,从而最大程度地保证用户的数据安全。

6.感谢

在数字化作业统计平台的开发之旅中,我们曾于服务器调试与网页构建的重重困难里徘徊挣扎,无数次想要放弃却又一次次选择坚持。队友间相互打气、携手共进,指导老师倾囊相授、悉心指引,网络资源如 CSDN、菜鸟编程等平台以及 zbar 库、flask 库、PILLOW 库的原作者提供的帮助,如同点点星光照亮我们前行的道路。 因为坚持,我们收获成长,未来也将秉持这种探索、积极且坚持不懈的精神,于生活中砥砺前行。我们会努力汲取科学文化知识,钻研辩证思维,立志在科技与网络领域发光发热,为国家贡献自己的力量,不负梦想,成就未来!

再次感谢评委们耐心观看我们的成果展示!


开发团队:

成员:郭子路,龚毅夫

指导老师:薛仙

学校:西安市第六十六中学