Files
IOT_SIM/web/src/pages/HelpPage.vue
T
xuyueandClaude Opus 5.5 d6e891cdb0
CI/CD / test (push) Canceled after 0s
CI/CD / deploy (push) Canceled after 0s
使用说明:截图点击后在页面上放大(按窗口大小,最多放大 2 倍),点任意处或按 Esc 关闭
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 14:53:54 +08:00

377 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
// 使用说明:学生部分谁都能看(登录页也有入口),老师登录后多出老师部分。从各页顶栏在新标签页打开,不打断正在做的事。
import { onBeforeUnmount, onMounted, ref } from 'vue'
import { RouterLink } from 'vue-router'
import { currentUser } from '../auth'
/** 点截图在页面上放大看,点任意处或按 Esc 关闭 */
const zoomed = ref<{ src: string; caption: string } | null>(null)
function zoom(event: MouseEvent) {
const link = event.currentTarget as HTMLAnchorElement
zoomed.value = { src: link.href, caption: link.closest('figure')?.querySelector('figcaption')?.textContent ?? '' }
}
/** 按窗口大小放大到放得下,小截图最多放大 2 倍(再大就糊了) */
function fit(event: Event) {
const img = event.target as HTMLImageElement
const scale = Math.min(2, (window.innerWidth - 32) / img.naturalWidth, (window.innerHeight - 72) / img.naturalHeight)
img.style.width = `${Math.round(img.naturalWidth * scale)}px`
}
function onKey(event: KeyboardEvent) {
if (event.key === 'Escape') zoomed.value = null
}
onMounted(() => window.addEventListener('keydown', onKey))
onBeforeUnmount(() => window.removeEventListener('keydown', onKey))
</script>
<template>
<div class="page">
<header class="toolbar">
<strong>物联网编程仿真平台</strong>
<span class="title">使用说明</span>
<span class="spacer" />
<RouterLink :to="currentUser ? '/' : '/login'" class="nav-link">{{ currentUser ? '返回实验' : '登录' }}</RouterLink>
</header>
<main class="content">
<nav class="toc">
<a href="#student">学生</a>
<a v-if="currentUser?.role === 'teacher'" href="#teacher">老师</a>
<a href="#faq">常见问题</a>
</nav>
<section id="student">
<h2>学生</h2>
<h3>1. 登录</h3>
<p>用老师发给你的用户名和密码登录。</p>
<h3>2. 自由练习和做作业</h3>
<ul>
<li>登录后先看到<b>我的作业</b>:老师布置的作业、截止时间和得分;点作业名开始做。做实验时随时可以点右上角的<b>我的作业</b>回来。</li>
<li>点<b>自由练习</b>:左上角的下拉框选教材上的任务,可以随便改、随便运行;下次打开时回到上次做的任务。</li>
<li>工具栏的<b>任务</b>:任务目标、控件名、实现步骤和在平台上怎么试,第一次打开一个实验时自动弹出。面板在工具栏下面,可以开着做。</li>
<li>
作业的起点有两种:<b>界面已做好</b>(只写事件和代码)、<b>空白工程</b>(从搭界面做起)。控件名照书上的写,自动评分按书上的控件名操作你的程序。
</li>
</ul>
<figure class="shot">
<a href="/help-img/assignments.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/assignments.webp" alt="" loading="lazy" /></a>
<figcaption>我的作业:点作业名开始做,右边是提交状态和得分</figcaption>
</figure>
<figure class="shot">
<a href="/help-img/overview.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/overview.webp" alt="" loading="lazy" /></a>
<figcaption>实验页:左边是设计器和代码,右边是运行区(学生程序的窗体)和虚拟实训台</figcaption>
</figure>
<figure class="shot">
<a href="/help-img/task.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/task.webp" alt="" loading="lazy" /></a>
<figcaption>任务面板:任务目标、控件名、实现步骤</figcaption>
</figure>
<h3>3. 搭界面</h3>
<ul>
<li>点 <code>Form1.cs [设计]</code> 标签打开窗体设计器,和 Visual Studio 一样用。</li>
<li>
把<b>工具箱</b>里的控件拖到窗体上,或者双击工具箱里的控件:放在选中的分组框、面板(或选中控件所在的容器)左上角,连续双击会依次错开。比窗体还宽的控件(如
LED 显示屏)会自动缩小到放得下。选中控件后在右边的<b>属性</b>里改名称、文字等。
</li>
<li>
<b>双击窗体上的控件</b>生成它的默认事件(如按钮的单击),并跳到代码;其他事件在 <b>⚡ 事件</b> 里双击事件名。定时器等组件显示在窗体下面的组件栏里。
</li>
<li>撤销 Ctrl+Z,重做 Ctrl+Y,删除控件 Delete,方向键微调位置。</li>
</ul>
<figure class="shot">
<a href="/help-img/designer.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/designer.webp" alt="" loading="lazy" /></a>
<figcaption>窗体设计器:左边工具箱,中间窗体,右边属性和事件(这里选中了"打开"按钮,它的单击事件是 btn_open_Click)</figcaption>
</figure>
<h3>4. 写代码、运行</h3>
<ul>
<li><b>F5</b> 或 <b>▶ 运行</b>:编译并运行,窗体显示在右边的运行区;<b>Shift+F5</b> 或 <b>■ 停止</b> 结束程序。</li>
<li>编译错误显示在窗体下面,点它跳到出错的代码;常见错误会给出中文<b>提示</b>。</li>
<li>程序运行时出错(比如文本框是空的就转换成数字),窗体下面显示中文说明和出错的文件、行号,点它跳到那一行。</li>
<li><code>Console.WriteLine</code> 的输出、程序保存的图片(项目 4 的拍照)也显示在窗体下面。</li>
<li>代码改了 1 秒后自动保存到服务器(工具栏显示"已保存"),换电脑登录也能接着做。</li>
<li>窗体太大时运行区会按比例缩小;点运行区右上角的<b>放大</b>让运行区占满整个网页,放大后也可以点<b>停止</b>,Esc 或<b>还原</b>回来。</li>
</ul>
<figure class="shot">
<a href="/help-img/error.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/error.webp" alt="" loading="lazy" /></a>
<figcaption>运行出错:窗体下面用中文说明原因和出错的行,点它跳到代码</figcaption>
</figure>
<h3>5. 虚拟实训台</h3>
<ul>
<li>运行区下面是虚拟实训台,代替书上的实物设备。程序打开的串口:COM2 → ADAM-4017+,COM3 → ADAM-4150,COM4 → ZigBee 协调器,COM5 → LED 屏。</li>
<li>拖动滑块(或点一下滑块再按方向键)调温度、湿度、光照;点人体红外、烟雾、火焰、红外对射切换有无。程序控制的灯、警示灯、LED 屏会跟着变化。</li>
<li>
两盏照明灯:<b>照明灯 1</b> 接 ZigBee 继电器节点 1(项目 3 的路灯),<b>照明灯 2</b> 接 ADAM-4150 的 DO1(项目 7 的教室、寝室、会议室);警示灯接
ADAM-4150 的 DO0。
</li>
<li>时钟可以拨到任意时刻、加快到 10 倍或 60 倍,程序里的 <code>DateTime.Now</code> 跟着它走(情景控制的任务用得到)。</li>
<li><b>实训台复位</b>:关掉所有灯、清空 LED 屏,传感器回到默认值。<b>收起</b>:实训台缩成一行,给窗体腾地方。</li>
</ul>
<figure class="shot">
<a href="/help-img/board.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/board.webp" alt="" loading="lazy" /></a>
<figcaption>虚拟实训台:程序打开了照明灯 2(ADAM-4150 DO1);拖滑块调温湿度、光照,点卡片切换传感器</figcaption>
</figure>
<h3>6. 自己检查、提交</h3>
<ul>
<li>
<b>任务</b
>面板下面是<b>评价项</b>:这个任务要自动检查哪些功能;点<b>自己检查</b>,平台按评分规则试运行你的程序,告诉你哪项没通过、为什么。不计分,可以检查很多次。
</li>
<li>做作业时点<b>提交</b>,平台自动评分,几十秒内出结果(全班同时提交时要排队)。截止前可以改了再交,以最后一次为准。</li>
<li>点工具栏上的分数,看每一项的得分;老师评阅后,这里能看到老师的打分和评语。</li>
</ul>
<figure class="shot">
<a href="/help-img/check.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/check.webp" alt="" loading="lazy" /></a>
<figcaption>任务面板最下面的"自己检查":逐项显示通过没有</figcaption>
</figure>
<figure class="shot">
<a href="/help-img/result.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/result.webp" alt="" loading="lazy" /></a>
<figcaption>提交后点工具栏上的分数看评分结果</figcaption>
</figure>
<h3>7. 数据库(项目 6、8)</h3>
<ul>
<li>点右上角的<b>数据库</b>(在新标签页打开),代替书上的 SSMS:右键新建数据库、新建表,<b>新建查询</b>写 SQL,按 F5 执行。</li>
<li>每个人有自己的一套数据库,只有自己能看到,一直保留。程序里的连接字符串只看数据库名,服务器名、账号密码照书上写就行。</li>
<li>数据弄乱了:点<b>恢复实验初始数据</b>,选实验(默认是刚才做的实验),把这个实验用到的库换回初始数据(其他库不动)。</li>
<li>点<b>← 返回实验</b>回到刚才做的实验。</li>
</ul>
<figure class="shot">
<a href="/help-img/db.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/db.webp" alt="" loading="lazy" /></a>
<figcaption>数据库页面:左边是对象资源管理器,右边写 SQL、按 F5 执行,下面是结果</figcaption>
</figure>
</section>
<section v-if="currentUser?.role === 'teacher'" id="teacher">
<h2>老师</h2>
<h3>1. 建班、导入名单</h3>
<ul>
<li>右上角<b>班级管理</b> → <b>班级 + 新建</b>,输入班级名。</li>
<li>
<b>学生</b>标签页 → <b>导入名单(CSV)</b>。CSV 两列:用户名、密码(可以点<b>下载名单模板</b>),用户名就是学生姓名,前面带的班级代号(如
ks241)会自动去掉;Excel 另存为 CSV 即可,GBK、UTF-8 都行。密码留空时自动生成 6 位数字。
</li>
<li>导入后点<b>导出名单(含密码)</b>,打印或发给学生。学生忘了密码,在名单里点<b>重置密码</b>。</li>
</ul>
<figure class="shot">
<a href="/help-img/students.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/students.webp" alt="" loading="lazy" /></a>
<figcaption>班级管理:导入名单后,用户名和密码都在这里,可以导出、重置密码</figcaption>
</figure>
<h3>2. 布置作业</h3>
<ul>
<li><b>作业</b>标签页 → <b>布置作业</b>:选实验、起点(界面已做好 / 空白工程)、截止时间(可以不限)。</li>
<li>自动评分项默认每项 10 分;老师评分项(界面、注释、命名)由你在评阅时打分,可以增删、改分值。</li>
<li><b>任务说明</b>预填实验的说明,可以改写,比如在最前面加一段"这次只做前 3 步";布置后也能在<b>修改</b>里改。</li>
</ul>
<figure class="shot">
<a href="/help-img/assign.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/assign.webp" alt="" loading="lazy" /></a>
<figcaption>布置作业:选实验和起点,自动评分项、任务说明、老师评分项都可以改</figcaption>
</figure>
<h3>3. 评阅、成绩</h3>
<ul>
<li>作业列表里点<b>评阅</b>:左边是全班学生,右边是选中学生的界面截图、代码、自动评分结果和规范提示。</li>
<li><b>▶ 运行</b>标签页直接运行学生的程序,可以操作实训台(改动不保存)。</li>
<li>配置了 AI 评阅时,右边有<b>AI 建议</b>的分数和评语,点<b>采纳 AI 建议</b>填进表单,改好后<b>保存并看下一个</b>。</li>
<li><b>成绩</b>标签页是全班 × 全部作业的总分,<b>导出成绩表(CSV)</b>用 Excel 打开不乱码。</li>
</ul>
<figure class="shot">
<a href="/help-img/review.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/review.webp" alt="" loading="lazy" /></a>
<figcaption>评阅:左边是学生列表,中间看界面截图、运行程序、看代码,右边打分写评语</figcaption>
</figure>
<figure class="shot">
<a href="/help-img/grades.webp" title="点击放大" @click.prevent="zoom"><img src="/help-img/grades.webp" alt="" loading="lazy" /></a>
<figcaption>成绩:全班 × 全部作业的总分,"待评"表示老师还没打分</figcaption>
</figure>
<h3>4. 上课前后</h3>
<ul>
<li>第一次用之前,让学生提前打开一次网站:实验页第一次打开要下载约 1.5 MB,之后浏览器会缓存;全班同时第一次打开时会慢一些。</li>
<li>上课时间不要更新平台(推送代码):更新会重启平台,正在运行的学生程序会结束(页面会提示并自动重连)。</li>
<li>全班同时"自己检查"或提交时要排队,项目 8 这种大任务最后一个人大约等 1.5 分钟。</li>
<li>重要节点前后备份数据:在服务器上执行 <code>deploy/backup.sh</code>(说明见 deploy/README.md)。</li>
</ul>
</section>
<section id="faq">
<h2>常见问题</h2>
<dl>
<dt>点了运行,只显示"已停止",没有窗体</dt>
<dd>代码有编译错误:看运行区窗体下面的红字,点它跳到出错的地方,照着<b>提示</b>改。</dd>
<dt>窗体上的按钮点了没反应</dt>
<dd>看运行区有没有显示"与服务器的连接断开了"。断开后程序已经结束,等它自动连上,再按 F5 重新运行。</dd>
<dt>代码改乱了,想重来</dt>
<dd>工具栏的<b>恢复原始代码</b>(做作业时是<b>恢复到作业起点</b>)把代码换回起点;已经提交的不受影响。</dd>
<dt>登录时提示密码输错太多次</dt>
<dd>同一个账号连续输错 10 次要等 10 分钟,或者请老师在名单里查看、重置密码。</dd>
<dt>网页打不开、一片空白</dt>
<dd>换新版的 Chrome 或 Edge</dd>
<dt>评分说"找不到名为 … 的控件"</dt>
<dd>控件名要和书上的一样(注意大小写),在设计器的属性里改<b>名称</b>;改名后代码里用到旧名字的地方也要改。</dd>
</dl>
</section>
</main>
<div v-if="zoomed" class="zoom" @click="zoomed = null">
<img :src="zoomed.src" alt="" @load="fit" />
<div class="zoom-caption">{{ zoomed.caption }}(点任意处或按 Esc 关闭)</div>
</div>
</div>
</template>
<style scoped>
.page {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.toolbar {
display: flex;
align-items: center;
gap: 12px;
padding: 8px 16px;
border-bottom: 1px solid #e5e7eb;
}
.title {
color: #374151;
}
.spacer {
flex: 1;
}
.nav-link,
.toc a {
color: #2563eb;
font-size: 14px;
text-decoration: none;
}
.content {
width: 100%;
max-width: 800px;
margin: 0 auto;
padding: 16px 16px 64px;
box-sizing: border-box;
font-size: 15px;
line-height: 1.8;
color: #1f2937;
}
.toc {
display: flex;
gap: 16px;
margin-bottom: 8px;
}
h2 {
margin: 32px 0 8px;
padding-bottom: 4px;
border-bottom: 1px solid #e5e7eb;
font-size: 20px;
}
h3 {
margin: 20px 0 4px;
font-size: 16px;
}
p,
ul {
margin: 4px 0;
}
ul {
padding-left: 22px;
}
code {
padding: 0 4px;
border-radius: 3px;
background: #f3f4f6;
font-size: 13px;
}
/* 截图:按原尺寸显示,比正文宽时缩小;点击在页面上放大 */
.shot {
margin: 12px 0 16px;
}
.shot img {
display: block;
max-width: 100%;
height: auto;
border: 1px solid #e5e7eb;
border-radius: 4px;
box-shadow: 0 1px 4px rgb(0 0 0 / 0.08);
}
.shot a {
cursor: zoom-in;
}
.zoom {
position: fixed;
inset: 0;
z-index: 100;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;
padding: 16px;
background: rgb(0 0 0 / 0.88);
cursor: zoom-out;
}
.zoom img {
max-width: 100%;
border-radius: 4px;
background: #fff;
}
.zoom-caption {
color: #fff;
font-size: 14px;
}
.shot figcaption {
margin-top: 4px;
font-size: 13px;
color: #6b7280;
}
dt {
margin-top: 12px;
font-weight: 600;
}
dd {
margin: 0 0 0 22px;
}
@media print {
.toolbar,
.toc {
display: none;
}
}
</style>