Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## 未发布

## v0.4.1 — 2026-11-13

- 大屏客户端界面更紧凑:默认窗口由 1180×760 缩小到 920×640,内容最大宽度 880;页眉、标题、卡片间距与内边距收紧。
- 班级信息改为整行横条(左侧班级名,右侧消息接收与班级音量),不再留出大块空白;「呼叫老师」与「声音测试」卡片并排,图标与文字对齐,设置项占满一行。窄窗口自动变为单列。

## v0.4.0 — 2026-11-13

- 桌面「呼叫老师」悬浮球不再始终置顶:PPT 放映或最大化窗口会盖住它,回到桌面仍可见;悬浮球加大、改为醒目的橙色和白色粗体大字,确认面板与按钮同步放大。
Expand Down
2 changes: 1 addition & 1 deletion api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "课堂叮咚 API",
"version": "0.4.0"
"version": "0.4.1"
},
"servers": [
{
Expand Down
2 changes: 1 addition & 1 deletion deploy/.env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
DOMAIN=classding.example.com
CLASSDING_IMAGE=ghcr.io/alumos/classding-server:v0.4.0
CLASSDING_IMAGE=ghcr.io/alumos/classding-server:v0.4.1
# openssl rand -hex 32
JWT_SECRET=
# 仅首次部署设置;创建成功后清空用户名/密码并重新创建容器
Expand Down
2 changes: 1 addition & 1 deletion deploy/compose.1panel.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# 粘贴到 1Panel 的编排编辑器。首次部署请填写两项密码;升级保留原值和原编排名称。
services:
classding:
image: ghcr.io/alumos/classding-server:0.4.0
image: ghcr.io/alumos/classding-server:0.4.1
platform: linux/amd64
restart: unless-stopped
ports:
Expand Down
2 changes: 1 addition & 1 deletion deploy/compose.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
server:
image: ${CLASSDING_IMAGE:-ghcr.io/alumos/classding-server:v0.4.0}
image: ${CLASSDING_IMAGE:-ghcr.io/alumos/classding-server:v0.4.1}
restart: unless-stopped
environment:
DATA_DIR: /data
Expand Down
2 changes: 1 addition & 1 deletion docs/INTEGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
- AuthResponse: {access_token,user};refresh token 放 HttpOnly Cookie。

## REST
GET config => {speech_enabled:false,registration_enabled:true,version:'0.4.0'}
GET config => {speech_enabled:false,registration_enabled:true,version:'0.4.1'}
POST auth/register {username,password,display_name} => AuthResponse
POST auth/login {username,password} => AuthResponse
POST auth/refresh => AuthResponse;POST auth/logout => {ok:true}
Expand Down
19 changes: 19 additions & 0 deletions docs/releases/v0.4.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 课堂叮咚 v0.4.1

大屏客户端界面更紧凑。只改大屏客户端的界面,服务端只更新了版本号。

## 大屏客户端

- **窗口更小**:默认窗口由 1180×760 缩小到 920×640,内容最大宽度 880。
- **排布更紧凑**:页眉、标题、卡片间距和内边距都收紧了。班级信息改为整行横条,左侧是班级名,右侧是“消息接收”和“班级音量”,不再留出大块空白。
- **卡片对齐**:「呼叫老师」与「声音测试」两张卡片并排,图标列和文字列对齐;设置项占满一行。窗口拉窄时自动变为单列。

## 升级

Windows amd64 安装包:`ClassDingScreen-amd64-installer.exe`,大屏升级到 v0.4.1 即可看到新界面。

服务端镜像 `ghcr.io/alumos/classding-server:0.4.1` 与 v0.4.0 功能相同,可以不升级;如果升级,只需替换镜像。

## 已知限制

- 主窗口大小、悬浮球层级和多显示器/缩放比例下的表现,需要在真实 Windows 设备上验收。
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "classding",
"private": true,
"version": "0.4.0",
"version": "0.4.1",
"type": "module",
"packageManager": "pnpm@11.25.0",
"engines": {
Expand Down
2 changes: 1 addition & 1 deletion screen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ wails build -platform windows/amd64 -nsis -installscope user

## 学生呼叫老师

绑定后 Windows 桌面左侧会显示橙色「呼叫老师」原生悬浮球(白色粗体大字)。它处在普通窗口层级,不会一直置顶:PPT 放映、最大化窗口会正常盖住它,回到桌面或其他窗口旁边时仍可见;主窗口关闭到托盘后仍可使用,不依赖网页中的浮层。拖动可移到其他显示器;松手停在最近显示器工作区内,避开任务栏,按显示器 DPI 调整大小。悬浮入口平时不抢焦点,只有点击展开二次确认时才激活;取消或 Escape 不发送,默认键盘焦点在取消按钮,Tab 可切换到确认按钮。全屏通知、课堂工具展示期间临时隐藏,结束后恢复,不移动或改变已有作业窗。
绑定后 Windows 桌面左侧会显示橙色「呼叫老师」原生悬浮球(白色粗体大字)。主窗口默认 920×640,内容紧凑排布。它处在普通窗口层级,不会一直置顶:PPT 放映、最大化窗口会正常盖住它,回到桌面或其他窗口旁边时仍可见;主窗口关闭到托盘后仍可使用,不依赖网页中的浮层。拖动可移到其他显示器;松手停在最近显示器工作区内,避开任务栏,按显示器 DPI 调整大小。悬浮入口平时不抢焦点,只有点击展开二次确认时才激活;取消或 Escape 不发送,默认键盘焦点在取消按钮,Tab 可切换到确认按钮。全屏通知、课堂工具展示期间临时隐藏,结束后恢复,不移动或改变已有作业窗。

确认后由原有 WebView service 复用设备认证和 loopback 代理发送 `POST /api/v1/device/student-calls`,Go 原生层不保存另一份密钥。发送中禁止重复提交;成功须收到有效的服务器记录才显示「呼叫已发送」。本班所有关联老师在打开的教师网页收到提醒,任一老师标记已读后共享为已处理。服务端按同班 30 秒限流,客户端显示 `Retry-After` 等待时间。网络异常或响应丢失会显示结果未确认,用户主动重试沿用同一个幂等编号;不会离线排队或自动补发,退出程序后不保留未确认编号。

Expand Down
2 changes: 1 addition & 1 deletion screen/frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@classding/screen",
"version": "0.4.0",
"version": "0.4.1",
"private": true,
"type": "module",
"scripts": {
Expand Down
43 changes: 22 additions & 21 deletions screen/frontend/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -344,18 +344,19 @@ function App() {
</div>
<div className="dashboard-grid">
<Card className="class-card">
<div className="class-card-top">
<span className="class-icon">
<Monitor size={22} />
</span>
<Badge variant="success">
<span className="status-dot" /> 已绑定
</Badge>
<span className="class-icon">
<Monitor size={22} />
</span>
<div className="class-info">
<div className="class-info-top">
<span className="section-label">当前班级</span>
<Badge variant="success">
<span className="status-dot" /> 已绑定
</Badge>
</div>
<h2>{state.className}</h2>
<p>{state.deviceName}</p>
</div>
<span className="section-label">当前班级</span>
<h2>{state.className}</h2>
<p>{state.deviceName}</p>
<div className="class-divider" />
<div className="class-summary">
<div>
<Radio size={18} />
Expand All @@ -374,24 +375,24 @@ function App() {
<div className="dashboard-side">
<Card className="student-call-card">
<span className="call-icon">
<BellRing size={26} />
<BellRing size={22} />
</span>
<div>
<h3>需要老师来教室?</h3>
<p>向本班所有关联老师发送呼叫。关闭主窗口后,桌面上的橙色悬浮球仍可呼叫。</p>
<p>通知本班所有老师,也可点桌面橙色悬浮球。</p>
{state.studentCallMessage && (
<p className="call-status" role="status">
{state.studentCallMessage}
</p>
)}
<Button
className="call-button"
onClick={() => setCallOpen(true)}
disabled={state.studentCallSending}
>
<BellRing size={18} /> 呼叫老师
</Button>
</div>
<Button
className="call-button"
onClick={() => setCallOpen(true)}
disabled={state.studentCallSending}
>
<BellRing size={18} /> 呼叫老师
</Button>
</Card>
<Dialog open={callOpen && state.bound} onOpenChange={setCallOpen}>
<DialogContent>
Expand Down Expand Up @@ -425,7 +426,7 @@ function App() {
<span className="sound-orbit orbit-one" />
<span className="sound-orbit orbit-two" />
<span className="ready-bell">
<BellRing size={37} />
<BellRing size={24} />
</span>
</div>
<div>
Expand Down
Loading
Loading