资讯详情

资讯详情

PHP+MySQL校园网运维管理系统:工单闭环与权限设计

简介面向高校网络中心运维人员与计算机专业课程设计、毕业设计参考者的技术文档聚焦 PHPMySQL 环境下的校园网运维系统设计用于应对运维流程分散、故障申报与处理进度难追溯、资产耗材缺少统一管理等问题。包内为 1 个 PDF 文件压缩包约 1.04MB依次覆盖需求分析、总体架构、数据库设计与关键技术实现。文档按权限分级将用户划为系统管理员、网络管理员、网络现维人员与网络用户四类并规划运维人员管理表、用户登记表、信息点记录表、网络资产表、故障维护表、维护进度分类表、通知公告表、耗材分类表等 10 张数据表。关键技术部分给出可借鉴的思路调用 ping 命令对外网做通断测试判断校园网运行状态检索最近十条已解决维修记录协助排查同类故障通过手机端外网访问查看本地设备状态另附安全性、可扩展性等实施要点。已有 93 人学习。1. 需求先立住为什么校园网运维要用一套轻量系统兜底校园网的报修单大多死在聊天记录里。用户打电话说「三楼连不上」值班的人记在纸上维修的人跑一趟回来忘了登记月底做统计时谁也说不清这个月到底处理了多少条、平均用了多久。这正是「基于 PHP 的校园网运维管理系统」要解决的问题把故障申报、任务派发、处理进度、资产台账、通知公告这几件事从口头和纸面挪进一张可以查询、可以统计、可以追溯的表里。反直觉的地方在于选型。很多人一听运维管理系统第一反应是上一套重量级网管平台但校园网的实际规模往往撑不起那个运维成本真正卡住的也不是监控粒度而是流程没人管。PHP 加 MySQL 的组合在这里反而合适部署门槛低一台普通服务器就能跑改一个字段、加一张报表不需要重新走一遍技术栈评审。这套系统适合两类人参考一类是要交毕设或课设、需要一个结构完整且能跑起来的题目的学生另一类是真在管一个中小规模校园网、想先把流程规范起来的从业者。2. 需求与角色建模四类用户撑起十条核心诉求需求分析这一步如果只写「实现用户管理、故障管理」后面数据库和权限就没法做。这套系统的做法是先按权限分级切出四类角色再让每条需求挂到具体角色上最后才落到表结构。2.1 四类角色的权限边界划分系统把使用者分成系统管理员、网络管理员、网络现维人员、网络用户四类代码里对应sysmgr、netmgr、netrepair、netusr四个子系统标识。这个划分不是随便切的它对应的是校园网里真实存在的四种动作决策、派活、干活、报障。系统管理员关心的是系统本身跑得怎么样、谁能进系统、谁有什么权限属于元层面的管理网络管理员关心的是今天有几单没派、资产台账对不对、公告发没发出去现维人员关心的是手上这单在哪个房间、是什么设备、上一单怎么解决的网络用户只关心我报的那条修到哪一步了、大概什么时候能好。提示角色少不等于权限简单。四类角色里前两类能吃到的数据范围明显更大权限判断必须做在后端每次请求上不能只靠前端隐藏菜单。按这个边界往下推需求自然就分开了管理员要能看到角色人员的管理入口和系统运行状况网管要能分配任务、发布公告、维护资产和运维状态、管理设备所有角色都要能看到与自己相关的通知此外还要有统计报表的生成和打印网络用户要能开通账号、提交故障申报、查看处理进度和责任人联系方式。这五条需求看着散其实刚好覆盖了一个完整的工单闭环。2.2 把需求翻译成可验收的条目需求写在纸上容易虚落到验收就必须能被一条一条点出来。通常的做法是把上面五条展开成可以演示的条目后面答辩的时候直接照着走一遍编号需求条目对应角色验收方式R1登录并按角色进入对应子系统全部四个账号分别登录菜单不同R2新增、修改、停用运维人员账号sysmgr停用后该账号无法登录R3发布通知公告指定可见范围netmgr用户端只看到公开公告R4登记网络资产与信息点netmgr资产能关联到具体房间R5故障申报并生成工单编号netusr提交后列表出现新单R6派单给现维人员netmgr工单责任人字段被写入R7更新处理进度直到已解决netrepair状态按预设流程流转R8用户查看本人工单进度与责任人联系方式netusr只能看到自己的单R9查看近期已解决工单作为处理参考netmgr / netrepair列表按时间倒序R10生成并打印统计报表netmgr按故障类别、时间段汇总这张表的价值在于它把「系统能干什么」变成了「演示时点哪里」。很多方案写到需求分析就停在几条抽象描述上到验收阶段自己也说不清做没做到问题就出在这个环节没落地。2.3 十个数据表各管一段流程数据库设计上系统规划了十张主要数据表它们不是并列关系而是围绕「人、点、设备、单、类型、通知」六个维度展开的。区域和楼栋这些都不单独建表而是作为信息点表里的字段存在因为校园网的物理范围相对固定没必要为了规范多建两张关联表。编号表标识表名主要职责1net_mgr网络运维人员管理表记录网管与现维人员的基本信息与在职状态2net_role系统登录人员类别表角色分类与权限标识3net_user网络用户登记表校园网用户账号、所属单位、联系方式4net_point信息点记录表区域、楼栋、楼层、房间号、对应交换机端口5net_device网络资产管理表交换机、路由器、服务器等设备的型号、IP、位置6net_repair网络故障维护表工单主表记录申报、处理、解决全过程7net_info网络故障分类表故障类别字典如断网、慢、无法认证8net_section网络维护进度分类表状态字典未受理、处理中、已解决、已关闭9net_notice网络通知公告管理表公告标题、正文、发布人、可见范围10net_consum网络常规耗材分类表网线、模块、跳线等常用耗材的分类把故障类别和进度做成字典表是个容易被忽略但很值的设计报障时用户从下拉框选类别统计时按类别分组报表口径天然一致不用后期再去清洗文本。耗材表独立出来则是为了配合资产维护换了一根网线、一个模块能记到具体工单上期末盘账时有据可查。3. 总体架构与数据关系四个子系统如何共用一套底座系统的总体架构图通常画成一个中心加四个分支中心是权限与数据访问层四个分支是四类角色的功能入口。这样画的意义不在于好看而在于说明四个子系统其实是同一套代码用不同的入口和不同的数据范围跑出来的不是四套独立程序。3.1 三层结构与子系统映射落到代码组织上一般按「入口层 - 业务层 - 数据层」来分。入口层负责登录校验、角色判定、菜单渲染业务层是一组按模块拆开的处理脚本工单、资产、公告、报表各自独立数据层只有一个数据库访问封装所有查询都走它。?php // config/roles.php —— 角色到模块的白名单入口层每次请求都查这张表 return [ sysmgr [ name 系统管理员, modules [user, role, notice, asset, repair, report, system], ], netmgr [ name 网络管理员, modules [notice, asset, point, repair, report, consum], ], netrepair [ name 网络现维人员, modules [repair, point, consum], ], netusr [ name 网络用户, modules [repair, notice], ], ];这段配置的作用是把「谁能进哪个模块」变成一张可读、可改的表。入口层拿到当前会话里的角色标识后直接查这个数组判断模块是否在白名单内不在就跳回首页。好处是加一个模块、调一次权限只改这一处不用去翻十几个页面里的 if 判断。参数上modules里的每一项对应业务层的一个目录或一组脚本命名保持和表前缀一致方便对照。按模块拆开还有一个现实考虑四个子系统的功能重叠度很高比如公告在四个角色里都能看到只是可见范围不同工单在网管、现维、用户三端都有入口只是可操作的动作不同。共用一套业务脚本、用角色和参数控制行为比复制四份代码要好维护得多。3.2 工单主表与周边表的关联设计十张表里net_repair是绝对的核心其他表基本都在给它提供上下文。一条工单从申报到关闭会依次用到谁报的net_user、在哪个位置net_point、可能涉及哪台设备net_device、属于什么故障net_info、当前什么状态net_section、谁在处理net_mgr。关键字段的设计大致如下字段名保持和业务语义一致避免出现flag1、type2这种后期没人看得懂的命名CREATE TABLE net_repair ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, ticket_no VARCHAR(20) NOT NULL COMMENT 工单编号如 WX20240512001, reporter VARCHAR(32) NOT NULL COMMENT 申报人账号关联 net_user, address VARCHAR(128) NOT NULL COMMENT 报障地址描述, point_id INT UNSIGNED DEFAULT NULL COMMENT 关联信息点可空, info_id INT UNSIGNED NOT NULL COMMENT 故障类别关联 net_info, question VARCHAR(500) NOT NULL COMMENT 用户描述的现象, reason VARCHAR(500) DEFAULT NULL COMMENT 定位到的原因, solution VARCHAR(500) DEFAULT NULL COMMENT 处理办法, mgr VARCHAR(32) DEFAULT NULL COMMENT 责任人账号关联 net_mgr, status TINYINT NOT NULL DEFAULT 0 COMMENT 0未受理 1处理中 2已解决 3已关闭, start_time DATETIME NOT NULL COMMENT 申报时间, finish_time DATETIME DEFAULT NULL COMMENT 解决时间, KEY idx_status_time (status, start_time), KEY idx_reporter (reporter) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里有两个点值得说。一是reason和solution要和question分开存用户的描述和运维的判断是两回事混在一起后期做知识沉淀就没法用。二是索引建在(status, start_time)上因为系统里最高频的两类查询——「未解决的工单」和「最近的工单」——都吃这个组合索引单建status效果会差一截。注意地址字段保留了冗余的文本描述同时用point_id指向信息点表。这是有意的冗余用户报障时经常说不清具体房间先存一段原话现维人员到场后再补关联比强制先选信息点要现实。3.3 会话与权限拦截的统一入口PHP 的会话机制天然适合做这件事。登录成功后把用户标识和角色写进$_SESSION之后每个业务脚本第一行引入同一个拦截文件由它判断角色、判断模块、判断数据范围三件事一次做完。?php // include/guard.php —— 所有业务脚本的第一行 session_start(); require __DIR__ . /../config/roles.php; if (empty($_SESSION[uid]) || empty($_SESSION[role])) { header(Location: /login.php); exit; } $role $_SESSION[role]; $module $MODULE ?? index; // 各业务脚本在引入前声明自己属于哪个模块 if (!in_array($module, $roles[$role][modules] ?? [], true)) { http_response_code(403); exit(无权访问该模块); }$MODULE由各业务脚本在引入拦截文件之前声明这样拦截逻辑只有一份模块归属由脚本自己说清楚。in_array的第三个参数传true走严格比较避免类型松散比较带来的意外命中。数据范围的判断放在业务层比如用户端查工单时强制拼上reporter 当前用户的条件这一层拦截管的是「能不能进这个模块」管不到「能看哪些行」两件事必须分开做——这也是后面避坑章节要展开的一条。4. 核心功能实现从通断探测到工单闭环功能实现这部分最有参考价值的不是页面长什么样而是几个具体动作怎么落到代码上怎么判断网络通不通、怎么让现维人员快速找到同类故障的历史处理办法、怎么根据用户报的位置定位到设备、以及工单状态怎么流转。4.1 出口通断探测的封装与结果判定判断校园网运行状态最直接的办法是从服务器侧对几个关键节点做连通性测试。原始做法是直接调系统的 ping 命令看返回的行数判断成败。这个思路没错但实现上要做三件事才敢放进生产目标集中配置、命令参数转义、结果做多数判定。?php // lib/probe.php function probe(string $host, int $count 3, int $timeout 2): array { // 目标地址必须经过转义防止被拼接成额外命令 $safe escapeshellarg($host); $cmd ping -c {$count} -W {$timeout} {$safe} 21; exec($cmd, $lines, $code); // 统计成功回包数而不是简单看行数 $ok 0; foreach ($lines as $line) { if (preg_match(/time[]\s*[\d.]/, $line)) { $ok; } } return [ host $host, success $ok 0 $code 0, loss $count 0 ? round((1 - $ok / $count) * 100) : 100, raw $lines, ]; }escapeshellarg是这条链路的安全底线凡是拼进 shell 的外部输入都必须过一遍。-c控制探测包数量-W控制单包等待秒数两个参数合起来把最坏情况下的耗时压在几秒内。结果判定没有沿用「返回行数为 1 就是不通」的写法而是用正则数实际收到回应的行数——因为不同系统、不同语言环境下 ping 的输出格式不一样靠行数判断在换机器时很容易翻车。返回结构里带上丢包率和原始输出前端可以据此区分「完全不通」和「通但质量差」两种状态这两种情况在运维上的处置方式完全不同。probe_targets里配三个目标出口网关、校内解析地址、一个外部参照站点。三个都通说明链路正常网关通、外部不通问题大概率在出口或上游网关都不通范围就缩到接入侧了。这个三分法比单点测试有用得多也是判断「本次故障影响范围级别」的依据。4.2 近期已解决工单的取用方式现维人员接到一张新单时最想知道的是「这种问题以前怎么弄的」。系统的做法是把最近十条状态为已解决的工单拉出来作为处理参考。原始描述里给的语句用了top 10那是另一套数据库的写法MySQL 里对应的是LIMIT。?php $sql SELECT id, ticket_no, address, start_time, reporter, question, reason, solution, mgr FROM net_repair WHERE status :status ORDER BY id DESC LIMIT :limit; $stmt $pdo-prepare($sql); $stmt-bindValue(:status, 2, PDO::PARAM_INT); $stmt-bindValue(:limit, 10, PDO::PARAM_INT); $stmt-execute(); $recent $stmt-fetchAll(PDO::FETCH_ASSOC);用预处理绑定参数LIMIT也走绑定而不是字符串拼接这是 PDO 在 MySQL 下需要注意的一点LIMIT的占位符必须显式指定PDO::PARAM_INT否则会被当成字符串引号包起来导致语法错误。这个查询走的是idx_status_time索引status 2加id DESC的组合能直接命中十万级工单量下响应依然在毫秒级。返回结果在页面上只展示四列时间、位置、现象、处理办法。原因和办法这两列是这条功能的核心价值现维人员扫一眼就知道上次是换了模块还是重新打了标签省去重复排查的时间。4.3 按区域楼栋楼层房间定位设备用户报障时给的位置是「几号楼几层几号房间」系统要据此查出这个房间对应的网络设备 IP再做一次探测。这中间需要一个四段式的条件查询把信息点表和资产表连起来。?php $sql SELECT d.ip_address, d.device_name FROM net_point p INNER JOIN net_device d ON d.id p.switch_num WHERE p.area :area AND p.building :building AND p.floor :floor AND p.room_num :room LIMIT 1; $stmt $pdo-prepare($sql); $stmt-execute([ :area $area, :building $building, :floor $floor, :room $room, ]); $device $stmt-fetch(PDO::FETCH_ASSOC); if ($device) { $result probe($device[ip_address]); }四个条件对应信息点表里的四个字段switch_num是信息点指向所属交换机的关联键。查不到设备时不报错返回空结果由页面提示「该位置暂未登记信息点」并引导用户补充地址描述——这比直接抛异常要友好也符合校园网信息点登记往往不完备的实际情况。这个功能真正的用处在于远程预判。值班人员不在现场通过手机访问系统输入用户报的位置就能知道这个房间挂在哪台交换机上、那台交换机通不通。如果整台交换机都不通那就是影响一层楼的范围性故障可以直接升级处理级别不用先跑一趟确认。4.4 故障申报与状态流转的实现工单的状态流转是整个系统的主线必须定义清楚否则会出现「已解决的单又被改回处理中」这类扯皮。系统设了四个状态0 未受理、1 处理中、2 已解决、3 已关闭。允许的流转只有一条主线加上一条回退分支。?php // lib/ticket.php const FLOW [ 0 [1, 3], // 未受理 - 处理中 / 直接关闭重复报障 1 [2, 3], // 处理中 - 已解决 / 关闭无法处理 2 [3, 1], // 已解决 - 关闭 / 退回处理中复发 3 [], // 已关闭为终态 ]; function canTransfer(int $from, int $to): bool { return in_array($to, FLOW[$from] ?? [], true); }状态迁移表写成常量数组判断逻辑只有一行。这样做的好处是流程可读、可审计答辩时被问到「状态会不会乱跳」直接把这五条列出来就能回答。状态改为 2 时同步写入finish_time供后续计算平均处理时长状态改为 1 时写入mgr如果原来为空则记为首次受理。用户端查自己工单的那条语句除了状态条件必须带上申报人条件SELECT ticket_no, address, question, status, mgr, start_time, finish_time FROM net_repair WHERE reporter :uid AND status 3 ORDER BY id DESCreporter :uid这一条不能省它决定了用户只能看到自己的单。责任人联系方式在展示时做一次脱敏处理只显示姓氏加岗位电话不直接把个人号码铺在页面上。5. 避坑与排查四个最容易翻车的地方这套系统的功能本身不复杂真正花时间的都在细节上。下面这四条是这类项目里出现频率最高的问题每一条都值得在动手前先看一眼。5.1 查询用字符串拼接改一个参数就出错现象查询条件里带单引号或者中文时页面报语法错误更糟的是没报错但结果不对比如查某栋楼的工单把别的楼也查出来了。原因原始写法把外部参数直接拼进 SQL 字符串既没有转义也没有类型约束。一旦参数里出现引号SQL 结构就被破坏如果参数恰好能构造出合法结构就会变成越权查询。这类问题在本地测试时往往发现不了因为测试用的都是规规矩矩的参数。解决全站统一用预处理语句参数一律绑定不拼接。上面几段查询都是这个写法。改的时候有个顺序先把数据库封装层改成只暴露prepare和execute把拼接入口堵死再逐个脚本迁移。另外把LIMIT、status这类看起来「一定是数字」的参数也坚持绑定别图省事直接插值。5.2 命令行探测传入未过滤的地址现象探测功能偶尔返回异常结果或者在日志里看到一条明显不该出现的命令记录。原因exec拼接时用了外部传入的地址没有做转义。这类问题平时不会暴露因为它需要外部输入恰好构造出特殊字符但一旦发生影响的不只是一个页面的显示结果。解决所有进入命令行的变量都过escapeshellarg更进一步的做法是根本不接受外部传入地址——探测目标从配置文件里读用户只能选择探测哪一个已配置的节点而不是自由输入一个地址。同时给exec加超时控制避免目标不可达时把 PHP 进程挂住。上面probe函数里的-c和-W就是干这个用的。5.3 前端隐藏了菜单后端却没有拦现象演示时一切正常换个账号用手工输入 URL 的方式访问能看到不该看的数据。原因权限只做在界面层菜单按角色渲染但对应的处理脚本没有做二次校验。这在学生项目里非常普遍因为演示路径都是按正常流程点的。解决权限判断必须做两次一次在入口层判断模块归属一次在业务层判断数据范围。前者解决「能不能进这个页面」后者解决「能看哪些行」。上面guard.php管的是前者用户端查询里强制拼reporter :uid管的是后者两个缺一不可。自测时养成一个习惯把每个角色的 URL 抄下来换账号逐个访问一遍看返回是不是 403。5.4 中文字段和时间的显示问题现象工单描述里的中文变成问号或者乱码工单时间和实际申报时间差几个小时某些较长的故障描述写进去被截断了。原因三个独立的问题叠在一起。字符集在连接层没有统一设置建表和连接的编码不一致就会乱码PHP 的默认时区和数据库的时区不一致date()和NOW()打出来的时间对不上字段长度按字符数估的但用了VARCHAR(50)去存用户的一段口语描述显然不够。解决建库建表统一utf8mb4PDO 连接串里显式带charsetutf8mb4在公共初始化文件里date_default_timezone_set设一次数据库连接后执行一次SET time_zone两边对齐描述类字段一律给到VARCHAR(500)并且在前端加字数提示而不是等数据库报错。这三条都是配置级的小事但漏掉任何一条都会在演示当天暴露属于典型的没有后悔药可吃的问题。6. 验收与答辩把系统跑通只是及格线验收这一步很多人栽在「功能都做了但说不清为什么这么做」上。评审关心的不是你写了多少行代码而是这套东西能不能对上一个真实场景、设计上有没有想清楚的地方。我会建议按一条完整链路来演示而不是按菜单逐个点。就从「用户在手机上提交一条报障」开始选位置、选故障类别、填描述、提交然后切到网管账号看到这条新单并派给自己再切到现维账号先看近期十条已解决工单找参考再用位置查一下对应交换机通不通最后填原因和办法、改成已解决。用户端刷新看到进度变化和责任人信息。整条链路走完不超过五分钟但把四类角色、十个表、状态机全串起来了比逐个模块点过去有说服力得多。答辩时最容易被追问的三个点提前准备好答案追问回答要点为什么不直接用现成的网管平台现成平台解决的是监控和告警这套系统解决的是流程和记录两者不冲突校园网规模下轻量方案维护成本更低为什么把故障类别和进度做成字典表报表统计口径统一避免后期清洗文本类别和状态可以随管理要求调整而不用改代码权限是怎么保证的入口层判模块归属业务层判数据范围两层分开且都有可复现的自测方式演示环境要提前一天准备数据库里预置至少二十条不同状态的工单、四五条资产记录不要用空库讲功能。空库演示时那种「点了没反应」的尴尬基本都出自这里。从那以后我每次带人做这类系统都会强制走一遍「换账号手工敲 URL」的自测流程不管演示前一天多晚。权限这块翻车的成本太高而补起来的成本其实很低。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →