☰
OA系统源码解析:PHP+MySQL老牌方案部署与二次开发指南
2026/10/6 16:14:16 网站建设 项目流程

简介:这是一份面向企业信息化建设者与PHP开发者的OA系统一体化源代码包,整合了OA审批、公文管理、人事管理、客户关系管理、财务管理、工程与项目管理、知识管理等多业务模块,支持流程与表单自定义配置,并且兼容PC端和移动端,可接入钉钉与企业微信,便于快速搭建或二次开发办公平台。包内含1403个文件,总大小约2.53MB,以702个PHP业务逻辑文件、177个HTML页面模板、169个JavaScript交互脚本以及231个GIF图标等为主,也包含CSS样式、SQL数据库脚本与字体文件,结构分类清晰,便于按模块定位与部署。已有221人学习下载。源码包附带了完整的数据库脚本与配置说明,可直接部署并利用初始管理员账号体验功能;对需要扩展企业OA能力或研究多模块集成方案的开发者,这套代码提供了实用的开发参考和基础框架。

1. 企业一体化办公平台 OA 源码:一套能跑十年的老牌方案

手里拿到这套「企业一体化办公平台 OA 系统源代码」的时候,第一反应是这玩意儿居然还活着。PHP 5.2 + MySQL 的组合,放在今天看像是上个时代的古董,但恰恰是这种古董级技术栈,造就了它极高的兼容性和极低的部署门槛。这套源码不单单是一个 OA——流程配置、表单配置是它的底座,上面还挂了公文管理、人事管理(EHR)、会员管理、行政管理、客户关系管理(CRM)、财务管理、工程管理、项目管理、知识管理等一整套模块,说它是半个 ERP 也不过分。它支持 PC 和手机双端访问,还能接入钉钉和企业微信,这意味着拿到手就能直接往企业内部推。适合谁?两类人:一是企业内部的 IT 运维或信息化负责人,想低成本快速搭一套能用的办公平台;二是想研究老牌 PHP 工作流引擎、表单引擎实现的开发者。接下来我按实际拆解顺序,把它从安装到二次开发讲透。

2. 拆解系统骨架:前端资源背后的技术栈与模块布局

2.1 从 CSS 文件嗅探前端技术选型

解压源码包后,先不急着看 PHP 文件,打开 css 目录扫一眼,信息量比想象中大。bootstrap_cerulean.css 是 Bootswatch 的 Cerulean 主题,Bootstrap 2.x 时代非常流行的一个蓝色系皮肤;font-awesome.min.css 是图标库,font-awesome-ie7.min.css 这个文件专供 IE7 兼容;weui.min.css 是微信团队的 Web UI 样式库,它的出现说明移动端页面刻意做得接近微信交互风格。再加上 default.css、webmain.css、webimcss.css、cssm.css 这些手写样式,基本可以还原出当时的设计思路:PC 端用 Bootstrap 搭框架,移动端套 WeUI 风格,图标统一走 FontAwesome。

这个选型放在当年非常务实。Bootstrap 2.x 对 IE8 的兼容性尚可,Cerulean 主题又是免费且观感专业的后台皮肤;WeUI 的引入让手机端不需要单独写一套 UI,直接复用微信生态的视觉语言。如果要做二次开发,建议保留这套前端体系,不要去升级 Bootstrap 版本——升级带来的 DOM 结构变化会让所有后台页面重写一遍,得不偿失。

2.2 功能模块地图:不止 OA,还是半个 ERP

从摘要描述可以确认这套系统包含十个以上业务模块。我按实际使用频率和业务关联度整理如下:

模块核心功能典型使用场景
流程配置流程模板设计、审批节点编排请假、报销、用章申请
表单配置自定义字段、表单布局业务数据采集、入离职登记
公文管理发文、收文、归档行政公文流转
人事管理(EHR)员工档案、考勤、工资HR 日常管理
客户关系管理(CRM)客户档案、跟进记录销售过程管理
项目管理任务分解、进度跟踪项目制协作
财务管理费用报销、应收应付财务数据归集
行政管理资产、宿舍、车辆行政后勤
知识管理文档库、分享、检索内部知识沉淀
会员管理会员档案、等级面向 C 端的组织

这些模块不是简单的菜单罗列,它们共享同一套用户体系和权限模型。也就是说,员工在 CRM 里维护的客户信息,可以在项目模块中被关联引用;公文审批的流程模板,也可以复用到人事模块的离职申请中。这个「流程引擎 + 业务模块」的设计,是这套源码最值钱的部分。

2.3 入口与权限模型:admin 登录后能看到什么

初始账号 admin / 123456,登录后进入的是系统管理后台。用惯了现代框架的人第一次进去可能会觉得土——没有仪表盘大屏,没有酷炫的图表,但权限划分是清晰的老式三层次:系统管理员(admin)、部门管理员、普通员工。菜单的可见性按角色配置,每个角色的可操作按钮(增删改查、导出、审批)可以精确到具体模块。

如果你打算把它作为企业内部系统正式用起来,上线第一步一定是修改 admin 密码,然后按部门建立角色、分配权限。源码里权限配置的数据结构是角色 → 菜单 → 操作按钮三层映射,在数据表中表现为用户表、角色表、权限表、菜单表四张核心表的关联。二次开发时想要给某个角色增加一个「导出工资单」的按钮,就是往菜单表插一条记录并绑定到对应角色,不需要动 PHP 逻辑。

3. 部署落地:环境选型、数据库导入与配置改写全流程

3.1 环境选型:为什么 PHP 5.2 反而是优势

这套系统要求 PHP 5.2 + MySQL,这在今天的新机器上是个麻烦事——PHP 官方在 5.3 起废弃了mysql_*系列函数,到 PHP 7 直接移除。但反过来说,它能跑在 PHP 5.2 上,意味着任何一台装了老版 phpStudy 或 XAMPP 的 Windows 机器都能直接跑起来,不需要处理 Composer 依赖、不需要 Node 环境,解压即用。这正是老项目的优势:依赖极简,逻辑自洽。

Windows 下我用的是 phpStudy 2016 老版本(集成 PHP 5.2.17 + MySQL 5.1),Linux 下建议用宝塔面板装 PHP 5.2 或手动编译。MySQL 版本控制在 5.1 ~ 5.5 之间,不要用 5.7 以上,因为老代码的 SQL 写法可能与新版 MySQL 的默认 SQL_MODE(如 ONLY_FULL_GROUP_BY)冲突。

3.2 数据库初始化:导入 webmain/install/db.sql

数据库文件在webmain/install/db.sql,这是一个完整的数据字典加初始数据的 SQL dump。导入方式有两种:

# 方式一:直接用 mysql 命令导入(先建库再导入) mysql -uroot -p -e "CREATE DATABASE oa_db DEFAULT CHARACTER SET utf8;" mysql -uroot -p --default-character-set=utf8 oa_db < webmain/install/db.sql # 方式二:进入 mysql 交互终端后操作 mysql -uroot -p > CREATE DATABASE oa_db DEFAULT CHARACTER SET utf8; > USE oa_db; > SOURCE webmain/install/db.sql;

这里有一个关键参数:--default-character-set=utf8。如果省略,Windows 命令行默认的 GBK 编码会把中文数据导成乱码,导致登录后整个界面出现「锟斤拷」字符集灾难。导入完成后可以快速验证一下:

USE oa_db; SHOW TABLES; -- 正常情况应看到几十张表,名称类似 sys_user、flow_template 等 SELECT COUNT(*) FROM sys_user; -- 初始管理员 1~2 条记录

看到表结构,基本能确认数据库导入没问题。这里补充一句:db.sql 里除了用户表,还会写入流程模板的初始分类、表单字段的初始字典等,这些基础数据决定后续流程配置时下拉框里有哪些选项,轻易不要手动去改。

3.3 配置文件改写:webmainConfig.php1 与 randkey

源码包里默认没有webmainConfig.php,只有一个webmainConfig.php1,这是安装程序的保险机制——只有等你把参数填好了才允许改名激活。进入webmain目录,执行改名:

mv webmain/webmainConfig.php1 webmain/webmainConfig.php

然后编辑这个文件,核心配置项如下:

<?php // webmain/webmainConfig.php 关键配置 $db_host = '127.0.0.1'; // 数据库地址,本机用 127.0.0.1,远程填 IP $db_user = 'root'; // 数据库账号 $db_pwd = 'your_password'; // 数据库密码,改成你自己的 $db_name = 'oa_db'; // 数据库名,与导入时建的库一致 $randkey = 'almvhcusrywkxvnzgdjtciodnu'; // 加密密钥,必须填写

参数说明:$db_host如果是远程数据库,建议把127.0.0.1改成实际 IP,同时确认 MySQL 允许远程连接(GRANT ALL ON oa_db.* TO 'root'@'%')。最关键的$randkey——它是一个 26 位的固定字符串,用来做密码散列和 Cookie 加密的盐值。这个值不是让你随便写的,必须用资源里给的那串almvhcusrywkxvnzgdjtciodnu。如果随意改成别的,轻则登录态无法保持,重则已存储的密码散列全部无法校验,等于把系统锁死。

原文还有个容易忽略的步骤:删除webmain/webmainConfig.php1。注意改名之后源码包里已经没有这个文件了,但如果你的备份里有,需要手动删除;同时删除webmain/install整个目录。这是安全要求——install 目录如果保留,攻击者可以重新执行安装脚本,直接覆盖数据库和配置文件,这是这类老系统最致命的漏洞。

3.4 Linux 部署的文件权限与目录隔离

Linux 下的坑比 Windows 多一个:文件权限。老代码普遍喜欢直接写文件(比如缓存、上传的附件),如果 webroot 目录的属主不是 PHP 运行用户,会出现「上传附件失败」「验证码图片无法生成」这类诡异问题。

# 以 nginx + php-fpm 为例,php-fpm 运行用户是 www-data chown -R www-data:www-data /var/www/html/oa chmod -R 755 /var/www/html/oa # 上传目录建议放宽写权限,一般是在 uploads/ 或 data/ 目录下 chmod -R 777 /var/www/html/oa/uploads 2>/dev/null || true

部署完成后,浏览器访问http://127.0.0.1/,用 admin / 123456 登录。如果一切正常,左侧菜单会完整显示全部模块;如果只显示空白页,大概率是$db_pwd配错了或 randkey 没填——别急着换环境,先回溯这两个参数。

4. 流程与表单配置实战:从请假审批流到自定义字段

4.1 流程配置的底层逻辑:模板、节点、实例三层模型

这套系统的流程引擎是典型的表驱动设计,核心概念可以拆成三层:流程模板、流程节点、流程实例。流程模板定义「这个流程叫什么、有哪些审批步骤」;流程节点定义「每一步谁来审批、满足什么条件跳哪一步」;流程实例是一条真实的业务数据(比如某员工提交的请假单)在模板上跑出来的结果。

打开源码中的流程相关数据表,你会发现实际存储结构与概念一一对应:

-- 流程模板主表:定义流程名称、状态、分类 SELECT * FROM flow_template WHERE status = 1; -- 流程节点表:定义节点顺序、审批人角色、条件分支 SELECT * FROM flow_node WHERE template_id = 1 ORDER BY node_order;

在界面上配置一个「请假审批」流程,操作路径通常是:流程配置 → 新建流程模板 → 依次添加节点。节点类型一般分三种:发起节点、审批节点、抄送节点。审批节点需要设置审批人来源——可以指定某个角色(如「部门经理」),也可以指定表单字段(如「申请人所在部门」),这属于动态审批人的玩法,老手常用,新手建议先从固定角色配起。

4.2 表单配置:自定义字段的类型与校验

流程要处理的数据,由表单配置来定义。这个系统里表单配置相当于单独的一个设计器,支持常见字段:单行文本、多行文本、数字、日期、下拉选择、单选、多选、附件、人员选择器。每类字段都有几个关键属性:

字段类型核心属性典型用途
单行文本长度上限、默认值、必填标题、单号
数字最小值、最大值、小数位金额、天数
日期日期格式、默认值为当天开始日期、结束日期
下拉选择选项数据源、级联关系部门、城市
附件文件类型限制、大小上限合同扫描件
人员选择器可选范围(部门/全员)审批人、经办人

配置表单时最容易忽视的是「字段与流程节点的绑定关系」。比如请假单里「请假天数」字段,在流程第三个节点(总监审批)时应当是只读的,不能让审批人乱改。这个权限粒度需要在表单字段配置里逐个设置:该字段在哪些节点可编辑、哪些节点只读、哪些节点必填。源码层面其实就是一个字段权限表的维护,但 UI 上做得比较隐晦,需要把节点切换到对应步骤才能看到字段的编辑权限开关。

4.3 实例化运行:从提交申请到审批完成的数据流转

配置好流程模板和表单之后,员工提交申请时,系统会创建一条流程实例记录,表单数据作为实例的快照存储在业务表中。审批人登录后能从待办列表看到这条实例,点开详情即是表单内容 + 历史审批记录。每个审批动作(同意/驳回/撤回)都会更新流程实例的当前节点指针和状态字段。

在实际使用中,我的习惯是在上线前先做一轮「全流程冒烟测试」:自己建一个测试部门、测试角色,跑一遍「发起 → 部门主管同意 → 总监同意 → 备案完成」的完整链路,然后故意发起一条驳回记录,确认节点状态回退正确。这个测试周期一般在半天到一天,能筛掉流程配置里 90% 的坑,比如节点顺序配反、审批人角色还没建好、字段权限未放行等。

5. 部署与运行的常见坑:现象、原因与解法

5.1 首页 500 错误或空白页

现象:数据库导入成功、配置文件也改好了,但访问首页直接白屏或 HTTP 500。

原因:90% 的情况是webmainConfig.php里的$randkey没填,或者$db_pwd与实际数据库密码不一致导致连接失败但错误提示被关闭。剩下的 10% 是 PHP 版本太新(5.3+ 把mysql_*函数的 E_DEPRECATED 提升到了 E_WARNING,某些主机display_errors开启后直接崩掉)。

解决:先开 PHP 错误显示临时排查——在 web 入口文件头部加ini_set('display_errors', 1); error_reporting(E_ALL);,刷新看具体报错。如果是数据库连接失败,回查配置文件;如果是 randkey 未填导致密码校验错乱,重置为那 26 位固定值并重启 PHP-FPM。这套系统不需要 Composer、不需要改伪静态,报错一定在 PHP 语法或配置参数上。

5.2 MySQL 高版本导致的「数据连接失败」与 SQL 执行中断

现象:MySQL 5.7/8.0 环境下身强 MySQL 连接失败,或者导入 db.sql 时报错中断,但前几张表已经导入成功。

原因:新旧 MySQL 的认证插件事。8.0 默认caching_sha2_password,老 PHP 的mysql_connect不支持这种认证方式;另外 db.sql 里的某些 SQL 写法(比如TYPE=MyISAM这种旧语法)在 MySQL 5.7+ 会直接报警告并中断导入。

解决:用 MySQL 5.5 或 5.1 是正解;如果必须用 8.0,可以ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';改回旧认证方式。SQL 导入中断的补救:删除库后重新导入前先检查 SQL 文件头部有没有SET SQL_MODE之类的兼容声明,没有就自己在命令行加--force参数忽略非致命错误。

5.3 中文乱码:登录后页面全是「锟斤拷」

现象:数据库导入成功,登录后菜单、模块名、系统设置全部乱码。

原因:Windows 命令行导入 SQL 时,客户端默认字符集是 GBK,导致把 UTF-8 源码当成 GBK 解码后写入数据库,数据本身已损坏。

解决:这个没有后悔药,只能删库重新导入。正确姿势一定是mysql --default-character-set=utf8 oa_db < db.sql。导入后在 PHP 配置文件里确认$db_charset = 'utf8';(如果有这个参数),保证运行态连接也走 UTF-8。

5.4 手机端访问样式错乱,CSS 全部丢失

现象:PC 端正常,手机浏览器打开页面是纯 HTML 不带样式,或者图片路径 404。

原因:URL 重写或入口文件名不对。这套系统手机端和 PC 端共用一套资源,但 CSS 路径通常是相对路径。如果你把系统装在子目录(如/oa/),而代码里写的是绝对路径/css/webmain.css,那 HTML 会去域名根目录找 CSS,自然 404。

解决:将系统装在域名根目录或独立子域名下,不要放二级目录。或者统一入口用http://127.0.0.1/访问,浏览器会自动解析相对路径。还有一种低频原因:webimcss.css 或 cssm.css 里引用的字体文件font-awesome.eot的 MIME 类型没在服务器配置,需要给 Nginx 加types { font/ttf ttf; }之类映射。

5.5 忘了删 install 目录引发的「重新安装覆盖」

现象:初始化完成后没有删除webmain/install,某天访问http://127.0.0.1/install/,出现重新安装引导界面;如果点下去,数据库会被清空重建,业务数据全部归零。

原因:安装脚本检查的是「配置文件和 install 目录是否同时存在」。配置文件已被改名激活,但 install 目录还在,安装脚本认为需要执行升级或重装流程。

解决:部署第一步就删。在 Linux 下执行rm -rf webmain/install,Windows 下直接右键删除。如果已经误操作导致数据被覆盖,只能靠数据库备份恢复。我的习惯是在部署完成后打包一份数据库转储放到服务器外,作为第一个恢复点。

6. 进阶玩法:钉钉 / 企业微信接入与老 PHP 代码的兼容层

如果你要把这套 OA 真正推给全员用,手机端是绕不开的。虽然源码自带手机适配页面,但员工不可能每天记一个网址。接入钉钉或企业微信的标准做法是把 OA 塞进对方的 H5 微应用框架里。以钉钉为例,在钉钉开放平台创建一个 H5 微应用,首页 URL 填http://your-domain/mobile.php,再配一个可信域名,员工就可以在钉钉工作台直接打开 OA。这里的关键是免登——钉端会往 URL 带一个authCode,后端拿这个 code 去钉钉开放接口换用户身份,再映射到 OA 系统的员工账号上。

免登接口对接的底层逻辑如下:

<?php // 钉钉免登对接示意:用 authCode 换取用户身份 $code = $_GET['authCode']; // 钉钉微应用带过来的授权码 $dd_access_token = get_dingtalk_token($app_key, $app_secret); // 调用钉钉接口:用 code 换用户 userid $user = http_post("https://oapi.dingtalk.com/topapi/v2/user/getuserinfo", array( 'access_token' => $dd_access_token, 'code' => $code )); if ($user['errcode'] == 0) { $oa_username = $user['result']['name']; // 钉钉名字,需与 OA 账号关联 // 根据 $oa_username 查 OA 的 sys_user 表,创建会话 $_SESSION['user'] = $oa_username; header('Location: index.php'); }

这个接入方案我实际落地过两次,最大的麻烦点在于账号映射——钉钉用户表里的员工姓名和 OA 里的姓名要保持一致,或者做一个「钉钉 userId ↔ OA uid」的映射表。建议先导出两份名单做比对,把差异项在入职流程里统一掉,不然用户提了免登申请还要走一遍手工绑定,体验会打折。

再说 PHP 兼容补丁。如果你的服务器只能装 PHP 7.4(比如用了较新的云主机镜像),老代码的mysql_*函数会直接 fatal error。有个低成本方案是写一个兼容 shim 文件:

<?php // mysql_* 兼容层,放到入口文件里 require 即可 if (!function_exists('mysql_connect')) { function mysql_connect($host, $user, $pwd) { $conn = new mysqli($host, $user, $pwd); return $conn; } function mysql_select_db($db, $conn = null) { $conn = $conn ?: new mysqli('127.0.0.1', 'root', ''); return $conn->select_db($db); } function mysql_query($sql, $conn = null) { $conn = $conn ?: new mysqli('127.0.0.1', 'root', ''); return $conn->query($sql); } function mysql_fetch_assoc($result) { return $result->fetch_assoc(); } // 其余 mysql_* 函数按同样方式逐个补全 }

注意这样只能解燃眉之急——mysqli 和 mysql 的 API 略有差异,某些老代码里的mysql_fetch_array($result, MYSQL_ASSOC)第二参数是不存在的,shim 里要兼容。更稳妥的做法是全局搜索源码中的mysql_前缀,写脚本批量替换为mysqli_并同步修改参数顺序。但这属于较大改造,非必要不推荐,还是找一台老环境最省事。

部署验证的最后一步,我会写一个检查清单:数据库表数量正确、admin 能登录、能新建流程模板、能提交一条请假申请、待办列表能收到通知。走完这五步,这套 OA 才算真正交付。说到底,老代码的价值在于它能稳定解决 80% 的通用办公需求,剩下的 20% 需要你理解它的脾气。印象最深的是有一次客户环境 PHP 版本装成了 7.1,我坚持让他们降到 5.2,这十分钟的坚持换来的是后面两年没出过一次运行时错误。从那以后我每次接手老 PHP 项目,都强制先确认 PHP 版本与mysql_*函数可用性,再谈别的优化。希望这些经验帮到你,下载源码后按上面的顺序一步步走,这套系统能比你想的更稳。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询