我们已经发布了最新的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 ImageWriterFlask等来自 Flask 框架的模块用于构建 Web 应用。decode用于解码条形码图片。Image来自 PIL 库,用于处理图像。os用于操作系统相关的操作,如文件路径检查、创建目录等。pickle用于序列化和反序列化数据。barcode和ImageWriter用于生成条形码。
三、定义数据文件路径和应用实例
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 路由定义
首页路由
@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'))处理 POST 请求,用于班级成员注册。
从表单中获取学生姓名列表,去除两端的空白字符。如果有学生姓名,则将其按行分割成列表,创建一个字典,其中键为学生的序号,值为学生姓名,并保存到数据文件中。
为每个学生生成条形码。最后,显示注册成功的消息,并重定向到首页。
注销路由
@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 请求,用于删除班级数据。
如果数据文件存在,则删除该文件,并显示班级数据已删除的消息,重定向到首页。
检查作业路由
@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-barcode3.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-tools 和 libzbar0,这些是用于在容器中处理条形码的依赖库。安装完成后,清理了软件包列表缓存以减小镜像大小。
三、设置工作目录
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> 标签中包含了页面的样式定义。
二、页面样式
整体背景和字体
body {
font-family: Arial, sans-serif;
background: linear-gradient(to right, #4facfe, #00f2fe);
color: white;
text-align: center;
}设置页面的字体为 Arial 或无衬线字体,背景为从蓝色到浅蓝色的线性渐变,文本颜色为白色,内容居中显示。
标题样式
h1 {
margin-top: 30px;
font-size: 2.5em;
}标题
h1元素距离页面顶部有 30 像素的边距,字体大小为 2.5 倍。
表单元素样式
文本区域:
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 秒内平滑变化。
网格容器样式
.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 倍。
图片样式
img {
max-width: 100%;
height: auto;
}确保图片最大宽度不超过其父元素宽度,高度自动调整以保持比例。
三、页面内容
标题
<h1>数字化作业统计平台</h1>显示页面的主要标题。
显示 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 消息,并根据消息的类别和内容进行显示。如果有消息,则以列表形式展示,每个消息都带有类别标签并加粗显示。
注册班级表单(如果班级未注册)
{% 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 方法。
班级成员及条码展示(如果班级已注册)
{% 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 root4.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-checker4.7.在安全组/防火墙放行44441端口,以保证请求不会被拦截
4.8.通过 http://{服务器ip}:44441 访问应用程序
4.9.若没有公网,可选择进行内网穿透。
5.未来计划
目前,我们的程序已基本实现通过在同学们的书侧面贴条码,老师拍照条码即可快速确定未交作业的学生,极大地减轻了收作业的工作负担。
对于未来的计划:
1.我们将引入设置多班级功能,可注册多个班级,让更多的师生共同使用我们这套系统。同时,我们还会为每科老师分别设置独立的账号密码,例如,语文老师有专属的语文账号密码,数学老师有自己的数学账号密码。不同老师上传作业情况后,班主任将拥有一个管理平台,在该平台上可以清晰地看到哪个同学具体哪一科未交作业。
2.我们将采用 token 技术与服务器进行验证。这样,老师在一次登录后,在特定时间段内可凭借 token 验证无需再次登录直接打开系统。
3.此外,后续我们还会引入每周、每月、每学期的统计量,并运用图表、折线等数据统计方式,直观地展示学生的作业完成情况,为教学管理提供更有力的支持。
4.为了保证这个数据安全,我们后续还会进行数据容灾方面的优化。在数据冗余方面,我们会对服务器设置 RAID 阵列,将数据存在阵列中,以保证即使硬盘损坏,数据也不会丢失。同时,我们还会进行数据灾备,设置两个异地服务器,让数据在异地服务器之间进行同步。这样,即使有一台服务器由于一些不可控因素如断电、火灾、海啸等问题损坏,我们的数据还能在另外一台服务器上恢复,服务也可以在另外一台服务器上继续进行,从而最大程度地保证用户的数据安全。
6.感谢
在数字化作业统计平台的开发之旅中,我们曾于服务器调试与网页构建的重重困难里徘徊挣扎,无数次想要放弃却又一次次选择坚持。队友间相互打气、携手共进,指导老师倾囊相授、悉心指引,网络资源如 CSDN、菜鸟编程等平台以及 zbar 库、flask 库、PILLOW 库的原作者提供的帮助,如同点点星光照亮我们前行的道路。 因为坚持,我们收获成长,未来也将秉持这种探索、积极且坚持不懈的精神,于生活中砥砺前行。我们会努力汲取科学文化知识,钻研辩证思维,立志在科技与网络领域发光发热,为国家贡献自己的力量,不负梦想,成就未来!
再次感谢评委们耐心观看我们的成果展示!
开发团队:
成员:郭子路,龚毅夫
指导老师:薛仙
学校:西安市第六十六中学