首页 / 资讯中心 / 文章详情

电脑维修报修网站源码:PHP+MySQL工单系统设计与避坑指南

电脑维修报修网站源码:PHP+MySQL工单系统设计与避坑指南 ★ FEATURED ARTICLE
简介一套面向电脑维修企业的完整网站源码以 ASP 动态技术实现适合中小维修公司快速搭建官网并接入在线报修流程也适合开发者二次定制。资源共 570 个文件压缩包 1.9MB主要包含 66 个 asp 核心动态页面、54 个 htm 静态页、10 个 css 样式表、7 个 js 交互脚本以及大量 gif/jpg 图片素材、db 数据库、swf 动画、asa 全局配置文件等结构上覆盖报修入口、后台管理、常见问题、标准服务等模块。已有 878 人学习浏览。通过这份源码使用者能直接获得可部署的网站雏形与报修表单逻辑理解 ASPAccess 的经典站点组织方式现成的图形素材和页面模板能缩短界面美化周期开发者还可在后台权限、表单校验、数据存储等环节按需扩展适合作为独立建站或接单改版的基础工程。1. 电脑维修公司的报修网站源码把“谁在修、修到哪”从电话本搬进系统一家电脑维修公司一天接几十个报修电话真正让人头疼的往往不是修电脑而是“客户地址听没听清、设备型号记没记住、师傅去没去、修到哪一步”。一套电脑维修公司的报修网站源码解决的就是这个流程问题客户在线填单店员后台派单师傅更新进度客户凭单号查状态老板看数据知道这个月修了多少台、配件花了多少钱。它不是给客户看的展示站而是把“报修、派单、维修、回访”整条链路钉在系统里。适合想整合线上报修入口的维修门店、想接私活或做课程设计的开发者也适合打算用源码建站方式快速起步的小团队。下面按选型、数据库、主流程、踩坑、上线验证的顺序把方案讲透。2. 技术选型与源码目录为什么多数报修网站源码选择 PHP MySQL2.1 源码建站的选型对比PHP 方案在什么条件下比 Java、Python 更省心做报修网站源码最常见的技术组合是 PHP MySQL。这个结论不是因为它性能最好而是因为它的部署链路最短。电脑维修公司的老板通常没有专职运维网站大概率跑在一台旧的Windows服务器或者便宜的云主机上。PHP 只要把源码丢进 Web 目录、配好 MySQL 导入 SQL 就能跑不需要编译、不需要容器编排出了问题找个懂 PHP 的在校生也能改。对比之下Java 那套方案比如网上流传的各种“java课程设计案例源码”里的 SSM 项目业务逻辑写得很清楚但光是对 JDK、Tomcat、Maven 仓库的版本折腾就够劝退。Python 的方案在“免费python源码大全”里确实不少Flask 或 FastAPI 写报修接口很顺手可一旦落到 Windows 服务器进程守护、虚拟环境、端口常驻都是额外的坑。所以我的结论很直接如果你的目标是一周内上线、以后少维护就按 PHP MySQL 这套 php源码去改造它最贴近“源码建站”这个动作本身。当然选 PHP 有一个前提业务规模控制在单店几十个工单/天。报修网站的核心动作是“插入一条工单 改状态 查列表”这类读写对 MySQL 来说毫无压力。真的到了多门店、几百人同时用的阶段再考虑拆服务、上队列也不迟。前期别为不存在的并发买单。2.2 看懂一套报修网站源码的目录结构入口、接口、后台、安装脚本拿到一套报修网站源码第一步不是急着打开浏览器而是先看目录结构。一套合格的报修系统目录不会太复杂但必须能一眼分清“客户看到的东西”和“店员操作的东西”。我一般会先找四个东西安装 SQL、前台报修入口、后台管理目录、接口目录。下面这个目录结构是我习惯的整理方式收到什么源码都先往这个结构上靠repair-system/ ├── install.sql # 建库建表脚本 ├── config.php # 数据库连接配置 ├── index.php # 前台报修入口 ├── query.php # 客户查进度页 ├── api/ │ ├── create_order.php # 提交报修单接口 │ └── update_status.php# 修改状态接口 ├── admin/ │ ├── login.php # 后台登录 │ ├── dashboard.php # 工单看板 │ └── export.php # 导出报表 ├── uploads/ # 故障照片目录 └── include/ ├── db.php # PDO 封装 └── auth.php # 登录鉴权注意看 config.php 和 install.sql 这两个文件它们是整个源码的入口。install.sql 决定了业务流程能不能撑起来config.php 决定了你能不能跑起来。很多源码结构花里胡哨但 install.sql 里只有一张表这种源码多半只能“展示”不能真正做派单和回访。反过来如果里面有三张以上的表并且有 status 字段说明作者考虑过流程值得往下读。2.3 部署架构取舍单机部署、短信通知和定时任务的边界报修网站源码的部署架构我强烈建议“单机部署优先”。一台云服务器装 Nginx、PHP-FPM、MySQL全部搞定。这个组合在 2 核 4G 的机器上可以轻松支撑一家维修公司一整年的工单量。别一开始就上 Redis、上 RabbitMQ那不是维修公司需要的东西。需要认真设计的是通知和定时任务。客户报修后店里必须有人知道。常见的做法是报修成功后系统调短信 API 或者邮件 API 通知管理员。这里有一个很重要的边界通知动作不要写在创建工单的同步请求里。因为短信 API 超时、欠费、返回错误都会阻塞客户提交报修的操作。正确做法是把通知记录到一张 notify_queue 表由定时任务每隔一分钟扫一次再发送。定时任务在 Linux 上用 crontab 跑一个 PHP 脚本即可在 Windows 上用计划任务调 php.exe。这一步很多源码没做你接手后要自己补上。后面第 5 章我会专门讲这个坑。3. 报修工单的数据库设计把维修流程“凝固”成一张张表3.1 工单主表状态字段和紧急程度决定整个流程报修网站的核心表是工单主表。我见过的很多半成品源码工单表只有“标题、内容、联系电话”三列这种设计根本撑不起派单流程。一张能用的工单表至少要有这几个字段单号、客户、设备、故障描述、紧急程度、状态、接单人、时间节点。下面是建表 SQLCREATE TABLE orders ( id int(11) unsigned NOT NULL AUTO_INCREMENT, order_no varchar(32) NOT NULL COMMENT 报修单号如 RX20240512001, customer_name varchar(50) NOT NULL COMMENT 客户姓名, customer_phone varchar(20) NOT NULL COMMENT 手机号, device_type tinyint(4) NOT NULL DEFAULT 0 COMMENT 0台式机 1笔记本 2一体机 3打印机 4网络设备, device_sn varchar(64) DEFAULT COMMENT 设备序列号或识别码, fault_desc text NOT NULL COMMENT 故障描述, urgent_level tinyint(4) NOT NULL DEFAULT 0 COMMENT 紧急度 0普通 1紧急 2加急, status tinyint(4) NOT NULL DEFAULT 0 COMMENT 0待接单 1已派单 2维修中 3待回访 4已完成 5已取消, assignee_id int(11) DEFAULT NULL COMMENT 接单维修师傅ID, created_at datetime NOT NULL COMMENT 报修时间, accepted_at datetime DEFAULT NULL COMMENT 接单时间, finished_at datetime DEFAULT NULL COMMENT 完成时间, closed_at datetime DEFAULT NULL COMMENT 回访关闭时间, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no), KEY idx_status_created (status, created_at) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT报修工单主表;这段 SQL 里最关键的参数是 status 和 urgent_level。status 是后面所有流程的判断依据“待接单”和“维修中”的工单在后台看到的操作按钮完全不同。urgent_level 则影响派单优先级加急单在列表里要标红排在前面。device_type 用 tinyint 枚举而不是字符串是为了减少存储开销同时避免“台式机”和“台式电脑”这种同一含义不同写法的脏数据。3.2 客户与设备表容易漏掉的保修期和设备归属很多报修网站源码只做一张工单表客户信息直接冗余在工单里。这种做法不是不行但会漏掉一个真实场景同一家公司可能隔三差五报修不同电脑如果每次都要重复填地址客户体验会很差。所以我的建议是把客户单独拆一张表工单表里通过 customer_id 关联。客户表要特别记录两个容易被忽略的字段地址和保修截止日期。地址影响上门维修路线保修日期影响报价判断。设备也应该单独建表因为一个客户可能有多台设备每台设备的品牌、型号、购入时间、保修截止都不一样。我把两台表的设计放在一起CREATE TABLE customers ( id int(11) unsigned NOT NULL AUTO_INCREMENT, customer_name varchar(50) NOT NULL, phone varchar(20) NOT NULL, address varchar(255) NOT NULL COMMENT 上门地址报修单回显用, company_name varchar(100) DEFAULT COMMENT 公司名企业客户用, warranty_end date DEFAULT NULL COMMENT 整体保修截止NULL表示未知, remark varchar(255) DEFAULT , PRIMARY KEY (id), KEY idx_phone (phone) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT客户档案; CREATE TABLE devices ( id int(11) unsigned NOT NULL AUTO_INCREMENT, customer_id int(11) NOT NULL COMMENT 所属客户ID, device_type tinyint(4) NOT NULL, brand varchar(50) DEFAULT COMMENT 品牌, model varchar(50) DEFAULT COMMENT 型号, sn varchar(64) DEFAULT COMMENT 序列号, warranty_end date DEFAULT NULL COMMENT 该设备保修截止, created_at datetime NOT NULL, PRIMARY KEY (id), KEY idx_customer (customer_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT客户设备档案;注意 customers 表和 devices 表是 1 对 N 的关系工单表只需要存 customer_id 和 device_id 就能把报修上下文查出来。这里有一个参数选择的细节手机号在 customers 表里要加索引因为查进度回显客户信息时基本都用手机号定位。devices 表则要在 customer_id 上加索引避免列表页逐条扫描。3.3 维修过程的可回溯设计维修日志与配件消耗除了主表报修网站还需要两张记录过程的表维修日志表和配件消耗表。它们的意义在于事后追溯——客户说“没修好”的时候店里能拿出“当时换了什么、谁修的、怎么修的”记录这是很多源码完全没有的部分。维修日志表记录每次状态变更和维修动作字段包括工单ID、操作人、动作内容、变更前后状态。配件消耗表记录本次维修用了什么配件、单价多少、数量多少这两张表和工单主表形成父子关系。下面是我常用的建表脚本CREATE TABLE repair_logs ( id int(11) unsigned NOT NULL AUTO_INCREMENT, order_id int(11) NOT NULL, operator_id int(11) NOT NULL COMMENT 操作人员ID, action varchar(20) NOT NULL COMMENT 接单/开始维修/换件/完工, content text NOT NULL COMMENT 具体说明, old_status tinyint(4) DEFAULT NULL, new_status tinyint(4) DEFAULT NULL, created_at datetime NOT NULL, PRIMARY KEY (id), KEY idx_order (order_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT维修日志表; CREATE TABLE repair_parts ( id int(11) unsigned NOT NULL AUTO_INCREMENT, order_id int(11) NOT NULL, part_name varchar(100) NOT NULL COMMENT 配件名称, quantity int(11) NOT NULL DEFAULT 1, unit_price decimal(10,2) NOT NULL DEFAULT 0.00, created_at datetime NOT NULL, PRIMARY KEY (id), KEY idx_order (order_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT工单配件消耗表;action 字段我建议用固定枚举值不要在 content 里自由发挥。因为后续做统计报表时按“接单”“换件”“完工”这类动作分组非常方便。unit_price 用 decimal(10,2) 而不是 float是因为涉及费用结算时浮点数误差会导致配件成本对不上账。3.4 状态机报修系统最容易被忽略的流转规则有了表还要约定状态怎么流转。很多源码里 status 只是一个字段没有规则约束结果就是师傅手一抖把“待接单”直接点成“已完成”中间环节全部丢失。状态机的核心原则是每个状态只能由特定角色触发而且必须按顺序走。报修系统最少需要这样的流转链路待接单status0只能由管理员或师傅操作变成已派单status1师傅接单后变成维修中status2维修完成变成待回访status3回访电话打完确认没问题才变成已完成status4。已取消status5是例外只能从待接单或已派单状态来已经开工的单不允许取消。我整理成一张流转规则表来约束开发当前状态允许操作目标状态允许角色0 待接单派单1 已派单管理员0 待接单取消5 已取消管理员1 已派单接单2 维修中维修师傅1 已派单改派1 已派单管理员2 维修中提交完工3 待回访维修师傅3 待回访回访关闭4 已完成客服/管理员2 维修中标记失败6 待重派管理员这张表贴在代码注释里后端接口每次更新状态前先校验“当前状态、目标状态、操作人角色”三要素是否匹配。第 4 章我会给一个具体的校验实现。4. 用 PHP 把报修主流程跑通从本地最小命令到后台派单看板4.1 用 php -S 在本地跑通最小报修网站的命令拿到源码先别配 Nginx直接用 PHP 内置服务器把页面跑起来。这是最快验证源码可用的方式。在源码根目录执行下面命令cd repair-system php -S 0.0.0.0:8080执行完浏览器访问http://localhost:8080能看到前台报修页就说明 PHP 环境没问题。接着导入 install.sqlmysql -uroot -p -e CREATE DATABASE repair_system DEFAULT CHARACTER SET utf8mb4; mysql -uroot -p repair_system install.sql注意这里的两个细节数据库名要和 config.php 里的配置一致utf8mb4 字符集一定要指定否则客户地址里的生僻字和特殊符号会变成问号。本地跑通的意义在于先把“网站能不能打开、表单能不能提交”这两个前置问题解决再开始改业务。4.2 报修提交接口防 SQL 注入、防重复提交、防脏数据报修页面的核心接口是 create_order.php。这里最容易犯的错是直接把表单值拼进 SQL。我一般用 PDO 预处理并且做三层校验手机号格式、紧急程度范围、故障描述长度。下面是一份可以抄的接口骨架?php require_once ../include/db.php; header(Content-Type: application/json); $name trim($_POST[customer_name] ?? ); $phone trim($_POST[customer_phone] ?? ); $device_type intval($_POST[device_type] ?? 0); $fault_desc trim($_POST[fault_desc] ?? ); $urgent intval($_POST[urgent_level] ?? 0); if ($name || mb_strlen($name) 50) { exit(json_encode([code 1, msg 姓名不能为空且不超过50字])); } if (!preg_match(/^1[3-9]\d{9}$/, $phone)) { exit(json_encode([code 1, msg 手机号格式不正确])); } if ($urgent 0 || $urgent 2) { $urgent 0; } if (mb_strlen($fault_desc) 5) { exit(json_encode([code 1, msg 故障描述至少5个字])); } $orderNo RX . date(Ymd) . strtoupper(substr(uniqid(), -6)); $stmt $pdo-prepare( INSERT INTO orders (order_no, customer_name, customer_phone, device_type, fault_desc, urgent_level, status, created_at) VALUES (?, ?, ?, ?, ?, ?, 0, NOW()) ); $stmt-execute([$orderNo, $name, $phone, $device_type, $fault_desc, $urgent]); echo json_encode([code 0, msg 报修成功, order_no $orderNo]);这段代码的逻辑分三层第一层 trim、intval 做基础清洗第二层正则和长度做业务校验第三层 PDO 的 execute 绑定参数杜绝拼接注入。order_no 的生成规则是“RX 日期 uniqid 后六位”保证同一天内不会撞单。urgent_level 做了越界钳制目的是防止有人通过改前端请求提交 urgent999 把普通单刷成加急单。4.3 后台派单与状态更新事务、角色、状态机三连校验后台接口 update_status.php 比提交接口复杂得多。它要同时做“状态机校验、角色校验、数据更新、日志写入”四件事其中状态更新和日志写入必须在同一个事务里。下面这段代码是核心片段?php require_once ../include/db.php; require_once ../include/auth.php; require_admin(); // 未登录直接跳转 $order_id intval($_POST[order_id] ?? 0); $action $_POST[action] ?? ; // assign / accept / finish / cancel $assignee_id intval($_POST[assignee_id] ?? 0); $pdo-beginTransaction(); try { $stmt $pdo-prepare(SELECT status FROM orders WHERE id ? FOR UPDATE); $stmt-execute([$order_id]); $order $stmt-fetch(); if (!$order) { throw new Exception(工单不存在); } $old intval($order[status]); $allowMap [ assign [0 1], accept [1 2], finish [2 3], cancel [0 5, 1 5], ]; if (!isset($allowMap[$action][$old])) { throw new Exception(当前状态不允许该操作); } $new $allowMap[$action][$old]; if ($action assign) { $pdo-prepare(UPDATE orders SET status?, assignee_id?, accepted_atNOW() WHERE id?) -execute([$new, $assignee_id, $order_id]); } else { $pdo-prepare(UPDATE orders SET status? WHERE id?)-execute([$new, $order_id]); } $pdo-prepare(INSERT INTO repair_logs (order_id, operator_id, action, content, old_status, new_status, created_at) VALUES (?, ?, ?, ?, ?, ?, NOW())) -execute([$order_id, $_SESSION[user_id], $action, 状态变更, $old, $new]); $pdo-commit(); echo json_encode([code 0, msg 操作成功]); } catch (Exception $e) { $pdo-rollBack(); echo json_encode([code 1, msg $e-getMessage()]); }注意这段代码用到SELECT ... FOR UPDATE这是 MySQL 行级锁。报修网站并发不高但要防止两个管理员同时操作同一张单子。allowMap 这个二维数组就是前面状态机表的落地每个动作允许哪些状态迁移全都在这里定义。如果有人跳过当前状态构造 URL 直接改状态在这里就会被拦截。4.4 工单看板让经理一眼看清今天的积压情况后台 dashboard.php 不需要复杂图表一张聚合表比任何可视化都实用。我把当天所有工单按状态分组统计配合一个“超 2 小时未接单”的红灯列表基本就能掌握全店状态。核心 SQL 如下SELECT CASE status WHEN 0 THEN 待接单 WHEN 1 THEN 已派单 WHEN 2 THEN 维修中 WHEN 3 THEN 待回访 WHEN 4 THEN 已完成 ELSE 已取消 END AS status_name, COUNT(*) AS cnt FROM orders WHERE created_at CURDATE() GROUP BY status ORDER BY status;这个查询返回六个分组计数。看板页在渲染时我把“待接单”和“已派单”的数量加粗标红因为这两个数字代表今天的进账有没有人处理。更进阶一点的指标是“平均响应时长”用AVG(TIMESTAMPDIFF(MINUTE, created_at, accepted_at))算出来可以作为师傅月度绩效参考。报表越简单老板越爱看。5. 避坑报修网站上线的 5 个翻车点每个都是钱和关系的教训5.1 现象客户报修成功店里却没有一个人知道这是最严重的翻车。客户在页面上看到“提交成功”但后台没人收到短信工单躺在数据库里直到第二天老板翻后台才发现。原因源码把短信通知写在 create_order.php 的同步流程里短信 API 超时或者返回错误被 PHP 直接忽略异常被吞掉。解决把通知请求和报修提交拆开。报修提交只做 INSERT 操作同时往 notify_queue 表插一条“待发送”通知记录。另写一个 send_notify.php 脚本用 crontab 每分钟跑一次逐条发送并把状态改成“已发送”。这样即使短信 API 挂了订单也先落库不会丢单。我在所有项目里都保留这个队列表它也是后面加企业微信通知、邮件通知的扩展点。5.2 现象客户不停打电话催单因为他在前台看不到进度报修提交之后客户唯一能做的事就是打电话问“修好了没”。电话一多前台就没时间处理别的业务。原因源码只做了报修入口没做进度查询页。客户不知道工单卡在哪个环节自然只能打电话。解决做一个 query.php客户输入报修单号加手机号后四位就能看到当前状态。状态文案用大白话比如“师傅已接单预计今天上门”而不是“status1”。这个页面不需要登录但要加简单校验防止别人乱查隐私订单。做完这页之后前台接到的催单电话会少一半。5.3 现象后台导出 Excel 乱码手机号变成科学计数法导出报表是维修公司月底对账的刚需。客户名称正常但打开 CSV 后手机号显示成1.38E10中文全乱码。原因CSV 直接输出 UTF-8 编码Excel 默认按 GBK 解析手机号超过 12 位被 Excel 当作数值处理。解决导出 CSV 时在文件头添加 BOM 标记\xEF\xBB\xBF让 Excel 识别为 UTF-8。手机号等长数字字段在导出时前面加一个制表符\tExcel 就会按文本处理不转科学计数法。另外一个细节是用 PHP 的 fputcsv 时记得先fwrite($fp, \xEF\xBB\xBF)否则第一行表头第一个字可能变成乱码。5.4 现象两个师傅被派到同一个客户那里上门撞车一个地址上午十点被派给张师傅下午又被派给李师傅两个人都跑了客户一趟客户体验极差。原因派单逻辑只检查了师傅今天有没有单没检查时间段是否重叠。或者更原始的情况是源码根本没有派单冲突校验。解决派单接口里增加一个重叠检查同一师傅同一时间段内不能有两个未完工的工单。SQL 可以这样写SELECT COUNT(*) FROM orders WHERE assignee_id ? AND status IN (1, 2) AND created_at BETWEEN ? AND ?BETWEEN 的时间窗口我一般取 2 小时。如果返回值大于 0就弹提示“该师傅当前时段已有单建议换人或调整时间”。这个校验不复杂但它直接决定了门店的出勤效率和口碑。5.5 现象客户上传的故障照片打不开后台一片空白故障照片在排查问题时有重要作用但上线后经常遇到上传成功、后台查看时图片裂开的情况。原因数据库里存的是相对路径比如uploads/202405/12/a.jpg但网页部署在子目录里相对路径没有拼上子目录前缀或者上传的文件名是中文、带空格导致 URL 编码没处理好。解决数据库里统一存绝对路径对应的完整 URL例如/repair-system/uploads/202405/12/a.jpg上传文件时用date(Ymd)做目录按月归档文件名用uniqid()重命名彻底避开中文和空格。另外服务器上要检查 uploads 目录的写权限很多“图片传不上”的问题只是目录权限是 755 而 PHP 进程不是所有者。6. 上线前用一条命令生成 30 天模拟报修数据验收比嘴上说有用新系统上线前最怕的是老板打开后台发现空荡荡一片不知道列表长什么样。我会用脚本批量生成模拟工单来验收整个流程。下面这段脚本用 curl 循环调用本地接口模拟 20 个客户在不同时间报修for i in $(seq 1 20); do curl -X POST http://localhost:8080/api/create_order.php \ -d customer_name测试客户$i \ -d customer_phone1380000$(printf %04d $i) \ -d device_type$((i % 4)) \ -d fault_desc测试故障开机黑屏电源指示灯亮 \ -d urgent_level$((i % 3)) sleep 1 done注意 phone 参数用printf %04d把序号补成四位否则13800001、138000012这类号码长度不齐会触发手机号校验。device_type 用取模生成保证四种设备类型都有覆盖。跑完后执行下面 SQL 检查状态分布SELECT status, COUNT(*) FROM orders GROUP BY status; SELECT order_no, customer_name, status FROM orders ORDER BY id DESC LIMIT 5;第一条 SQL 看各状态订单是否正常第二条看最新工单是否完整写入。这一步没问题再让老板拿真实手机号下一单走完全流程。我现在上线任何一套报修系统都会先跑一遍模拟数据再把 install.sql 重新执行一次确保清库重装也能一键拉起来。这个习惯帮我避开了很多次“测试环境好好的、生产环境一跑就废”的尴尬希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站