

项目地址:https://github.com/jinxuan-cd/it-ops-system-github
IT 运维工单台账与日报自动管理系统
面向企业内部 IT 运维团队的一体化工单与日报平台:报障 → 抢单 → 处理 → 归档 → 日报/月报 → 知识沉淀 → 数据分析全链路打通,支持多角色权限隔离、SLA 时效管控、机房巡检、故障复盘与一键备份。
🔐 公网 / 内网双入口隔离:员工自助报障门户独立成公网端口(外勤、分公司扫码即可用),管理后台只留在内网端口;两个端口共用同一个后端与数据库,数据实时互通,但公网端口在网关层拿不到任何登录与数据管理接口。
- 开发者:锦轩(邮箱 2686389727@qq.com)
- 授权方式:个人与小团队免费,商业使用需购买授权,详见 授权与商业许可
- 运行环境:Linux / Windows + Docker 20.10+,或 Node.js 20+ / MariaDB 10.11(MySQL 8.0 亦可)
目录
- 项目简介
- 功能特性
- 技术栈
- 目录结构
- 快速开始
- 默认账号与角色
- 系统初始化
- 核心联动逻辑
- 数据口径说明
- 公网 / 内网双入口隔离
- 数据库:MariaDB 10.11 与迁移
- 自助入口与移动端
- 实时消息说明
- 数据备份与恢复
- 安全说明
- AI 接入
- 生产部署建议
- 升级与更新
- 常见问题
- 更新日志
- 贡献与反馈
- 授权与商业许可
- 第三方组件与许可合规
- 关于作者与版权声明
项目简介
中小企业的 IT 运维工作通常散落在微信群、Excel 和口头交接里:谁报了障、谁在处理、处理了多久、这个月做了多少事,都很难说清。本项目把这套流程做成一个可私有化部署的轻量系统:
- 报障入口零门槛:员工扫码或点链接即可报障,无需注册账号。
- 处理过程可追溯:每张工单记录发生 / 响应 / 完成时间,自动算 SLA 是否超期。
- 日报月报自动化:一键把当日工单汇总成纯文本日报,明日计划自动转次日待办。
- 数据说话:看板与团队运营分析给出受理量、完成率、平均处理时长、人员产出排名。
- 部署即用:
docker compose up -d一条命令,自动建库建表、自动生成管理员账号。
适用规模:3~50 人的运维团队;单实例部署(无 Redis / 消息队列等外部依赖)。
功能特性
工单全流程
| 能力 | 说明 |
|---|---|
| 多种录入方式 | 标准录入(完整字段 + 知识库方案推荐)、快捷录入(极简草稿)、扫码报障自动建单、巡检异常转工单 |
| 抢单接单 | 新单进入待接单池,所有运维收到待办 + 右下角实时弹窗;点「接取」即转处理中(数据库原子更新,两人同抢只有一人成功) |
| 派单转派 | 管理员 / 处理人可派单、转单、退回池子;被指派人立即收到待办与实时提醒 |
| 服务台模式(可选) | 开启后新单只推服务台 + 管理员,由服务台统一派单;关闭则运维自行抢单 |
| 状态机 | pending 待接单 → processing 处理中 → done 已完成,时间与状态强联动(见核心联动逻辑) |
| 批量操作 | 批量标记完成 / 批量删除 / 导出选中;Excel 导出含状态与处理人 |
| 满意度回访 | 员工凭手机号后 4 位查进度,完成后可打 1–5 分并留言 |
时效与质量
| 能力 | 说明 |
|---|---|
| SLA 策略 | 按「问题类别 + 优先级」配置响应/解决时限,支持默认兜底;工单自动计算截止时间并标记「即将超时 / 已超时」 |
| 优先级 | 低 / 普通 / 高 / 紧急四级,与 SLA 联动 |
| 一键重算 | 调整策略后可对历史工单批量重算 SLA 截止时间 |
| 数据体检 | 团队分析页可一键检测并修复异常数据(完成时间早于发生时间、已完成却无完成时间等) |
汇报与沉淀
| 能力 | 说明 |
|---|---|
| 日报自动生成 | 一键汇总当日工单,可编辑、一键复制、提交后「明日计划」自动转次日待办 |
| 月报生成 | 基于当月工单/目标/故障数据生成月度工作报告 |
| 团队查阅 | 管理员 / 审计员可查看全员的日报、月报,含今日提交情况、7 天趋势、未提交名单、明细弹窗 |
| 知识库 | 检索、文档解析回填(txt/md/csv/pdf/docx)、来源工单跳转、浏览计数 |
| 知识自动沉淀 | 工单完成时勾选「同步知识库」→ 自动生成条目 |
| 常见问题门户 | 知识库条目标记「对外公开」后自动成为免登录 FAQ,支持搜索与折叠查看 |
运维专项
| 能力 | 说明 |
|---|---|
| 故障管理 | P1–P4 分级、影响范围档位、受影响系统、发生/接单/恢复三时间点、原因、处理过程、复盘总结 |
| 机房巡检 | 巡检区域与巡检项可在设置页配置,支持「需拍照」项;逐项打卡 + 现场拍照留底 + 进度条,异常可一键转工单 |
| 账号台账 | 业务系统账号清单(系统/账号/权限范围/责任人/开通回收时间/状态)+ 台账汇总 |
| 项目管理 | 项目阶段拆解、进度、起止时间、状态 |
| 待办与目标 | 当日/本周/全部待办、月度目标与权重、完成月份自动记录 |
分析与通知
| 能力 | 说明 |
|---|---|
| 数据看板 | 顶部切换今日 / 本周 / 本月 / 上月 / 本年,整页跟着换:6 张指标卡(受理 / 完成 / 完成率 / 平均处理时长 / 未完成 / 满意度 + 与上一周期环比)、趋势图(自动按小时 / 按天 / 按月分桶)、问题类别 TOP、类别与系统分布、本期最新工单、今日待办与本月目标 |
| 团队运营分析 | 全公司受理与完成量、完成率、平均时长、积压超期(分页滚动)、人员产出排名、人员维度下钻、问题类别排名、系统排名、部门排名、近 6 月趋势、自动生成「汇报要点」 |
| 消息推送 | 企微 / 钉钉 / 飞书 / 自定义 Webhook,订阅新故障、P1P2 升级、SLA 超时、每日提醒 |
| 定时提醒 | 内置调度器:每日 09:00 待跟进提醒、18:00 当日小结 |
| 操作审计 | 全量记录 POST/PUT/DELETE(操作人、IP、路径、方法、耗时、敏感字段脱敏),支持检索与汇总 |
平台能力
- 公网内网双入口:员工自助门户独立端口(默认 8081),管理后台独立端口(默认 8080)。两个端口连的是同一个后端、同一个数据库,数据完全互通;公网端口只放行 4 个免登录接口,登录与管理接口在该端口上直接 404。
- 多角色权限:管理员 / 审计员(全公司只读)/ 服务台 / 运维工程师,写操作按角色收口。
- 数据隔离:所有业务表绑定
user_id,普通用户只能看到自己的数据。 - 实时推送:SSE 长连接,新单/接单/退回/完成即时到达浏览器;员工在公网门户报障后,运维的管理端界面同样实时弹出提醒。
- 一键备份恢复:打包成 zip(全部数据 + 上传附件),上传即还原,恢复前自动快照。
- 移动端适配:宽度 ≤ 820px 自动切换抽屉菜单、卡片列表、全宽弹窗,手机浏览器直接可用。
- 登录防护:连续输错密码触发图形验证码与账号锁定,防暴力破解。
技术栈
| 层次 | 技术选型 |
|---|---|
| 前端 | Vue 3(<script setup>)、Element Plus、Vite、Pinia、Vue Router、ECharts |
| 后端 | Node.js 20、Express 4、mysql2 连接池、JWT、bcryptjs |
| 数据库 | MariaDB 10.11(InnoDB / utf8mb4 / +08:00 时区),兼容 MySQL 8.0 |
| 文件与导出 | Multer 上传、ExcelJS 导出、archiver + adm-zip 备份、pdf-parse / mammoth 文档解析 |
| 部署 | Docker Compose(db / backend / frontend / public-web),Nginx 托管静态资源并反代 API |
目录结构
it-ops-system/
├── docker-compose.yml # 一键部署编排(db / backend / frontend / public-web)
├── .env.example # 部署环境变量模板(复制为 .env)
├── sql/
│ └── init.sql # 数据库初始化:18 张表 + 视图 + 字典 + SLA + 设置
├── scripts/
│ ├── upgrade.sh # 安全升级(只重建、永不带 -v,数据不丢)
│ ├── demo-data.sql # 可选演示数据(一年工单 + 演示账号 + FAQ)
│ ├── gen-demo-data.py # 生成上面的演示数据 SQL
│ └── demo-reset.sh # 清空演示数据,恢复出厂
├── backend/ # Express 后端(单进程,管理端与门户共用)
│ ├── src/
│ │ ├── index.js # 入口:全部接口 + /api/public 免登录接口
│ │ ├── db.js # 数据库连接池(MariaDB / MySQL 通用)
│ │ ├── middleware/ # auth 鉴权、upload 上传白名单、audit 审计
│ │ ├── routes/ # 23 个业务路由(见下表)
│ │ └── utils/ # 响应封装、SLA、实时推送、调度器、seed、文本清洗
│ ├── uploads/ # 上传附件(已挂卷,重建容器不丢)
│ ├── backups/ # 备份包(已挂卷)
│ └── Dockerfile
├── public-portal/ # 员工自助门户(公网端口,零依赖静态站)
│ ├── index.html # 报障 / 查进度 / 常见问题(单页,Tab 切换)
│ ├── app.js style.css
│ ├── nginx.conf # 公网入口:只放行 /api/public/*,其余一律 404
│ └── Dockerfile
└── frontend/ # Vue3 管理端(内网端口)
├── src/
│ ├── api/ # 统一接口层(含拦截器与错误提示)
│ ├── layout/ # 后台布局、待办面板、接单弹窗
│ ├── router/ store/ utils/
│ └── views/ # 各业务页面
├── nginx.conf
└── Dockerfile
后端路由:auth users tickets todos goals knowledge projects dictionary dashboard analytics dailyReport monthlyReport incidents inspections accounts sla notify auditLog system backup aiConfig publicApi realtime。
快速开始
方式一:Docker Compose(推荐,生产同款)
前置:Docker 20.10+ / Docker Compose v2。
# 1. 获取代码
git clone <仓库地址> it-ops-system
cd it-ops-system
# 2. 准备环境变量(生产必须改口令与 JWT_SECRET)
cp .env.example .env
vim .env # 修改 MYSQL_* / JWT_SECRET / DEFAULT_ADMIN_PASSWORD
# 3. 构建并启动(首次会自动建库、建表、写入初始字典与管理员)
docker compose up -d --build
# 4. 查看状态与日志
docker compose ps
docker compose logs -f backend
启动后访问:
| 入口 | 地址 | 网络范围 |
|---|---|---|
| 管理后台(运维/管理员) | http://服务器内网IP:8080 |
只在内网开放 |
| 员工自助门户(报障/查进度/FAQ) | http://服务器公网IP:8081 |
可对公网开放 |
两个端口连的是同一个后端、同一个数据库,报障进来自动出现在管理后台的工单列表,数据不需要任何同步。 门户端口(8081)在网关层只放行
/api/public/*,访问http://公网IP:8081/api/auth/login、/api/tickets、/uploads/...一律返回 404。db与backend不映射宿主机端口,只存在于容器网络内(要本机调试后端,临时在 compose 里加回- "127.0.0.1:3000:3000")。 入口密钥在后端首次启动时自动生成,登录管理后台后到「系统设置 → 自助服务入口」查看二维码与链接,并把「公网门户地址」填成http://公网IP:8081。
方式二:本地开发
前置:Node.js ≥ 20、本地 MariaDB 10.11 或 MySQL 8.0。
# 1. 建库并初始化
mariadb -uroot -p -e "CREATE DATABASE itops DEFAULT CHARACTER SET utf8mb4"
mariadb -uroot -p itops < sql/init.sql
# 2. 启动后端
cd backend
cp .env.example .env # 按本地数据库修改 DB_* 与 JWT_SECRET
npm install
npm run dev # http://localhost:3000
# 3. 启动前端(另开终端)
cd frontend
npm install
npm run dev # http://localhost:5173,已配置 /api 代理到 3000
也可以用根目录脚本:
npm run install:all # 安装前后端依赖
npm run dev:backend # 启动后端
npm run dev:frontend # 启动前端
默认账号与角色
首次启动(用户表为空时)自动创建管理员:
| 账号 | 初始密码 | 角色 |
|---|---|---|
admin |
admin123 |
管理员 |
初始密码可通过
.env的DEFAULT_ADMIN_PASSWORD指定;首次登录后请立即到「系统设置 → 安全」修改。 系统初始化后只保留管理员一个账号,其它账号由管理员在「账号管理」中按需创建。
角色权限:
| 角色 | 标识 | 权限 |
|---|---|---|
| 管理员 | admin |
全部功能 + 账号管理 + 字典维护 + SLA 策略 + 备份恢复 + 审计日志 + 团队运营分析 |
| 审计员 | auditor |
只读查看全公司看板、团队分析、工单/知识库/日报月报明细;非 GET 请求被后端统一拦截(仅放行改自己资料与密码) |
| 服务台 | service |
查看全部工单并派单/转单;需在「系统设置 → 工单流转」开启服务台派单后才生效 |
| 运维工程师 | user |
本人录入的工单 + 指派给自己的工单 + 待接单池 |
系统初始化
系统出厂即为空业务数据状态,可直接交付使用:
| 初始化项 | 状态 |
|---|---|
| 表结构 | 18 张表 + v_ticket_duration 视图,sql/init.sql 全量定义 |
| 部门 / 应用系统 / 问题类别 | 44 条默认字典(可在「基础字典维护」增改停删) |
| SLA 策略 | 4 条默认策略(低/普通/高/紧急) |
| 系统设置 | 报障入口、FAQ 门户、服务台、巡检区域与巡检项默认值 |
| 业务数据 | 全部为空:工单、故障、巡检、台账、知识库、日报、月报、待办、目标、项目、审计日志 |
| 账号 | 仅 admin |
重新初始化(清空所有业务数据)
# 方式 A:彻底重建数据库(推荐,最干净)
docker compose down -v # -v 会删除 db 数据卷,数据不可恢复!
docker compose up -d --build
# 方式 B:保留容器,只重跑初始化脚本
docker compose exec -T db sh -c \
'mariadb -uroot -p"$MARIADB_ROOT_PASSWORD" itops' < sql/init.sql
⚠️
docker compose down -v会清空数据库与上传文件。执行前请先在「系统设置 → 备份恢复」下载一份备份包。
如需只清空业务数据、保留账号与字典,可在数据库执行:
SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE TABLE ticket; TRUNCATE TABLE todo;
TRUNCATE TABLE knowledge; TRUNCATE TABLE daily_report;
TRUNCATE TABLE monthly_report;TRUNCATE TABLE month_goal;
TRUNCATE TABLE project; TRUNCATE TABLE incident;
TRUNCATE TABLE inspection; TRUNCATE TABLE account_ledger;
TRUNCATE TABLE audit_log;
SET FOREIGN_KEY_CHECKS = 1;
演示数据(可选,只想先看效果)
出厂是空库,看板和团队分析的图表都是 0,不好判断效果。想直接看真实图表(月度趋势、上月汇总、超期分页、人员维度分析),可以铺一份演示数据:
# 铺演示数据:一年的工单 + 3 个演示账号 + 5 条常见问题
docker compose exec -T db mariadb -uitops -p"$MYSQL_PASSWORD" itops < scripts/demo-data.sql
# 用完一键清空(保留 admin、字典、系统设置)
bash scripts/demo-reset.sh
演示账号 zhangwei / lijing / wangqiang,密码与 admin 相同。数据跨全年、含已完成与超期未完成工单,专门用来验证图表与分页。
演示数据脚本由
scripts/gen-demo-data.py生成。生产环境不要执行。
核心联动逻辑
- 工单标记【已完成】并勾选【同步知识库】→ 自动生成知识库条目。
- 录入工单选择【应用系统 + 问题类别】→ 优先匹配知识库方案,无匹配走关键词兜底。
- 日报【明日工作计划】提交 → 自动拆分为次日待办(重复提交会先清掉当日自动生成的待办,不会翻倍)。
- 右侧全局浮动待办面板 → 实时拉取当日未完成待办。
- 看板 → 聚合工单 / 待办 / 目标,计算环比与平均处理时长。
- 知识库上传文档(txt/md/csv/pdf/docx)→ 自动解析文本回填。
- 所有业务数据绑定
user_id,严格数据隔离(管理员可看全部)。 - 工单保存/导入时按 SLA 策略计算响应与解决截止时间,并标记超时状态。
- 故障登记为 P1/P2 → 立即通过已配置的 Webhook 推送告警;恢复后自动统计恢复时长。
- 巡检出现异常项 → 一键转成工单,把异常清单写进服务内容。
- 自助报障提交 → 生成带编号的工单(来源标记
qr),员工凭手机后 4 位查进度、完成后评价满意度。 - 编辑工单把状态改为「已完成」但没填完成时间 → 自动补当前时间;改回「处理中」→ 清空完成时间。
- 把工单「完成时间」删掉 → 状态自动回退为「处理中」(删除故障「恢复时间」同理回退为「未恢复」)。
- 巡检项勾选「需拍照」但没传图 → 提交时二次确认(不强制阻断,现场拍不了也能先记录)。
- 扫码报障 → 工单为
pending→ 给每个运维生成source='ticket'的待办,并通过 SSE 推送到在线浏览器;被接取/派单后其他人的待办与弹窗立即关闭。公网门户与内网管理端共用同一个后端进程,所以门户提交的报障会立刻推送到运维的浏览器。 - 接单采用数据库原子更新(
WHERE assignee_id IS NULL AND status='pending'),两人同时点只有一人成功,另一人收到「手慢了,已被接取」。 - 删除工单会同步删除关联的接单待办,避免待办里留下点不开的死链。
- 停用或降级账号后,鉴权中间件 60 秒内即生效(含强制下线),不需要重启服务。
- 最后一个管理员不可被降级 / 停用 / 删除,避免把自己锁在系统外。
数据口径说明
| 指标 | 口径 |
|---|---|
| 受理量 | 按 happen_time(工单发生时间)落在统计区间内计数 |
| 完成量 | 按 finish_time(完成时间)落在区间内计数,与受理量分开统计,避免跨期完成让完成率超过 100% |
| 完成率 | 本期受理且已完成 ÷ 本期受理 |
| 平均处理时长 | 只统计 finish_time 晚于 happen_time 的工单(真正记录了起止时间的),历史批量导入只填日期的记录不计入分母;无有效样本显示「—」 |
| 超期未完成 | 未完成工单按 NOW() - happen_time 计算已挂时长,用 GREATEST(...,0) 兜底,不会出现负数 |
| 故障类指标 | 只在有故障记录时展示;无故障时看板与分析页自动隐藏故障卡片 |
| 看板时间维度 | 今日 = 当天 0 点起;本周 = 周一起;本月 / 上月 = 自然月;本年 = 1 月 1 日起。环比对比「上一同长度周期」(今日↔昨日、本周↔上周、本月↔上月、本年↔去年) |
| 看板趋势分桶 | 今日按小时(24 桶)、本周 / 本月 / 上月按天、本年按月,空桶补 0,图表不会跳段 |
时区:容器数据库必须使用
TZ=Asia/Shanghai+--default-time-zone=+08:00(docker-compose.yml已固定)。 若数据库跑在 UTC,NOW()会比北京时间早 8 小时,导致「已挂时长」出现负数、趋势图分桶错位、SLA 超期判定滞后 8 小时。后端计算本地时间统一使用todayStr()/nowStr(),不使用toISOString()。
公网 / 内网双入口隔离
员工不一定在内网:分公司、外勤、出差的人要用手机扫码报障,管理后台却绝不能放到公网。 因此系统把「员工自助」和「管理后台」拆成两个端口:
| 管理后台 | 员工自助门户 | |
|---|---|---|
| 默认端口 | 8080 |
8081 |
| 配置项 | .env 里的 ADMIN_PORT |
.env 里的 PUBLIC_PORT |
| 面向 | 内网(运维、管理员、审计员) | 公网(全体员工手机扫码) |
| 界面 | Vue3 完整后台 | 零依赖静态页(约 30KB,弱网秒开) |
| 后端 | 同一个 backend 容器 |
同一个 backend 容器 |
| 可访问接口 | 全部 | 仅 `/api/public/config |
| 需要登录 | 是 | 否(凭入口密钥 k) |
两道防护:
- 网关层(主防线):门户 nginx 只反代
/api/public/,/api/(其它)、/uploads/、点文件一律return 404;只允许 GET/POST/HEAD。 - 数据库层:
db与backend不做宿主机端口映射,公网只能碰到门户那个 nginx。
公网侧额外加固:
- 按 IP 限流:报障提交 6 次/分钟、其它公开接口 60 次/分钟(网关
limit_req+ 应用内计数双保险)。 - 严格响应头:
X-Frame-Options: DENY、Content-Security-Policy(只允许自身资源)、X-Robots-Tag: noindex、server_tokens off。 - 只暴露必要字段:进度查询不返回处理人名与内部沟通;填过手机号的单必须校验后 4 位才能查看。
部署要点:云安全组 / 宝塔 WAF 只把 8081 映射到公网;8080 只在局域网可达,不做公网映射。
改端口后不生效?
.env 里的 ADMIN_PORT / PUBLIC_PORT 只在创建容器时生效,docker compose restart 不会重建容器:
# 改完 .env 执行这个(不是 restart)
docker compose up -d --force-recreate
# 确认实际映射的端口
docker compose ps
还要确认端口没被别的程序占用(宝塔/1Panel 自己、旧容器都可能占着):
ss -lntp | grep -E ':8080|:8081' # 应分别对应 frontend / public-web 容器
默认端口:管理端 8080(只内网)、员工报障 8081(对公网开放,宝塔 WAF 反代到这里)。
数据库:MariaDB 10.11 与迁移
镜像固定为 mariadb:10.11(LTS,兼容 MySQL 协议与语法,启动比 MySQL 8.0 更快、内存占用更低)。 sql/init.sql 同时兼容 MariaDB 10.11 与 MySQL 8.0,两份都能直接跑。
从 MySQL 8.0 换成 MariaDB(重要)
MariaDB 无法读取 MySQL 8.0 的数据目录,所以换镜像必须换新数据卷(compose 里已改名为 mariadb_data,与旧的 db_data 分开)。 系统出厂即为空数据,通常直接重建最省事:
cd /opt/it-ops-system
git pull
# 1. 停掉旧栈(同时清掉旧镜像的容器)
docker compose down
# 2. 删掉旧的 MySQL 8 数据卷(卷名以 docker volume ls 为准)
docker volume ls | grep -E 'db_data|itops'
docker volume rm it-ops-system_db_data # 确认数据可丢弃再执行
# 3. 重新构建启动:MariaDB 会按 init.sql 全新初始化
docker compose up -d --build
docker compose logs -f db | tail -30 # 看到 ready for connections 即成功
docker compose logs -f backend | tail -20 # 看到「数据库连接成功」+「已创建默认管理员账号」
如果旧库数据必须保留(例如已经在用,只是要换镜像),先用旧的 MySQL 8 容器把数据导出来:
# ① 单独起旧的 mysql:8.0 容器挂旧卷,并用 --skip-grant-tables 绕过忘记的口令
docker run -d --name old-mysql -v it-ops-system_db_data:/var/lib/mysql mysql:8.0 --skip-grant-tables --skip-networking=0
sleep 20
# ② 导出(此时无需口令)
docker exec old-mysql mysqldump -uroot --single-transaction --routines --triggers --default-character-set=utf8mb4 itops > /opt/itops-old.sql
# ③ 起新栈(MariaDB 空库初始化),再把数据灌进去
docker rm -f old-mysql
docker compose up -d --build
sleep 30
docker compose exec -T db sh -c 'mariadb -uroot -p"$MARIADB_ROOT_PASSWORD" itops' < /opt/itops-old.sql
docker compose restart backend
导出文件里如果带
utf8mb4_0900_ai_ci(MySQL 8 默认排序规则),导入 MariaDB 前替换成utf8mb4_unicode_ci:sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' /opt/itops-old.sql
数据库连不上 / 口令被拒绝?
症状:后端日志刷 Access denied for user 'root'@'localhost',或页面登录报 500、docker compose exec db mariadb -uroot -p... 提示 ERROR 1045。
根因只有一个:数据卷已经初始化过,库里的真实口令不会再跟着 .env 变。 MYSQL_ROOT_PASSWORD / MYSQL_PASSWORD 仅在数据目录为空的第一次启动时生效。
三种处理方式(按代价从低到高):
# 方式 1:把 .env 改回当初初始化时用的口令,然后重建容器
docker compose up -d --force-recreate
# 方式 2:进容器改口令(数据保留)
docker compose exec db mariadb -uroot -p # 用当前能登录的口令
# → ALTER USER 'root'@'localhost' IDENTIFIED BY '新口令';
# → ALTER USER 'itops'@'%' IDENTIFIED BY '新口令';
# → FLUSH PRIVILEGES;
# 改完把 .env 里的口令同步,再 up -d --force-recreate
# 方式 3:数据可丢弃,删卷重建(最干净)
docker compose down -v && docker compose up -d --build
后端已内置友好提示:口令被拒绝时会打印连接目标(itops@db:3306/itops,不含口令)和上述三种处理方式,不会只丢一句 ER_ACCESS_DENIED_ERROR。
自助入口与移动端
- 设置页「自助服务入口」提供二维码与两个免登录链接(指向公网门户):
- 报障入口:
{公网门户地址}/report?k=<入口密钥> - 常见问题:
{公网门户地址}/faq?k=<入口密钥>
- 报障入口:
- 「公网门户地址」填成
http://公网IP:8081(或域名)后,二维码自动改指公网;未填写时会提示「当前二维码只有连内网才能打开」。 - 端口千万别填 8080:8080 是管理端(要登录),扫码会打开后台登录页,员工看到的是”另一个系统”。填成管理端端口时设置页会红字拦住,后端也会拒绝保存。
- 报障的故障截图支持直接粘贴:截图后 Ctrl+V(手机长按粘贴),本地压缩后直接上传,不用先存相册再选文件;也保留「选择图片 / 拍照」两个按钮,最多 3 张。
- 门户页脚显示版本号(如
v20261102),设置页「自助服务入口」也显示同一版本。两边不一致说明浏览器在用旧缓存或服务器门户没更新——门户静态资源已设no-cache,正常刷新即可。 - 入口密钥保存在
sys_setting.report_key,可在设置页一键重置(旧二维码立即失效,需重新打印)。 - 报障时若填写了手机号,查询进度与评价必须校验手机号后 4 位,避免单号被枚举。
- 报障与 FAQ 接口均有限频,防刷。
- 宽度 ≤ 820px 自动进入移动端布局:侧栏变抽屉、筛选表单竖排、工单/故障/巡检列表改卡片、弹窗占满宽度、顶部显示当前页面名。
- 手机端菜单只保留高频入口(数据看板、团队分析、工单录入、工单记录、故障、巡检、待办、项目、知识库、日报生成、日报月报查阅),系统设置放在抽屉底部;桌面端功能仍可通过地址直达。
- 巡检拍照走系统相机(
input capture),不依赖 HTTPS、不触发摄像头授权;上传前自动压缩到 1600px / JPEG。
实时消息说明
- 通道:
GET /api/realtime/stream?token=<JWT>,浏览器端全局只建一条连接。 - 事件:
ticket:new(新工单进池)、ticket:taken(被接走/已派单)、ticket:released(退回池子)、ticket:done(已完成)。 - 反向代理必须关闭缓冲(
proxy_buffering off),否则事件会被攒着一起发;frontend/nginx.conf已为/api/realtime/单独配置。 - 兜底:页面重新可见(
visibilitychange)时主动拉一次待接单池,SSE 断线期间不会漏单。
数据备份与恢复
「系统设置 → 数据管理 → 系统备份与恢复」(仅管理员)把整个系统打成一个 zip 包:
| 包内文件 | 内容 |
|---|---|
meta.json |
版本、备份时间、各表条数、附件数量 |
db.json |
全部数据表:工单、故障、巡检、台账、知识库、项目、日报/月报、待办、目标、字典、系统设置、账号、AI 配置、审计日志 |
uploads/* |
工单附件、巡检照片等原件 |
- 备份包存放在容器内
/app/backups(宿主机backend/backups,已挂卷),默认保留最近 20 个。 - 恢复方式:上传 .zip 或直接选服务器上已有的备份包。流程:读包 → 生成「恢复前快照」→ 附件回写 → 数据表在事务内整体替换(失败回滚)→ 校验至少保留一个可用管理员。
- 备份包包含账号密码哈希与 AI 密钥,请只存放在可信位置。
backend/backups/backup.sh可用于只备份 MySQL 的定时任务(gzip + 保留 30 天):
# crontab -e 加入:每日 2 点备份
0 2 * * * /path/it-ops-system/backend/backups/backup.sh >> /var/log/itops_backup.log 2>&1
安全说明
通用
- 密码 bcrypt 加密存储;JWT 会话鉴权;所有写操作走角色校验;按用户隔离数据。
- 附件上传有扩展名与 MIME 双重白名单(拒绝 html / svg 等可执行内容)。
- 静态附件响应带
X-Content-Type-Options: nosniff与Content-Security-Policy: sandbox,避免上传文件被当作页面执行。 - 审计日志对敏感字段(密码、Token、密钥)自动脱敏。
- 建议只在内网部署;如需公网访问,请在前面加一层 HTTPS 反向代理(如 Nginx + Let’s Encrypt)并限制来源 IP。
网络隔离(公网 / 内网)
- 对公网只暴露 8081(员工自助门户);8080(管理后台)只在局域网可达。
db与backend不做任何宿主机端口映射,即使服务器有公网 IP 也连不上数据库与内部 API。- 门户 nginx 是唯一对公网开的口子,只放行
/api/public/*,其余路径(含/api/auth、/api/tickets、/uploads)直接 404。 - 生产建议再叠加:公网门户走 HTTPS(避免报障内容明文)、限制公网侧并发连接数、把管理端访问限制到办公网段(云安全组 / 防火墙白名单 / 宝塔 WAF)。
登录防护(防暴力破解)
| 触发条件 | 处理 |
|---|---|
| 同一账号连续输错 3 次 | 后续登录必须输入图形验证码(一次性、5 分钟有效,点击图片可刷新) |
| 连续输错 5 次 | 账号锁定 5 分钟 |
| 验证码错误 | 同样计入失败次数,防止绕过 |
| 登录成功 | 失败计数立即清零 |
- 失败计数保存在后端内存(单实例部署足够),重启即清零;多实例部署请迁移到 Redis 或数据库。
- 账号不存在时也执行一次 bcrypt 比对,避免通过响应时间判断账号是否存在。
- 停用账号后 60 秒内即无法继续使用旧 Token。
AI 接入
AI 能力(智能日报、月度工作报告、知识库整理)按用户各自配置,不使用全局 Token:
- 登录后进入左侧菜单「AI 助手」;
- 选择供应商(DeepSeek / OpenAI / 通义千问 / Kimi / OpenRouter / Ollama / 自定义),填写 API 地址、Token、模型名;
- 点「测试连接」验证后保存。
未配置或调用失败时,系统自动降级为规则汇总(列出今日处理事项与结果),功能不受影响。
| 报错 | 原因与处理 |
|---|---|
429 |
上游限流,稍后重试或换模型 |
401 / 403 |
Token 无效或无该模型权限 |
404 |
API 地址或模型名不正确 |
用本地模型(LM Studio / Ollama / vLLM):后端在容器里,容器内的 localhost 是容器自己。
| 场景 | 地址填法 |
|---|---|
| AI 服务与平台同机 | http://host.docker.internal:1234/v1 |
| AI 服务在局域网另一台机器 | http://192.168.x.x:1234/v1 |
只填到 /v1 即可,系统自动补全 /v1/chat/completions;Token 可留空(未填则不发送 Authorization 头);模型名不确定时点「获取模型」自动拉取 GET /v1/models 列表。
生产部署建议
- 改默认口令:
admin初始密码与.env中的MYSQL_*、JWT_SECRET全部替换为随机值(openssl rand -hex 32)。 - 数据持久化:
db_data卷、backend/uploads、backend/backups已挂载到宿主机;迁移服务器时整目录拷贝即可。 - 开机自启:三个服务均已配置
restart: unless-stopped。 - 端口收敛(重要):只把
8081(员工自助门户)映射到公网;8080(管理后台)限内网访问。db与backend默认不做宿主机映射,不要为了”方便”给它们加公网端口。 - 反向代理与 HTTPS:域名访问时用外层 Nginx / 宝塔 WAF 转发到
127.0.0.1:8080(管理端)与127.0.0.1:8081(门户),并为/api/realtime/保留proxy_buffering off与较长的proxy_read_timeout。 - 定时备份:同时开启「系统设置 → 备份恢复」的 zip 备份与服务器 crontab,并定期把备份包拷贝到别的机器。
- 日志与监控:
docker compose logs -f backend,或接入宿主机日志收集;内置调度器会在每日固定时间推送提醒,可用作存活探测。
常用运维命令:
docker compose ps # 查看服务状态
docker compose logs -f --tail=200 backend
docker compose restart backend # 只重启后端
docker compose down # 停止(保留数据)
docker compose up -d # 启动
升级与更新
升级步骤(Docker 部署)
# 1. 先备份:登录系统 →「系统设置 → 备份恢复」→ 立即备份并下载 zip
# 同时备份宿主机上的上传目录
cp -r backend/uploads /backup/uploads-$(date +%F)
# 2. 拉取新代码
git pull # 或解压新的发布包覆盖
# 3. 重新构建并启动(数据库结构变更由后端启动时自动幂等迁移)
docker compose up -d --build
# 4. 验证
docker compose logs -f backend # 看到 [migrate] 相关日志且无报错
数据库升级机制:后端每次启动会执行 migrateSchema(),全部为 CREATE TABLE IF NOT EXISTS / 「列不存在才新增」,可重复执行;sys_meta 表记录一次性数据修复,已执行过的不会再跑。因此升级不需要手工执行 SQL,回滚同理(把代码切回旧版本重启即可)。
升级会不会把数据清空?——不会
这是刻意设计的行为,升级时请认准一个原则:只要不带 -v,数据就一定在。
| 操作 | 会不会重新执行 init.sql |
工单数据 |
|---|---|---|
docker compose restart |
不会 | 保留 |
docker compose up -d --build(日常升级) |
不会 | 保留 |
docker compose up -d --force-recreate |
不会 | 保留 |
| 换镜像版本后重建 | 不会 | 保留 |
docker compose down(不加 -v) |
不会 | 保留 |
docker compose down -v |
会(空库重建) | 全部清空 |
原因:sql/init.sql 挂在 /docker-entrypoint-initdb.d/,数据库入口脚本只在数据目录为空时才执行它。数据卷 mariadb_data 里有内容之后,这个脚本就会被跳过。
想更省心可以直接用升级脚本(自带检查,绝不会删卷):
bash scripts/upgrade.sh # 用当前代码重建容器
bash scripts/upgrade.sh --pull # 先 git pull 再升级
脚本会先检测数据卷是否存在、提示先备份,然后执行 docker compose up -d --build,永远不会带 -v。
前端构建更新(不走 Docker)
cd frontend && npm install && npm run build # 产物在 frontend/dist
# 将 dist 覆盖到 Nginx 站点目录即可
员工门户(public-portal)改了要重建 public-web
门户是独立的静态站镜像(public-web 服务),改完 public-portal/ 下的文件必须重建该服务, 否则员工扫码看到的还是旧页面(管理端和门户是两个不同的容器):
docker compose up -d --build public-web
排查「扫码看到的样式不对」按顺序看:
- 页脚版本号(如
v20261102)是否与「系统设置 → 自助服务入口」显示的门户版本一致; 不一致说明浏览器在用旧缓存(已设no-cache,强刷即可)或服务器没重建 public-web。 - 设置页填的公网地址端口是不是
8081(填成8080会打开后台登录页,形状完全不同)。 - 手机在不在能访问到该地址的网络里(公网 IP / 端口映射 / 安全组)。
版本管理建议
- 用 Git 管理代码,
main为稳定分支,改动走特性分支合并。 - 每次发布打 tag(如
v1.2.0)并在更新日志登记变更。 .env、backend/uploads/、backend/backups/不纳入版本管理(已在.gitignore中排除)。
重要提示
源码工具资源类要求技术能力: 源码工具对技术要求较高,不建议小白购买下载,建议具有一定思考和动手能力的用户购买。 请谨慎考虑: 小白和缺乏思考动手能力者不建议赞助。本站只收集整理资源,部分源码不一定能运行。有空会测试部分源码及修改,赞助前请谨慎! 虚拟商品购买须知: 虚拟类商品具有可复制性,一经打赏赞助,不支持退款。请谅解,谢谢合作!








暂无评论内容