From f6024dc1130485ce7766ec9d06da92174630551b Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Tue, 27 Oct 2026 08:49:42 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=95=E7=94=A8=E5=89=8D=E8=B5=B0=E6=9F=A5?= =?UTF-8?q?=E7=9A=84=E4=BF=AE=E6=94=B9=EF=BC=9A=E6=8A=A5=E9=94=99=E7=9C=8B?= =?UTF-8?q?=E5=BE=97=E8=A7=81=E3=80=81=E5=AD=A6=E7=94=9F=E6=89=BE=E5=BE=97?= =?UTF-8?q?=E5=88=B0=E4=BD=9C=E4=B8=9A=E3=80=81=E8=BF=90=E8=A1=8C=E5=8C=BA?= =?UTF-8?q?=E5=92=8C=E8=AE=BE=E8=AE=A1=E5=99=A8=E7=9A=84=E8=8B=A5=E5=B9=B2?= =?UTF-8?q?=E4=BD=93=E9=AA=8C=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 运行区:编译错误、运行异常、控制台输出和保存的图片移到窗体下面,不再被实训台挤成 0 高;缩放和放大按钮移到桌面上方,不压窗体的关闭按钮;放大后也能停止程序;点停止后清掉窗体 - 运行异常:常见 .NET 异常配中文说明,显示出错的文件、行号和方法,点击跳到代码 - 运行中的下拉列表挂到页面最外层,能伸出窗体和分组框(小窗体也能选到 COM4、COM5) - 学生登录后进"我的作业";任务面板从工具栏下面开始,不挡导航;记住上次做的实验,从数据库页面返回、恢复数据时默认用它 - 代码页和设计页左栏都占 3/5,文件标签放不下时换行;实验选择框加宽;关闭粘性滚动 - 设计器:双击生成的事件方法带缩进;双击工具箱放进选中控件所在的容器并错开位置;新控件比容器宽时按比例缩小;无边框窗体不画标题栏 - 中文界面:代码编辑器(查找替换等)、属性窗口的颜色选项 - SQL:DATEADD、DATEDIFF、DATEPART 的日期单位(day、hour)解析成 IdentifierLiteral 时报"不支持",补上 - 项目 8 的预置环境数据改成建库那天之前的 7 天;p6-t3 评分项改为"按日期查询环境数据" - 没有 AI 建议时不显示"全部采纳 AI 建议"和相关说明;导出 CSV 只给纯数字的文字加制表符 Co-Authored-By: Claude Opus 5.5 --- runtime/Sim.Data/Engine/Translator.cs | 3 +- runtime/Sim.WinForms/Host/SimHost.cs | 50 +++++- samples/p6-t3-按时间查询/checks.yaml | 2 +- samples/p8-t3-环境采集与分析/database.sql | 86 +++++------ samples/p8-t4-校园安防/database.sql | 86 +++++------ samples/p8-t5-历史图片/database.sql | 86 +++++------ server/test/runner.test.ts | 41 +++++ shared/protocol.ts | 3 +- web/src/auth.ts | 1 + web/src/designer/FormDesigner.vue | 43 ++++-- web/src/designer/PropertyGrid.vue | 4 +- web/src/designer/code.test.ts | 6 +- web/src/designer/code.ts | 4 +- web/src/designer/values.ts | 24 +++ web/src/editor/CodeEditor.vue | 2 + web/src/editor/monaco.ts | 2 + web/src/grading/TaskPanel.vue | 8 + web/src/pages/DatabasePage.vue | 5 +- web/src/pages/HelpPage.vue | 4 +- web/src/pages/LoginPage.vue | 6 +- web/src/pages/ReviewPage.vue | 7 +- web/src/pages/TeacherPage.vue | 4 +- web/src/pages/WorkbenchPage.vue | 24 +-- web/src/run/RunArea.vue | 176 ++++++++++++++-------- web/src/run/session.ts | 23 ++- web/src/samples.ts | 21 ++- web/src/teacher/GradebookPanel.vue | 12 +- web/src/teacher/csv.ts | 5 +- web/src/winforms/ControlView.vue | 44 +++++- web/src/winforms/winforms.css | 10 +- 30 files changed, 537 insertions(+), 255 deletions(-) diff --git a/runtime/Sim.Data/Engine/Translator.cs b/runtime/Sim.Data/Engine/Translator.cs index 8c062de..e8c27df 100644 --- a/runtime/Sim.Data/Engine/Translator.cs +++ b/runtime/Sim.Data/Engine/Translator.cs @@ -802,9 +802,10 @@ internal sealed class Translator } } - /// DATEADD(day, ...) 的第一个参数是关键字,解析成列名 + /// DATEADD(day, ...) 的第一个参数是关键字:ScriptDom 解析成 IdentifierLiteral(旧版本是列名) private static string DatePartName(ScalarExpression expression) => expression switch { + IdentifierLiteral i => i.Value, ColumnReferenceExpression c => c.MultiPartIdentifier.Identifiers[^1].Value, StringLiteral s => s.Value, _ => throw SqlException.NotSupported("这种 datepart 写法"), diff --git a/runtime/Sim.WinForms/Host/SimHost.cs b/runtime/Sim.WinForms/Host/SimHost.cs index cac9264..43da78b 100644 --- a/runtime/Sim.WinForms/Host/SimHost.cs +++ b/runtime/Sim.WinForms/Host/SimHost.cs @@ -134,12 +134,54 @@ public static class SimHost public static void ReportException(Exception ex) { while (ex is TargetInvocationException { InnerException: not null } wrapper) ex = wrapper.InnerException!; - Send(new JsonObject + var type = ex.GetType().FullName; + // 仿真库自己抛的异常信息已经是中文;.NET 自带的是英文,常见的几种配上中文说明,原文放在括号里 + var message = HasChinese(ex.Message) ? $"{ex.Message}({type})" + : ExplainException(ex) is { } explained ? $"{explained}({type}: {ex.Message})" + : $"{type}: {ex.Message}"; + var frame = StudentFrame(ex); + var result = new JsonObject { ["type"] = "exception", - ["message"] = $"{ex.GetType().FullName}: {ex.Message}", - ["detail"] = StudentStackTrace(ex), - }); + ["message"] = message, + ["detail"] = frame is { } f ? $"出错位置:{f.File} 第 {f.Line} 行({f.Method} 方法)" : StudentStackTrace(ex), + }; + if (frame is { } at) + { + result["file"] = at.File; + result["line"] = at.Line; + } + Send(result); + } + + private static bool HasChinese(string text) => text.Any(c => c >= '\u4e00' && c <= '\u9fff'); + + private static string? ExplainException(Exception ex) => ex switch + { + FormatException => "文字转换成数字或日期时格式不对,比如文本框是空的,或者里面不是数字", + NullReferenceException => "用到的对象是 null:变量还没有赋值,或者对象、窗体还没有 new 出来", + IndexOutOfRangeException => "数组的下标超出了范围:下标从 0 开始,最大是长度减 1", + ArgumentOutOfRangeException => "下标或参数超出了范围,比如列表、字符串的下标太大,或者下拉框还没有选中", + DivideByZeroException => "整数除以了 0", + OverflowException => "数字太大或太小,超出了这个类型能表示的范围", + InvalidCastException => "类型转换失败,这个对象不能转换成要求的类型", + KeyNotFoundException => "字典里没有这个键", + FileNotFoundException => "找不到这个文件", + DirectoryNotFoundException => "找不到这个文件夹", + _ => null, + }; + + /// 堆栈里离出错点最近的一行学生代码:文件名、行号、方法名 + private static (string File, int Line, string Method)? StudentFrame(Exception ex) + { + foreach (var frame in new System.Diagnostics.StackTrace(ex, true).GetFrames()) + { + var file = frame.GetFileName(); + var line = frame.GetFileLineNumber(); + if (file == null || line <= 0 || file.Contains("/runtime/Sim.")) continue; + return (Path.GetFileName(file), line, frame.GetMethod()?.Name ?? ""); + } + return null; } /// 只保留学生代码的堆栈行,去掉仿真库内部的调用 diff --git a/samples/p6-t3-按时间查询/checks.yaml b/samples/p6-t3-按时间查询/checks.yaml index 9f02cae..964a5f8 100644 --- a/samples/p6-t3-按时间查询/checks.yaml +++ b/samples/p6-t3-按时间查询/checks.yaml @@ -1,7 +1,7 @@ # 评分规则:书上评价表的功能项。每项单独启动一次程序(使用 database.sql 建的初始数据库),按步骤操作,核对结果。 # 初始数据有 3 行:2024-01-16 09:00、2024-01-18 14:30、2024-01-23 08:15 # 格式说明见 server/src/grading/checks.ts -- title: 能实现按日期查询灾情数据 +- title: 能实现按日期查询环境数据 steps: - pick: { control: StartTime, value: '2024-01-15' } - pick: { control: EndTime, value: '2024-01-20' } diff --git a/samples/p8-t3-环境采集与分析/database.sql b/samples/p8-t3-环境采集与分析/database.sql index 2e5eeba..9d8b460 100644 --- a/samples/p8-t3-环境采集与分析/database.sql +++ b/samples/p8-t3-环境采集与分析/database.sql @@ -1,5 +1,5 @@ -- 实验的初始数据库 WisdomCampus(教材"综合实训"附带的库):环境数据表 EnvironmentData、报警图片表 SecurityData、用户表 Users。 --- EnvironmentData 预置了 7 天的历史数据,"数据分析"的图表一打开就有内容;SecurityData 是空的,拍照或有人入侵时才有记录。 +-- EnvironmentData 预置了今天之前 7 天的历史数据(按建库那天往前推),"数据分析"的图表一打开就有最近一周的内容;SecurityData 是空的,拍照或有人入侵时才有记录。 -- 学生可以在数据库页面"恢复实验初始数据";评分时每个检查项用一份新的。 CREATE DATABASE WisdomCampus GO @@ -10,45 +10,45 @@ CREATE TABLE EnvironmentData (Id int IDENTITY(1,1) PRIMARY KEY, Fire bit NOT NUL CREATE TABLE SecurityData (Id int IDENTITY(1,1) PRIMARY KEY, EvenTime datetime NOT NULL, EvenImage image NOT NULL) GO INSERT INTO Users (UserName, Password) VALUES ('admin', '123') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 58, 258, '2026-10-14 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.1, 53, 475, '2026-10-14 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 761, '2026-10-14 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.5, 49, 733, '2026-10-14 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 54, 528, '2026-10-14 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 283, '2026-10-14 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.9, 59, 261, '2026-10-15 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 53, 499, '2026-10-15 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 764, '2026-10-15 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.5, 47, 778, '2026-10-15 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 503, '2026-10-15 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 56, 218, '2026-10-15 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 13.9, 63, 258, '2026-10-16 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 60, 477, '2026-10-16 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 741, '2026-10-16 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.5, 54, 796, '2026-10-16 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 488, '2026-10-16 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 59, 214, '2026-10-16 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 11.9, 67, 234, '2026-10-17 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 63, 544, '2026-10-17 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.3, 60, 804, '2026-10-17 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.5, 54, 801, '2026-10-17 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.8, 59, 524, '2026-10-17 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 58, 286, '2026-10-17 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.4, 59, 250, '2026-10-18 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 55, 533, '2026-10-18 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.3, 50, 749, '2026-10-18 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 24, 48, 766, '2026-10-18 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.8, 54, 534, '2026-10-18 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.1, 53, 241, '2026-10-18 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.4, 54, 253, '2026-10-19 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.1, 50, 474, '2026-10-19 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.3, 48, 778, '2026-10-19 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 26, 46, 783, '2026-10-19 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.3, 50, 520, '2026-10-19 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.6, 50, 213, '2026-10-19 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 62, 230, '2026-10-20 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.6, 52, 471, '2026-10-20 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 53, 751, '2026-10-20 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.5, 48, 747, '2026-10-20 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 527, '2026-10-20 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 220, '2026-10-20 18:00:00') +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 58, 258, DATEADD(hour, 8, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.1, 53, 475, DATEADD(hour, 10, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 761, DATEADD(hour, 12, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.5, 49, 733, DATEADD(hour, 14, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 54, 528, DATEADD(hour, 16, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 283, DATEADD(hour, 18, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.9, 59, 261, DATEADD(hour, 8, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 53, 499, DATEADD(hour, 10, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 764, DATEADD(hour, 12, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.5, 47, 778, DATEADD(hour, 14, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 503, DATEADD(hour, 16, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 56, 218, DATEADD(hour, 18, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 13.9, 63, 258, DATEADD(hour, 8, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 60, 477, DATEADD(hour, 10, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 741, DATEADD(hour, 12, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.5, 54, 796, DATEADD(hour, 14, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 488, DATEADD(hour, 16, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 59, 214, DATEADD(hour, 18, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 11.9, 67, 234, DATEADD(hour, 8, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 63, 544, DATEADD(hour, 10, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.3, 60, 804, DATEADD(hour, 12, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.5, 54, 801, DATEADD(hour, 14, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.8, 59, 524, DATEADD(hour, 16, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 58, 286, DATEADD(hour, 18, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.4, 59, 250, DATEADD(hour, 8, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 55, 533, DATEADD(hour, 10, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.3, 50, 749, DATEADD(hour, 12, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 24, 48, 766, DATEADD(hour, 14, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.8, 54, 534, DATEADD(hour, 16, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.1, 53, 241, DATEADD(hour, 18, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.4, 54, 253, DATEADD(hour, 8, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.1, 50, 474, DATEADD(hour, 10, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.3, 48, 778, DATEADD(hour, 12, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 26, 46, 783, DATEADD(hour, 14, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.3, 50, 520, DATEADD(hour, 16, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.6, 50, 213, DATEADD(hour, 18, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 62, 230, DATEADD(hour, 8, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.6, 52, 471, DATEADD(hour, 10, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 53, 751, DATEADD(hour, 12, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.5, 48, 747, DATEADD(hour, 14, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 527, DATEADD(hour, 16, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 220, DATEADD(hour, 18, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) diff --git a/samples/p8-t4-校园安防/database.sql b/samples/p8-t4-校园安防/database.sql index 2e5eeba..9d8b460 100644 --- a/samples/p8-t4-校园安防/database.sql +++ b/samples/p8-t4-校园安防/database.sql @@ -1,5 +1,5 @@ -- 实验的初始数据库 WisdomCampus(教材"综合实训"附带的库):环境数据表 EnvironmentData、报警图片表 SecurityData、用户表 Users。 --- EnvironmentData 预置了 7 天的历史数据,"数据分析"的图表一打开就有内容;SecurityData 是空的,拍照或有人入侵时才有记录。 +-- EnvironmentData 预置了今天之前 7 天的历史数据(按建库那天往前推),"数据分析"的图表一打开就有最近一周的内容;SecurityData 是空的,拍照或有人入侵时才有记录。 -- 学生可以在数据库页面"恢复实验初始数据";评分时每个检查项用一份新的。 CREATE DATABASE WisdomCampus GO @@ -10,45 +10,45 @@ CREATE TABLE EnvironmentData (Id int IDENTITY(1,1) PRIMARY KEY, Fire bit NOT NUL CREATE TABLE SecurityData (Id int IDENTITY(1,1) PRIMARY KEY, EvenTime datetime NOT NULL, EvenImage image NOT NULL) GO INSERT INTO Users (UserName, Password) VALUES ('admin', '123') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 58, 258, '2026-10-14 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.1, 53, 475, '2026-10-14 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 761, '2026-10-14 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.5, 49, 733, '2026-10-14 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 54, 528, '2026-10-14 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 283, '2026-10-14 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.9, 59, 261, '2026-10-15 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 53, 499, '2026-10-15 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 764, '2026-10-15 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.5, 47, 778, '2026-10-15 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 503, '2026-10-15 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 56, 218, '2026-10-15 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 13.9, 63, 258, '2026-10-16 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 60, 477, '2026-10-16 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 741, '2026-10-16 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.5, 54, 796, '2026-10-16 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 488, '2026-10-16 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 59, 214, '2026-10-16 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 11.9, 67, 234, '2026-10-17 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 63, 544, '2026-10-17 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.3, 60, 804, '2026-10-17 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.5, 54, 801, '2026-10-17 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.8, 59, 524, '2026-10-17 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 58, 286, '2026-10-17 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.4, 59, 250, '2026-10-18 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 55, 533, '2026-10-18 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.3, 50, 749, '2026-10-18 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 24, 48, 766, '2026-10-18 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.8, 54, 534, '2026-10-18 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.1, 53, 241, '2026-10-18 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.4, 54, 253, '2026-10-19 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.1, 50, 474, '2026-10-19 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.3, 48, 778, '2026-10-19 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 26, 46, 783, '2026-10-19 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.3, 50, 520, '2026-10-19 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.6, 50, 213, '2026-10-19 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 62, 230, '2026-10-20 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.6, 52, 471, '2026-10-20 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 53, 751, '2026-10-20 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.5, 48, 747, '2026-10-20 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 527, '2026-10-20 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 220, '2026-10-20 18:00:00') +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 58, 258, DATEADD(hour, 8, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.1, 53, 475, DATEADD(hour, 10, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 761, DATEADD(hour, 12, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.5, 49, 733, DATEADD(hour, 14, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 54, 528, DATEADD(hour, 16, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 283, DATEADD(hour, 18, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.9, 59, 261, DATEADD(hour, 8, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 53, 499, DATEADD(hour, 10, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 764, DATEADD(hour, 12, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.5, 47, 778, DATEADD(hour, 14, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 503, DATEADD(hour, 16, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 56, 218, DATEADD(hour, 18, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 13.9, 63, 258, DATEADD(hour, 8, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 60, 477, DATEADD(hour, 10, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 741, DATEADD(hour, 12, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.5, 54, 796, DATEADD(hour, 14, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 488, DATEADD(hour, 16, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 59, 214, DATEADD(hour, 18, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 11.9, 67, 234, DATEADD(hour, 8, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 63, 544, DATEADD(hour, 10, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.3, 60, 804, DATEADD(hour, 12, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.5, 54, 801, DATEADD(hour, 14, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.8, 59, 524, DATEADD(hour, 16, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 58, 286, DATEADD(hour, 18, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.4, 59, 250, DATEADD(hour, 8, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 55, 533, DATEADD(hour, 10, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.3, 50, 749, DATEADD(hour, 12, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 24, 48, 766, DATEADD(hour, 14, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.8, 54, 534, DATEADD(hour, 16, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.1, 53, 241, DATEADD(hour, 18, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.4, 54, 253, DATEADD(hour, 8, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.1, 50, 474, DATEADD(hour, 10, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.3, 48, 778, DATEADD(hour, 12, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 26, 46, 783, DATEADD(hour, 14, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.3, 50, 520, DATEADD(hour, 16, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.6, 50, 213, DATEADD(hour, 18, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 62, 230, DATEADD(hour, 8, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.6, 52, 471, DATEADD(hour, 10, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 53, 751, DATEADD(hour, 12, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.5, 48, 747, DATEADD(hour, 14, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 527, DATEADD(hour, 16, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 220, DATEADD(hour, 18, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) diff --git a/samples/p8-t5-历史图片/database.sql b/samples/p8-t5-历史图片/database.sql index 2e5eeba..9d8b460 100644 --- a/samples/p8-t5-历史图片/database.sql +++ b/samples/p8-t5-历史图片/database.sql @@ -1,5 +1,5 @@ -- 实验的初始数据库 WisdomCampus(教材"综合实训"附带的库):环境数据表 EnvironmentData、报警图片表 SecurityData、用户表 Users。 --- EnvironmentData 预置了 7 天的历史数据,"数据分析"的图表一打开就有内容;SecurityData 是空的,拍照或有人入侵时才有记录。 +-- EnvironmentData 预置了今天之前 7 天的历史数据(按建库那天往前推),"数据分析"的图表一打开就有最近一周的内容;SecurityData 是空的,拍照或有人入侵时才有记录。 -- 学生可以在数据库页面"恢复实验初始数据";评分时每个检查项用一份新的。 CREATE DATABASE WisdomCampus GO @@ -10,45 +10,45 @@ CREATE TABLE EnvironmentData (Id int IDENTITY(1,1) PRIMARY KEY, Fire bit NOT NUL CREATE TABLE SecurityData (Id int IDENTITY(1,1) PRIMARY KEY, EvenTime datetime NOT NULL, EvenImage image NOT NULL) GO INSERT INTO Users (UserName, Password) VALUES ('admin', '123') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 58, 258, '2026-10-14 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.1, 53, 475, '2026-10-14 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 761, '2026-10-14 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.5, 49, 733, '2026-10-14 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 54, 528, '2026-10-14 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 283, '2026-10-14 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.9, 59, 261, '2026-10-15 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 53, 499, '2026-10-15 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 764, '2026-10-15 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.5, 47, 778, '2026-10-15 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 503, '2026-10-15 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 56, 218, '2026-10-15 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 13.9, 63, 258, '2026-10-16 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 60, 477, '2026-10-16 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 741, '2026-10-16 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.5, 54, 796, '2026-10-16 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 488, '2026-10-16 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 59, 214, '2026-10-16 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 11.9, 67, 234, '2026-10-17 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 63, 544, '2026-10-17 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.3, 60, 804, '2026-10-17 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.5, 54, 801, '2026-10-17 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.8, 59, 524, '2026-10-17 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 58, 286, '2026-10-17 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.4, 59, 250, '2026-10-18 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 55, 533, '2026-10-18 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.3, 50, 749, '2026-10-18 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 24, 48, 766, '2026-10-18 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.8, 54, 534, '2026-10-18 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.1, 53, 241, '2026-10-18 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.4, 54, 253, '2026-10-19 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.1, 50, 474, '2026-10-19 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.3, 48, 778, '2026-10-19 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 26, 46, 783, '2026-10-19 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.3, 50, 520, '2026-10-19 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.6, 50, 213, '2026-10-19 18:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 62, 230, '2026-10-20 08:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.6, 52, 471, '2026-10-20 10:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 53, 751, '2026-10-20 12:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.5, 48, 747, '2026-10-20 14:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 527, '2026-10-20 16:00:00') -INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 220, '2026-10-20 18:00:00') +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 58, 258, DATEADD(hour, 8, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.1, 53, 475, DATEADD(hour, 10, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 761, DATEADD(hour, 12, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.5, 49, 733, DATEADD(hour, 14, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 54, 528, DATEADD(hour, 16, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 283, DATEADD(hour, 18, DATEADD(day, -7, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.9, 59, 261, DATEADD(hour, 8, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 53, 499, DATEADD(hour, 10, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 764, DATEADD(hour, 12, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.5, 47, 778, DATEADD(hour, 14, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.8, 52, 503, DATEADD(hour, 16, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 56, 218, DATEADD(hour, 18, DATEADD(day, -6, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 13.9, 63, 258, DATEADD(hour, 8, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 60, 477, DATEADD(hour, 10, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.8, 51, 741, DATEADD(hour, 12, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.5, 54, 796, DATEADD(hour, 14, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 488, DATEADD(hour, 16, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.6, 59, 214, DATEADD(hour, 18, DATEADD(day, -5, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 11.9, 67, 234, DATEADD(hour, 8, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 63, 544, DATEADD(hour, 10, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.3, 60, 804, DATEADD(hour, 12, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.5, 54, 801, DATEADD(hour, 14, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.8, 59, 524, DATEADD(hour, 16, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.1, 58, 286, DATEADD(hour, 18, DATEADD(day, -4, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 16.4, 59, 250, DATEADD(hour, 8, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.6, 55, 533, DATEADD(hour, 10, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.3, 50, 749, DATEADD(hour, 12, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 24, 48, 766, DATEADD(hour, 14, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.8, 54, 534, DATEADD(hour, 16, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.1, 53, 241, DATEADD(hour, 18, DATEADD(day, -3, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.4, 54, 253, DATEADD(hour, 8, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.1, 50, 474, DATEADD(hour, 10, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 22.3, 48, 778, DATEADD(hour, 12, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 26, 46, 783, DATEADD(hour, 14, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 23.3, 50, 520, DATEADD(hour, 16, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 20.6, 50, 213, DATEADD(hour, 18, DATEADD(day, -2, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 15.9, 62, 230, DATEADD(hour, 8, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 18.6, 52, 471, DATEADD(hour, 10, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 53, 751, DATEADD(hour, 12, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 21.5, 48, 747, DATEADD(hour, 14, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 19.3, 55, 527, DATEADD(hour, 16, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) +INSERT INTO EnvironmentData (Fire, Smoke, Temperature, Humidity, Light, _Time) VALUES (0, 0, 17.1, 57, 220, DATEADD(hour, 18, DATEADD(day, -1, CONVERT(varchar(10), GETDATE(), 120)))) diff --git a/server/test/runner.test.ts b/server/test/runner.test.ts index 3df6df1..77d74d9 100644 --- a/server/test/runner.test.ts +++ b/server/test/runner.test.ts @@ -806,3 +806,44 @@ test.skipIf(config.sandbox === 'none')( }, 30000, ) + +test('运行时异常:常见的 .NET 异常配中文说明,带出错的文件、行号和方法', async () => { + const { runner } = await runMain( + 'exception', + ` + Console.WriteLine("start"); + int n = int.Parse("abc");`, + ) + const error = await runner.next('exception') + expect(error.message).toStartWith('文字转换成数字或日期时格式不对') + expect(error.message).toContain('System.FormatException') + expect(error).toMatchObject({ file: 'Program.cs', line: 11 }) + expect(error.detail).toBe('出错位置:Program.cs 第 11 行(Main 方法)') +}, 30000) + +test('数据库:DATEADD、DATEDIFF、DATEPART 的日期单位写成关键字(day、hour)', async () => { + const dbDir = resolve(ROOT, '.runs', 'test-dateadd-db') + await rm(dbDir, { recursive: true, force: true }) + await mkdir(dbDir, { recursive: true }) + const { runner } = await runMain( + 'dateadd', + ` + var master = new SqlConnection("Data Source=.;User ID=sa"); + master.Open(); + new SqlCommand("CREATE DATABASE T", master).ExecuteNonQuery(); + var conn = new SqlConnection("Data Source=.;Initial Catalog=T"); + conn.Open(); + foreach (var sql in new[] { + "SELECT DATEADD(hour, 8, DATEADD(day, -7, '2024-01-16'))", + "SELECT DATEDIFF(day, '2024-01-01 23:00', '2024-01-02 01:00')", + "SELECT DATEPART(hh, '2024-01-16 09:05:03')", + }) + Console.WriteLine("result=" + new SqlCommand(sql, conn).ExecuteScalar());`, + 'using System.Data.SqlClient;', + dbDir, + ) + await runner.finished() + const output = runner.messages.flatMap((m) => (m.type === 'console' ? [m.text] : [])).join('') + expect(runner.messages.filter((m) => m.type === 'exception')).toEqual([]) + expect(output).toBe('result=2024/1/9 8:00:00\nresult=1\nresult=9\n') +}, 30000) diff --git a/shared/protocol.ts b/shared/protocol.ts index 37d711c..7554503 100644 --- a/shared/protocol.ts +++ b/shared/protocol.ts @@ -120,7 +120,8 @@ export type RunnerMessage = /** 学生程序操作了实训台输出:led/text、adam4150/do、zigbee/relay、camera/on、camera/pan,data 见 DeviceCtrlHelper.cs、IPCameraHelper.cs */ | { type: 'device'; device: string; action: string; data: unknown } | { type: 'console'; text: string } - | { type: 'exception'; message: string; detail: string } + /** 学生程序没有处理的异常;file、line 是出错的那行学生代码(找得到时才有),网页上点击可以跳过去 */ + | { type: 'exception'; message: string; detail: string; file?: string; line?: number } | { type: 'exited'; code: number } /** diff --git a/web/src/auth.ts b/web/src/auth.ts index bd25ec9..559cee8 100644 --- a/web/src/auth.ts +++ b/web/src/auth.ts @@ -26,6 +26,7 @@ export async function login(username: string, password: string) { const result = await api('POST', '/api/login', { username, password }) setTokens(result) currentUser.value = result.user + return result.user } export async function logout() { diff --git a/web/src/designer/FormDesigner.vue b/web/src/designer/FormDesigner.vue index d04af06..913a6cb 100644 --- a/web/src/designer/FormDesigner.vue +++ b/web/src/designer/FormDesigner.vue @@ -373,15 +373,24 @@ function onDrop(event: DragEvent) { place(d, controlDef(type), x, y) } -/** 双击工具箱:放在选中的容器(或窗体)左上角 */ +/** 双击工具箱:放在选中的容器(选中的是普通控件时放进它所在的容器)左上角,已有控件在那里就往右下错开 */ function onToolDoubleClick(def: ControlDef) { const d = parsed.value.doc if (!d) return - // 直接放进选中的容器,不按坐标判断(左上角可能正好压在另一个分组框上) - const container = !def.component && selected.value && isContainerType(typeOf(d, selected.value) ?? '') ? selected.value : '' - const result = addControl(d, def, container, { x: 12, y: container ? 20 : 12 }) + // 直接放进容器,不按坐标判断(左上角可能正好压在另一个分组框上) + let container = '' + if (!def.component && selected.value) { + container = isContainerType(typeOf(d, selected.value) ?? '') ? selected.value : (listControls(d).find((c) => c.name === selected.value)?.parent ?? '') + } + const location = { x: 12, y: container ? 20 : 12 } + const taken = childrenOf(d, container).map((child) => localRect(d, child)) + while (taken.some((r) => r.x === location.x && r.y === location.y)) { + location.x += 12 + location.y += 12 + } + const result = addControl(d, def, container, location) selected.value = result.name - commit(result.doc) + commit(fitInside(result.doc, result.name, container)) } function place(d: DesignerDocument, def: ControlDef, x: number, y: number) { @@ -389,7 +398,15 @@ function place(d: DesignerDocument, def: ControlDef, x: number, y: number) { const origin = container ? absRect(d, container) : { x: 0, y: 0 } const result = addControl(d, def, container, { x: x - origin.x, y: y - origin.y }) selected.value = result.name - commit(result.doc) + commit(def.component ? result.doc : fitInside(result.doc, result.name, container)) +} + +/** 新控件比容器宽(LED 显示屏默认 800 宽,新窗体只有 300):按比例缩小到右边留出边距,不用学生再去改大小 */ +function fitInside(d: DesignerDocument, name: string, container: string): DesignerDocument { + const rect = localRect(d, name) + const room = (container ? localRect(d, container).width : clientSize.value.width) - rect.x - 12 + if (rect.width <= room || room < 40) return d + return setProp(d, name, 'Size', { kind: 'size', width: room, height: Math.max(20, Math.round((rect.height * room) / rect.width)) }) } // ---------- 属性窗口的回调 ---------- @@ -469,6 +486,7 @@ function onComponentDoubleClick(name: string) { } const formTitle = computed(() => String(tree.value?.props.Text ?? '')) +const borderless = computed(() => tree.value?.props.FormBorderStyle === 'None') const formStyle = computed(() => ({ width: `${clientSize.value.width}px`, height: `${clientSize.value.height}px`, @@ -511,7 +529,9 @@ const noop = () => {}
- 拖动工具箱里的控件到窗体上;双击控件生成事件处理方法;Delete 删除 + 拖动工具箱里的控件到窗体上;双击控件生成事件处理方法;Delete 删除
-
-
+
+ +
{{ displayText(formTitle) }} ─ ☐ ✕
@@ -707,6 +728,10 @@ const noop = () => {} box-shadow: 0 2px 10px rgb(0 0 0 / 0.15); } +.window.borderless { + border-color: transparent; +} + .window.selected { outline: 1px dashed #2563eb; outline-offset: 2px; diff --git a/web/src/designer/PropertyGrid.vue b/web/src/designer/PropertyGrid.vue index 209c998..5865b1f 100644 --- a/web/src/designer/PropertyGrid.vue +++ b/web/src/designer/PropertyGrid.vue @@ -7,7 +7,7 @@ import ChartDialog from './ChartDialog.vue' import type { DesignerDocument } from './document' import { checkName, getEventHandler, getItems, getPropText, typeOf } from './edit' import { resourceNameOf } from './resources' -import { NAMED_COLORS, hexToRgb, parseValue, rgb, type Value } from './values' +import { COLOR_LABELS, NAMED_COLORS, hexToRgb, parseValue, rgb, type Value } from './values' const props = defineProps<{ doc: DesignerDocument @@ -289,7 +289,7 @@ function renameHandler(event: string, value: string) { { const code = 'namespace A\n{\n public partial class F : Form\n {\n }\n}\n' const { code: next, line } = ensureHandler(code, 'F', 'F_Load', 'EventArgs') expect(next).toBe( - 'namespace A\n{\n public partial class F : Form\n {\n private void F_Load(object sender, EventArgs e)\n {\n\n }\n }\n}\n', + 'namespace A\n{\n public partial class F : Form\n {\n private void F_Load(object sender, EventArgs e)\n {\n \n }\n }\n}\n', ) expect(line).toBe(7) }) @@ -33,5 +33,5 @@ test('类里还没有成员时不留多余空行', () => { test('字符串和注释里的大括号不影响查找类的结尾', () => { const code = 'class F\n{\n string s = "}{";\n // }\n char c = \'}\';\n}\n' const { code: next } = ensureHandler(code, 'F', 'F_Load', 'EventArgs') - expect(next.endsWith(" char c = '}';\n\n private void F_Load(object sender, EventArgs e)\n {\n\n }\n}\n")).toBe(true) + expect(next.endsWith(" char c = '}';\n\n private void F_Load(object sender, EventArgs e)\n {\n \n }\n}\n")).toBe(true) }) diff --git a/web/src/designer/code.ts b/web/src/designer/code.ts index 4201c54..584d69a 100644 --- a/web/src/designer/code.ts +++ b/web/src/designer/code.ts @@ -20,7 +20,9 @@ export function ensureHandler(code: string, className: string, handler: string, // 类里已有成员时,与上一个成员之间空一行 const before = code.slice(0, lineStart) const hasMembers = !/\{\s*$/.test(before) - const method = [...(hasMembers ? [''] : []), `${indent}private void ${handler}(object sender, ${args} e)`, `${indent}{`, '', `${indent}}`].join(eol) + // 方法体的空行带好缩进(和 VS 一样),光标跳过去就在缩进后面,学生的代码不会顶格写 + const body = `${indent} ` + const method = [...(hasMembers ? [''] : []), `${indent}private void ${handler}(object sender, ${args} e)`, `${indent}{`, body, `${indent}}`].join(eol) const next = `${before}${method}${eol}${code.slice(lineStart)}` return { code: next, line: lineOf(next, before.length) + (hasMembers ? 3 : 2) } } diff --git a/web/src/designer/values.ts b/web/src/designer/values.ts index 083ebd4..74bd65b 100644 --- a/web/src/designer/values.ts +++ b/web/src/designer/values.ts @@ -134,6 +134,30 @@ export const NAMED_COLORS: Record = { Cyan: '#00ffff', } +/** 属性窗口里颜色的中文名,英文名放在悬停提示里 */ +export const COLOR_LABELS: Record = { + Transparent: '透明', + Black: '黑色', + White: '白色', + Red: '红色', + Green: '绿色', + Blue: '蓝色', + Yellow: '黄色', + Orange: '橙色', + Gray: '灰色', + DimGray: '暗灰色', + Silver: '银色', + LightGray: '浅灰色', + DarkBlue: '深蓝色', + SkyBlue: '天蓝色', + LightGreen: '浅绿色', + Lime: '亮绿色', + Purple: '紫色', + Brown: '棕色', + Pink: '粉红色', + Cyan: '青色', +} + /** 系统颜色(System.Drawing.SystemColors),按 Windows 10 默认主题取值 */ const SYSTEM_COLORS: Record = { Control: '#f0f0f0', diff --git a/web/src/editor/CodeEditor.vue b/web/src/editor/CodeEditor.vue index 00841ab..474b812 100644 --- a/web/src/editor/CodeEditor.vue +++ b/web/src/editor/CodeEditor.vue @@ -124,6 +124,8 @@ onMounted(() => { tabSize: 4, insertSpaces: true, minimap: { enabled: false }, + // 顶部不固定显示所在的类和方法:点报错跳到文件开头附近的行时,那一行会被它挡住 + stickyScroll: { enabled: false }, scrollBeyondLastLine: false, renderWhitespace: 'selection', unicodeHighlight: { ambiguousCharacters: false }, diff --git a/web/src/editor/monaco.ts b/web/src/editor/monaco.ts index 6f95597..5b2fa7f 100644 --- a/web/src/editor/monaco.ts +++ b/web/src/editor/monaco.ts @@ -1,5 +1,7 @@ // 按需加载 Monaco(0.57 的模块布局):编辑器 API + 全部编辑功能(查找、折叠、括号匹配等)+ C# 和 SQL 语法高亮, // 不加载其他几十种语言和 JS/TS/CSS 语言服务,体积小很多。 +// 中文界面(查找替换、右键菜单、提示文字):必须在编辑器模块之前加载,编辑器模块加载时就会取界面文字 +import 'monaco-editor/nls/lang/zh-cn' import * as monaco from 'monaco-editor/editor/editor.api' import 'monaco-editor/features/register.all' import 'monaco-editor/languages/definitions/csharp/register' diff --git a/web/src/grading/TaskPanel.vue b/web/src/grading/TaskPanel.vue index be1ab5b..b50a34c 100644 --- a/web/src/grading/TaskPanel.vue +++ b/web/src/grading/TaskPanel.vue @@ -77,6 +77,7 @@ const formatTime = (ms: number) => new Date(ms).toLocaleTimeString('zh-CN', { ho :show-mask="false" :trap-focus="false" :block-scroll="false" + class="task-drawer" @update:show="emit('update:show', $event)" > @@ -117,6 +118,13 @@ const formatTime = (ms: number) => new Date(ms).toLocaleTimeString('zh-CN', { ho + +