MCClock 的 React Web 前端控制面板,通过 HTTP API 与 MCClock 桌面客户端通信,实现对闹钟、生日、关机任务、运行程序、倒计时、秒表、健康提醒等功能的完整管理。
支持 PC 浏览器与手机移动端浏览器自适应布局,无需安装任何 App。
| 模块 | 功能 |
|---|---|
| 闹钟 | 新建/编辑/删除/复制闹钟;支持循环模式(一次/每天/每周/每月/每年/间隔);支持闹钟分组;软删除(回收站)可恢复 |
| 生日 | 公历/农历生日管理;提前天数/提醒时间可配置;铃声自定义 |
| 运行程序 | 定时启动可执行文件或打开 URL;支持命令行参数;可立即执行;支持复制任务 |
| 关机任务 | 定时关机/重启/注销/强制关机;可配置预警提前秒数;可立即触发 |
| 倒计时 | 相对时长(时分秒)与绝对目标时间两种模式;铃声可配置 |
| 秒表 | 开始/暂停/继续/重置/记圈;本地计时器平滑显示;圈次记录列表 |
| 健康提醒 | 工作/休息时长配置;全屏或窗口展示;铃声配置 |
| 设置 | 图形化全局设置:基本设置、提醒设置、整点报时、高级设置(HTTP API/快捷键/时间同步) |
| 状态 | 实时显示后端连接状态、版本号、服务器时间、运行时长 |
| 依赖 | 版本 | 用途 |
|---|---|---|
| React | 19 | UI 框架 |
| TypeScript | 6 | 类型安全 |
| Vite | 8 | 构建工具 |
| Tailwind CSS | 4 | 样式(Utility-first) |
| React Router | 7 | 单页路由 |
| Axios | 1 | HTTP 请求 |
| lucide-react | — | 图标库 |
| react-hot-toast | 2 | 操作反馈提示 |
| clsx | 2 | 条件类名拼接 |
mcclock-web/
├── index.html # 入口 HTML,含移动端 viewport meta
├── vite.config.ts # Vite 配置(含开发代理 /api → MCClock 后端)
├── package.json
├── tsconfig.json
├── dist/ # 生产构建产物(运行 npm run build 生成)
└── src/
├── main.tsx # React 入口
├── App.tsx # 根组件,包含路由和全局 Provider
├── index.css # 全局样式(Tailwind v4 导入 + 自定义变量)
│
├── api/
│ ├── client.ts # Axios 实例封装,响应拦截,apiGet/Post/Put/Delete
│ └── index.ts # 各模块 API 函数(按后端路由一一对应)
│
├── contexts/
│ └── ApiConfigContext.tsx # API 服务器地址动态配置(localStorage 持久化)
│
├── types/
│ └── models.ts # 所有数据模型 TypeScript 类型定义(与 C++ 结构体完全对应)
│
├── utils/
│ └── index.ts # 工具函数:时间格式化、枚举标签映射、cycleData 解析
│
├── components/
│ ├── Layout.tsx # 全局布局:PC 侧边栏 + 移动端底部导航
│ ├── ServerConfigModal.tsx # API 服务器地址配置弹窗
│ └── ui/
│ ├── Button.tsx # 通用按钮(5 种样式 × 3 种尺寸)
│ ├── Modal.tsx # 通用弹窗(支持 ESC 关闭、底部操作区)
│ ├── FormField.tsx # 表单组件:FormField / Input / Select / Toggle
│ ├── PathInput.tsx # 路径输入器(PC: 文件浏览框;手机: 带搜索的下拉选择)
│ ├── CycleEditor.tsx # 循环模式编辑器(一次/每天/每周/每月/每年/间隔)
│ ├── RingtoneEditor.tsx # 铃声/响铃模式编辑器
│ └── EmptyState.tsx # 空状态占位组件
│
└── pages/
├── AlarmsPage.tsx # 闹钟页面
├── BirthdaysPage.tsx # 生日页面
├── RunProgramsPage.tsx # 运行程序页面
├── ShutdownTasksPage.tsx # 关机任务页面
├── CountdownsPage.tsx # 倒计时页面
├── StopwatchPage.tsx # 秒表页面
├── HealthPage.tsx # 健康提醒页面
├── SettingsPage.tsx # 设置页面(图形化 4 Tab)
└── StatusPage.tsx # 状态页面
- Node.js ≥ 18
- MCClock 已运行,且 HTTP API 服务已启用(在 MCClock 设置 → 高级设置中开启)
cd mcclock-web
npm install
# 国内网络可加镜像源:
npm install --registry https://registry.npmmirror.comnpm run dev开发服务器默认运行在 http://localhost:5173。
vite.config.ts 中配置了开发代理,所有 /api 请求会自动转发到 http://127.0.0.1:8081(MCClock 默认端口),无需处理跨域。
修改代理目标: 若 MCClock 运行在不同端口,修改
vite.config.ts中server.proxy['/api'].target即可。生产环境不使用 Vite 代理,请见生产部署。
npm run build产物输出至 dist/ 目录:
dist/
├── index.html (~0.75 KB)
└── assets/
├── index-*.css (~28 KB,gzip ~6 KB)
└── index-*.js (~366 KB,gzip ~113 KB)
npm run preview将 dist/ 目录的文件部署到任意静态文件服务器(Nginx、Caddy、Apache 等)。
关键: 生产环境没有 Vite 代理,需要在 Web 服务器层将 /api 路径反向代理到 MCClock API 地址。
server {
listen 80;
server_name your-domain.com; # 或局域网 IP
root /path/to/mcclock-web/dist;
index index.html;
# 单页应用:所有非文件路径回退到 index.html
location / {
try_files $uri $uri/ /index.html;
}
# 将 /api 请求转发到 MCClock 后端
location /api/ {
proxy_pass http://127.0.0.1:8081/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}跨主机访问(手机/局域网): 若 MCClock 与 Nginx 运行在同一台电脑,手机通过局域网 IP 访问此页面即可,Nginx 在服务器端完成代理转发,不存在跨域问题。
直接访问(无反向代理): 也可以不配置 Nginx 代理,直接在页面右上角的「服务器配置」弹窗中填写 MCClock API 的完整地址(如
http://192.168.1.100:8081),前提是 MCClock 后端已启用 CORS(已在源码中配置Access-Control-Allow-Origin: *)。
以下为前端调用的所有后端接口,与 api_server.cpp 中的路由完全一一对应:
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/v1/status |
获取应用版本、服务器时间、运行时长 |
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/v1/settings |
获取完整设置 JSON |
| PUT | /api/v1/settings |
递归合并更新设置 |
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/v1/alarm-groups |
获取所有分组 |
| POST | /api/v1/alarm-groups |
新建分组 |
| PUT | /api/v1/alarm-groups/:uuid |
更新分组 |
| DELETE | /api/v1/alarm-groups/:uuid |
删除分组 |
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/v1/alarms |
获取所有闹钟 |
| POST | /api/v1/alarms |
新建闹钟 |
| PUT | /api/v1/alarms |
更新闹钟 |
| DELETE | /api/v1/alarms/:uuid |
软删除(移入回收站) |
| GET | /api/v1/alarms/deleted |
获取回收站闹钟 |
| POST | /api/v1/alarms/restore/:uuid |
从回收站恢复 |
| POST | /api/v1/alarms/purge/:uuid |
永久删除 |
| POST | /api/v1/alarms/clear-recycle |
清空回收站 |
| POST | /api/v1/alarms/copy/:uuid |
复制闹钟 |
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/v1/birthdays |
获取所有生日 |
| POST | /api/v1/birthdays |
新建生日 |
| PUT | /api/v1/birthdays |
更新生日 |
| DELETE | /api/v1/birthdays/:uuid |
删除生日 |
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/v1/shutdown-tasks |
获取所有关机任务 |
| POST | /api/v1/shutdown-tasks |
新建关机任务 |
| PUT | /api/v1/shutdown-tasks |
更新关机任务 |
| DELETE | /api/v1/shutdown-tasks/:uuid |
删除关机任务 |
| POST | /api/v1/shutdown-tasks/:uuid/run |
立即执行 |
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/v1/run-programs |
获取所有运行程序任务 |
| POST | /api/v1/run-programs |
新建任务 |
| PUT | /api/v1/run-programs |
更新任务 |
| DELETE | /api/v1/run-programs/:uuid |
删除任务 |
| POST | /api/v1/run-programs/:uuid/run |
立即执行 |
| POST | /api/v1/run-programs/copy/:uuid |
复制任务 |
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/v1/countdowns |
获取所有倒计时 |
| POST | /api/v1/countdowns |
新建倒计时 |
| PUT | /api/v1/countdowns |
更新倒计时 |
| DELETE | /api/v1/countdowns/:uuid |
删除倒计时 |
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/v1/stopwatch/status |
获取秒表状态 |
| POST | /api/v1/stopwatch/start |
开始/继续 |
| POST | /api/v1/stopwatch/pause |
暂停 |
| POST | /api/v1/stopwatch/stop |
停止并重置 |
| POST | /api/v1/stopwatch/reset |
重置 |
| POST | /api/v1/stopwatch/lap |
记圈 |
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | /api/v1/health |
获取健康提醒配置 |
| PUT | /api/v1/health |
更新健康提醒配置 |
| 断点 | PC(≥768px) | 手机(<768px) |
|---|---|---|
| 导航 | 左侧固定侧边栏(9 个模块 + 服务器配置按钮) | 顶部标题栏 + 底部固定 Tab 栏(可横向滚动) |
| 弹窗 | 屏幕居中 | 从底部滑出(rounded-t-2xl) |
运行程序、铃声文件路径等涉及「浏览电脑文件」的字段,PC 与手机采用不同交互:
PC 端:
- 文本框:可直接输入或粘贴路径
- 「浏览」按钮:调用原生
<input type="file">文件选择对话框,选择后将文件名填入文本框(注:因浏览器安全限制,只能获取文件名,不能获取完整路径,完整路径需手动输入)
手机端:
- 文本框:可直接输入或粘贴完整路径
- 下拉箭头:展开带搜索过滤的下拉列表
- 预置了 12 个常用 Windows 程序路径(记事本、计算器、Chrome、Edge、Excel 等)
- 搜索框可按程序名称或路径过滤
- 也可完全忽略预设,直接在文本框手动输入/粘贴任意路径
前端 API 基地址存储在浏览器 localStorage(key: mcclock_api_base_url),默认为 http://127.0.0.1:8081。
修改方式:
- PC 端:点击左侧侧边栏底部的服务器地址按钮
- 手机端:点击顶部标题栏右侧的服务器图标
弹窗中输入新地址(格式:http://<IP>:<PORT>,不含 /api/v1),保存后立即生效,无需刷新页面,设置在刷新/重启浏览器后依然保留。
典型使用场景:
- 手机访问局域网内的 MCClock:填写
http://192.168.1.x:8081(将 IP 替换为 MCClock 所在电脑的局域网 IP) - MCClock 修改了 API 端口:直接在此更新端口号
设置页面对应 MCClock 桌面客户端的「全局设置」对话框,分为 4 个标签:
- 开机自动启动:控制是否随 Windows 启动
- 启动时提醒遗漏闹钟:错过的闹钟在下次启动时弹出
- 自动检查更新:启动时自动检查新版本
- 显示桌面时钟 / 数字时钟:桌面组件开关
- 全屏提醒模式:在指定时段(如 22:00 ~ 07:00)内闹钟以全屏方式显示
- 提醒窗口位置:屏幕居中 / 左上角 / 左下角
- 关闭方式:手动关闭 或 N 分钟后自动关闭
- 铃声音量:0~100 滑块控制
- 报时方式:文字+语音 / 仅文字 / 仅语音 / 不报时
- 报时周期:每小时 / 每半小时 / 自定义分钟间隔
- 自定义报时小时:24 格按钮,点击选择/取消指定小时是否报时,支持全选/全不选
- HTTP API 服务器:启用开关 + 绑定 IP + 监听端口(修改后需重启 MCClock 生效)
- 快捷键:最小化到后台 / 语音报时 的全局热键配置
- 时间同步间隔:自动校对系统时间的周期(分钟,0 表示不同步)
- 在
src/types/models.ts中添加对应的 TypeScript 类型 - 在
src/api/index.ts中添加对应的 API 函数 - 在对应 Page 组件中调用
目前未使用 .env 文件,API 地址通过运行时 localStorage 配置。如需编译时固定 API 地址,可在 vite.config.ts 中添加 define 配置。
- 使用
oxlint进行代码检查:npm run lint - 所有组件使用 TypeScript 严格模式
- 表单状态使用
Partial<Model>管理,与后端结构完全对应
MIT