本手册包含安装口令与初始管理员账号,仅用于首次部署。系统上线前请立即修改默认密码、关闭或限制安装向导访问,并按第十二章完成安全加固。
一、部署前先弄懂这几件事
1.1 这套系统由哪几部分组成
| 组成部分 | 作用 | 通俗理解 |
|---|---|---|
| Nginx | 网站服务器,负责把浏览器请求转给程序 | 大楼的「前台」 |
| PHP 8.1 / 8.2 | 运行业务代码 | 干活的「员工」 |
| MySQL 5.7 / 8.0 | 保存客户、人员、证书、费用等全部数据 | 仓库的「账本」 |
| Redis 7(必需) | 保存登录状态、菜单、字典等缓存 | 员工的「便签本」 |
| 前端页面 | 已经打包好,放在 backend/public/web、backend/public/mobile |
已经装修好的「房间」 |
重要:Redis 是硬性依赖。 系统不会在 Redis 不可用时自动改用文件缓存,而是直接返回 503 并提示检查 Redis。这样设计是为了避免多台服务器登录状态不一致。安装前请务必先把 Redis 跑起来。
1.2 部署完成后你能得到什么
| 入口 | 地址示例 | 用途 |
|---|---|---|
| PC 管理端 | https://cert.example.com/web/ |
日常办公主界面 |
| 手机 H5 | https://cert.example.com/mobile/ |
手机浏览器、企业微信内使用 |
| 后端接口 | https://cert.example.com/api/ |
前后端通信、Agent 接入 |
| 安装向导 | https://cert.example.com/install.php |
只在首次安装时使用 |
直接访问 https://cert.example.com/ 时,系统会按浏览器类型自动跳转到 /web/ 或 /mobile/。
1.3 三个名词,先记住
- 网站根目录:本系统必须指向
backend/public,不是项目根目录,也不是backend。这是新手最容易配错的一步。 - 伪静态:让
/certificate这类页面地址能正确找到程序。不配置的话,登录后一刷新就 404。 - 定时任务:服务器每天自动执行一次「证书到期检测」和「政务网进度同步」。不配置的话,到期提醒不会自动发出。
二、服务器与环境要求
2.1 软件版本
| 软件 | 要求 | 说明 |
|---|---|---|
| 操作系统 | Linux(CentOS 7+ / Ubuntu 20.04+ / Debian 10+) | 生产环境不建议用 Windows |
| Nginx | 1.20 及以上 | 需要支持伪静态 |
| PHP | 8.1 或 8.2(最低 8.1) | PHP 7.x 无法运行;8.3 及以上尚未充分验证,生产建议用 8.1/8.2 |
| MySQL | 5.7 或 8.0 | 字符集必须 utf8mb4 |
| Redis | 5.0 及以上,推荐 7.x | 必须能连通,必须设密码(生产) |
| 浏览器 | Chrome / Edge 最新版 | 不建议 IE |
2.2 PHP 扩展(必装)
| 扩展 | 用途 | 缺失后果 |
|---|---|---|
pdo_mysql |
连接 MySQL | 无法安装、无法打开任何页面 |
mbstring |
中文字符处理 | 中文乱码、Excel 导入失败 |
fileinfo |
上传文件真实类型校验 | 附件上传失败 |
gd |
登录图形验证码 | 验证码不显示,无法登录 |
curl |
推送、政务网同步、在线升级 | 推送和同步失败 |
dom / libxml |
Excel 读写 | 导入导出报错 |
openssl |
加密、HTTPS 请求 | 密码托管、推送失败 |
zip |
在线升级、备份 | 在线升级不可用 |
opcache(建议) |
提升 PHP 性能 | 页面变慢,但不影响使用 |
redis(可选) |
更快的 Redis 客户端 | 没有时会使用内置 Predis,仍可运行 |
2.3 PHP 关键参数
在 php.ini 中确认(宝塔在「软件商店 → PHP 8.x → 配置修改」):
memory_limit = 512M
upload_max_filesize = 20M
post_max_size = 24M
max_execution_time = 300
max_input_time = 300
date.timezone = Asia/Shanghai
display_errors = Off
log_errors = On
expose_php = Off
[opcache]
opcache.enable = 1
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 32
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0
opcache.revalidate_freq = 0
opcache.save_comments = 1
opcache.validate_timestamps = 0表示 PHP 不会自动发现代码变化。每次升级或手工改代码后,必须重启 PHP-FPM(宝塔:软件商店 → PHP → 重启;Docker:重启 php 容器)。
2.4 服务器配置建议
| 规模 | 账号数 | 峰值并发 | CPU | 内存 | 系统盘 | 数据盘 | 带宽 |
|---|---|---|---|---|---|---|---|
| 小型 | ≤ 50 | ≤ 20 | 2 核 | 4 GB | 40 GB SSD | 100 GB SSD | 5 Mbps |
| 中型 | 50–200 | ≤ 60 | 4 核 | 8 GB | 60 GB SSD | 300 GB SSD | 10 Mbps |
| 大型 | 200–500 | ≤ 150 | 8 核 | 16 GB | 100 GB SSD | 500 GB+ NVMe | 20–50 Mbps |
磁盘请优先 SSD。附件(证书扫描件、合同、资质图片)是增长最快的部分,建议单独挂数据盘。
2.5 网络与端口
| 方向 | 端口/地址 | 用途 |
|---|---|---|
| 入站 | 80、443 | 网站访问 |
| 入站 | 22(建议限制来源 IP) | SSH 运维 |
| 出站 | https://hngcjs.hnjs.henan.gov.cn |
河南建筑市场监管平台采集 |
| 出站 | https://www.hnzwfw.gov.cn |
河南政务服务网申报进度同步 |
| 出站 | https://qyapi.weixin.qq.com |
企业微信登录、通讯录、推送 |
| 出站 | SMTP 服务器端口(25/465/587) | 邮件提醒 |
| 出站 | https://gitee.com |
在线升级检查与下载 |
MySQL 3306、Redis 6379 不要对公网开放。只监听
127.0.0.1或内网地址。
三、部署前的准备清单
动手前,请先把下面这些信息写在纸上或记事本里:
| 项目 | 示例 | 你的值 |
|---|---|---|
| 服务器公网 IP | 123.123.123.123 |
|
| 域名 | cert.example.com |
|
| 域名是否已解析到服务器 | 是 / 否 | |
| 服务器 SSH 账号 | root |
|
| SSH 密码或密钥 | — | |
| MySQL root 密码 | 32 位随机字符串 | |
| 数据库名 | cert_agent |
|
| 数据库账号 | cert_agent |
|
| 数据库密码 | 32 位随机字符串 | |
| Redis 密码 | 32 位随机字符串 | |
| 管理员账号 | admin |
|
| 管理员密码 | 8–32 位,含字母和数字 | |
| 站点根目录 | /www/wwwroot/cert-agent/backend/public |
密码建议统一用密码管理器生成,至少 16 位,包含大小写字母、数字和符号。不要使用
123456、admin123上线。
四、方式一:宝塔面板部署(最推荐,小白首选)
宝塔面板是图形化服务器管理工具,可以用鼠标完成 90% 的部署工作。以下步骤以宝塔 7.9+ 为例。
4.1 安装宝塔面板
- 用 SSH 登录服务器。
- 到宝塔官网复制对应系统的安装命令,粘贴执行。
- 安装完成后,终端会输出面板地址、用户名、密码,请保存好。
- 浏览器打开面板地址,登录。
- 首次登录会提示安装运行环境,选择 LNMP(Nginx + MySQL + PHP),不要选 LNMPA 或 LAMP。
4.2 安装软件(软件商店)
在「软件商店」依次安装并等待完成:
| 软件 | 版本 | 备注 |
|---|---|---|
| Nginx | 1.22 或更高 | 已随 LNMP 安装 |
| MySQL | 8.0(或 5.7) | 已随 LNMP 安装 |
| PHP | 8.2(或 8.1) | 必须这个版本 |
| Redis | 7.x | 必装 |
| phpMyAdmin | 任意 | 可选,方便看数据库 |
安装 PHP 后,点「设置 → 安装扩展」,确认已安装:
pdo_mysql mbstring fileinfo gd curl dom libxml openssl zip opcache
如果列表里没有
redis扩展也没关系,系统自带 Predis 客户端。装了会更快。
4.3 调整 PHP 配置
在「软件商店 → PHP 8.2 → 配置修改」中,把第二章 2.3 的参数填进去,保存。
再点「禁用函数」,如果列表里有下面这些,删除它们(表示允许使用):
putenv proc_open shell_exec exec system passthru
putenv被禁用会导致程序读不到.env,表现为「数据库连接失败」。exec等函数用于在线升级时调用mysqldump备份数据库。
保存后重启 PHP。
4.4 上传代码
方式 A:Git 拉取(推荐,后续可在线上更新)
cd /www/wwwroot
git clone https://gitee.com/kxunyun/cert-expiry-manager.git cert-agent
仓库是私有的,执行时会要求输入 Gitee 账号和密码/私人令牌。如果没有仓库权限,请使用方式 B。
方式 B:上传压缩包
- 在宝塔「文件」中进入
/www/wwwroot。 - 上传项目压缩包(
.zip)。 - 右键解压,把目录重命名为
cert-agent。 - 确认目录结构如下:
/www/wwwroot/cert-agent/
├── backend/ ← 后端(重点)
│ ├── public/ ← 网站根目录必须指向这里
│ │ ├── index.php
│ │ ├── install.php
│ │ ├── web/ ← PC 端页面(已打包)
│ │ ├── mobile/ ← 手机端页面(已打包)
│ │ └── uploads/ ← 附件目录
│ ├── app/
│ ├── config/
│ ├── database/
│ ├── runtime/ ← 运行时目录(必须可写)
│ ├── vendor/ ← PHP 依赖(已内置)
│ └── .env.example
├── frontend/ ← PC 端源码(一般不用管)
├── mobile/ ← 手机端源码(一般不用管)
└── docs/
不需要安装 Composer,也不需要安装 Node.js。
vendor、web、mobile都已随包提供。
4.5 创建站点
宝塔「网站 → 添加站点」:
| 配置项 | 填写 |
|---|---|
| 域名 | cert.example.com(没有域名可先填服务器 IP) |
| 根目录 | /www/wwwroot/cert-agent/backend/public |
| FTP | 不创建 |
| 数据库 | 不创建(安装向导会自动建库) |
| PHP 版本 | PHP-82 |
创建完成后,点站点「设置」:
- 网站目录:运行目录选择
/public(如果宝塔提供该选项)。 - 网站目录 → 防跨站攻击(open_basedir):取消勾选。
项目根目录和
public不在同一层,开启后程序读不到上级的.env和app/,会直接 500。 - 伪静态:粘贴下面内容并保存:
location / {
index index.php index.html index.htm;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
}
- 配置文件:如果你想进一步优化,可在
server { }内补充:
client_max_body_size 24m;
gzip on;
gzip_vary on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml image/svg+xml;
fastcgi_connect_timeout 10s;
fastcgi_send_timeout 300s;
fastcgi_read_timeout 300s;
保存后点「重载配置」或重启 Nginx。
4.6 设置目录权限
用 SSH 执行(宝塔站点用户通常是 www):
cd /www/wwwroot/cert-agent/backend
chown -R www:www runtime public/uploads
chmod -R 755 runtime public/uploads
如果站点用户是
nginx或apache,把www:www换成对应用户。权限不对的表现是:首页 500、验证码不显示、附件上传失败、安装向导提示目录不可写。
4.7 准备数据库(二选一)
做法 A:让安装向导自动建库(最简单)
安装向导会自动执行 CREATE DATABASE,只需要准备一个 MySQL 账号(root 或独立账号)和密码。
做法 B:手工建库(推荐生产环境,权限更小)
宝塔「数据库 → 添加数据库」:
| 项 | 值 |
|---|---|
| 数据库名 | cert_agent |
| 用户名 | cert_agent |
| 密码 | 强随机密码 |
| 字符集 | utf8mb4 |
或者用命令行:
CREATE DATABASE `cert_agent` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'cert_agent'@'localhost' IDENTIFIED BY '这里换成强密码';
GRANT ALL PRIVILEGES ON `cert_agent`.* TO 'cert_agent'@'localhost';
FLUSH PRIVILEGES;
生产环境不要用 root 跑业务。独立账号只需对
cert_agent库有全部权限即可。
4.8 准备 Redis
宝塔「软件商店 → Redis → 设置」:
- 确认服务状态为「运行中」。
- 在「配置修改」中设置密码:
requirepass 这里换成强密码
bind 127.0.0.1
maxmemory 1gb
maxmemory-policy allkeys-lru
appendonly yes
- 保存并重启 Redis。
- 命令行验证:
redis-cli -a '你的Redis密码' ping
# 返回 PONG 表示正常
如果服务器上还有别的系统也用 Redis,请给本系统分配独立 DB 编号(如
DB=1)和独立前缀(如cert:),避免互相清缓存。
4.9 运行网页安装向导
浏览器打开:
http://你的域名/install.php
第一步:环境检测
向导会自动检查 PHP 版本、扩展、目录权限、SQL 文件。所有项目显示绿色「通过」再点下一步。
常见红色项及处理:
| 提示 | 处理 |
|---|---|
| PHP 版本过低 | 把站点 PHP 版本切到 8.2 |
| 缺少 gd / fileinfo / pdo_mysql | 宝塔 PHP → 安装扩展 |
| 目录不可写 | 执行 4.6 的权限命令 |
| 缺少 Redis 客户端 | 安装 phpredis 扩展,或确认 backend/vendor 完整 |
| SQL 文件不存在 | 确认 backend/database/init.sql、init_data.sql 已上传 |
第二步:填写配置
| 字段 | 填什么 | 说明 |
|---|---|---|
| 数据库主机 | 127.0.0.1 |
数据库和网站同一台服务器就填这个 |
| 端口 | 3306 |
默认 |
| 数据库名 | cert_agent |
不存在会自动创建 |
| 数据库用户名 | cert_agent 或 root |
建议独立账号 |
| 数据库密码 | 对应密码 | 失败后需要重新输入 |
| Redis 主机 | 127.0.0.1 |
同机 |
| Redis 端口 | 6379 |
默认 |
| Redis 密码 | 你的 Redis 密码 | 没设密码可留空 |
| Redis 数据库编号 | 0 或独立编号 |
多系统共用时务必区分 |
| Redis 键前缀 | cert: |
不同部署用不同前缀 |
| 管理员账号 | admin |
登录账号 |
| 管理员姓名 | 系统管理员 |
显示用 |
| 管理员密码 | 8–32 位,含字母和数字 | 请立刻记下来 |
密码里如果包含
$、#、;、引号等特殊字符,系统会按原样写入.env,不需要手工转义。
点击「开始安装」。向导会依次:
- 检测 Redis 读写、过期、删除;
- 连接 MySQL;
- 创建数据库;
- 导入
init.sql(建表); - 导入
init_data.sql(角色、菜单、字典、消息模板、示例数据); - 创建管理员;
- 生成
backend/.env; - 生成
backend/runtime/install.lock(安装锁)。
只有 Redis 和数据库都检测通过,才会真正写入。 失败不会生成安装锁,也不会把密码显示在页面上;重新提交时需要重新输入数据库和 Redis 密码。
第三步:完成
页面会显示 PC 端和手机端地址:
- PC 管理端:
http://你的域名/web/ - 手机 H5:
http://你的域名/mobile/
打开 PC 端,用刚才设置的管理员账号登录。
4.10 安装后立刻做的 5 件事
- 确认安装锁存在:
ls -l /www/wwwroot/cert-agent/backend/runtime/install.lock
- 限制安装器访问(生产建议)。站点「配置文件」加入:
location = /install.php {
allow 192.168.0.0/16;
allow 127.0.0.1;
deny all;
}
安装锁本身已经能阻止重复安装,这一步是额外保护。
-
确认
APP_DEBUG = false:查看backend/.env,安装向导会自动设为 false。 -
申请 HTTPS:站点「SSL → Let's Encrypt」,申请后开启「强制 HTTPS」。
-
修改 CORS 白名单:编辑
backend/config/security.php,把cors_allowed_origins改成你的实际域名:
'cors_allowed_origins' => [
'https://cert.example.com',
],
不要保留
*,也不要把127.0.0.1:8000这类开发地址留在生产配置里。
4.11 配置定时任务(宝塔)
「计划任务 → 添加任务」:
| 项 | 值 |
|---|---|
| 任务类型 | Shell 脚本 |
| 任务名称 | 证书到期检测 |
| 执行周期 | 每天 08:00(或每小时) |
| 脚本内容 | 见下 |
cd /www/wwwroot/cert-agent/backend && /www/server/php/82/bin/php think cert:checkexpire --catch-up >> runtime/cron.log 2>&1
再加一条政务网同步:
cd /www/wwwroot/cert-agent/backend && /www/server/php/82/bin/php think gov:sync >> runtime/cron.log 2>&1
PHP 路径以宝塔实际为准,常见为
/www/server/php/82/bin/php。不要用php裸命令,定时任务环境里可能找不到。 详细说明见第九章。
4.12 宝塔部署最容易踩的 6 个坑
| 坑 | 现象 | 解决 |
|---|---|---|
根目录指到项目根或 backend |
首页 404 / 直接下载源码 | 必须指到 backend/public |
| 没配伪静态 | 登录后刷新 404 | 粘贴 4.5 的伪静态 |
| 开着防跨站攻击 | 500,日志提示 open_basedir | 关闭 open_basedir |
runtime 不可写 |
500、验证码空白 | chown -R www:www runtime |
| PHP 版本是 7.4 | 500 / 语法错误 | 切到 8.1 或 8.2 |
| Redis 没启动或密码错 | 页面 503,提示 Redis 不可用 | 启动 Redis、核对密码,执行 php think redis:check |
五、方式二:Docker 一键部署
适合有 Docker 基础的团队。Docker 方式不使用网页安装器,首次启动会自动建库并导入数据。
5.1 前提
- 已安装 Docker 24+ 与 Docker Compose v2;
- 服务器能拉取
mysql:8.0、redis:7-alpine、nginx:alpine镜像; - 80/8080 端口未被占用。
5.2 配置环境变量
cd 项目目录/docker
cp .env.example .env
编辑 docker/.env,至少修改这三项:
MYSQL_ROOT_PASSWORD='换成强随机密码'
REDIS_PASSWORD='换成另一个强随机密码'
GOV_PASSWORD_KEY='换成32位以上随机字符串'
其余可选项:
| 变量 | 默认 | 说明 |
|---|---|---|
MYSQL_DATABASE |
cert_agent |
数据库名 |
MYSQL_PORT |
3306 |
只绑定宿主机 127.0.0.1 |
REDIS_PORT |
6379 |
Redis 端口(不映射到宿主机) |
REDIS_DB |
0 |
Redis 库号 |
REDIS_PREFIX |
cert: |
键前缀 |
HTTP_PORT |
8080 |
对外访问端口 |
HTTP_BIND |
0.0.0.0 |
生产建议改成内网 IP 或 127.0.0.1,由外层 Nginx 转发 |
MYSQL_MEM_LIMIT |
3g |
MySQL 内存上限 |
PHP_MEM_LIMIT |
2g |
PHP 内存上限 |
REDIS_MEM_LIMIT |
1g |
Redis 内存上限 |
密码包含
$时,用单引号包住整个值,例如MYSQL_ROOT_PASSWORD='a$b#c'。
5.3 启动
cd docker
docker compose up -d --build
docker compose ps
首次启动会:
- 启动 MySQL 并自动导入
backend/database/init.sql、init_data.sql; - 启动 Redis 并设置密码;
- PHP 容器安装依赖(使用内置
vendor卷)并等待 MySQL/Redis 健康; - Nginx 等待 PHP 的 Redis 读写健康检查通过后启动;
- scheduler 容器每小时执行一次到期检测和政务网同步。
5.4 访问
| 入口 | 地址 |
|---|---|
| PC 管理端 | http://服务器IP:8080/web/ |
| 手机 H5 | http://服务器IP:8080/mobile/ |
| 接口 | http://服务器IP:8080/api/ |
管理员账号:admin / admin123(首次登录后立即修改)。
Docker 的 Nginx 配置默认对
/install.php返回 404,这是有意为之。不要尝试在 Docker 环境运行网页安装器覆盖已有数据库。
5.5 常用运维命令
cd docker
# 查看状态
docker compose ps
# 查看日志
docker compose logs -f php
docker compose logs -f nginx
docker compose logs -f scheduler
# 重启
docker compose restart php nginx
# 停止(保留数据)
docker compose down
# 停止并删除数据卷(危险,会清空数据库和 Redis)
docker compose down -v
# 进入 PHP 容器执行命令
docker compose exec php php think redis:check
docker compose exec php php think cert:checkexpire --dry-run
5.6 Docker 方式升级
cd docker
# 先备份数据库(见第十章)
git pull
docker compose up -d --build
docker compose restart php nginx
opcache.validate_timestamps=0,不重启 PHP 容器不会生效。
5.7 Docker 注意事项
- MySQL 数据在
mysql_data卷,Redis 在redis_data卷,不要随意执行down -v。 - Redis 不映射宿主机端口,只能容器内访问,这是安全设计。
- 生产环境建议在 Docker 外再套一层 Nginx 做 HTTPS,
HTTP_BIND设为127.0.0.1。 GOV_PASSWORD_KEY一旦设置不要更改,否则已保存的政务网申报密码无法解密。
六、方式三:Linux 手工部署(Nginx + PHP-FPM)
适合不用宝塔、不用 Docker 的标准化运维环境。以下以 Ubuntu 22.04 + PHP 8.2 为例,CentOS 请用
dnf替换apt。
6.1 安装软件
sudo apt update
sudo apt install -y nginx mysql-server redis-server \
php8.2-fpm php8.2-cli php8.2-mysql php8.2-mbstring php8.2-xml \
php8.2-gd php8.2-curl php8.2-zip php8.2-redis php8.2-opcache
确认版本:
php -v # 应为 8.2.x
nginx -v
mysql --version
redis-server --version
6.2 创建运行用户与目录
sudo useradd -r -s /sbin/nologin certagent || true
sudo mkdir -p /var/www/cert-agent
sudo chown -R certagent:certagent /var/www/cert-agent
把代码放到 /var/www/cert-agent,确认 backend/public 存在。
6.3 配置 PHP-FPM
编辑 /etc/php/8.2/fpm/pool.d/www.conf:
user = certagent
group = certagent
pm = dynamic
pm.max_children = 40
pm.start_servers = 8
pm.min_spare_servers = 8
pm.max_spare_servers = 20
pm.max_requests = 800
request_terminate_timeout = 300s
4C8G 用 40;2C4G 取一半;8C16G 且 MySQL 同机取 60。
pm.max_children必须小于 MySQLmax_connections(建议后者为前者的 1.5 倍以上)。
修改 /etc/php/8.2/fpm/php.ini,填入第二章 2.3 的参数,然后:
sudo systemctl restart php8.2-fpm
6.4 配置 MySQL
CREATE DATABASE `cert_agent` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'cert_agent'@'127.0.0.1' IDENTIFIED BY '强密码';
GRANT ALL PRIVILEGES ON `cert_agent`.* TO 'cert_agent'@'127.0.0.1';
FLUSH PRIVILEGES;
/etc/mysql/mysql.conf.d/mysqld.cnf 建议:
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
default-time-zone = '+08:00'
max_connections = 200
innodb_buffer_pool_size = 2G
innodb_flush_log_at_trx_commit = 1
innodb_file_per_table = 1
wait_timeout = 600
重启 MySQL:
sudo systemctl restart mysql
6.5 配置 Redis
编辑 /etc/redis/redis.conf:
bind 127.0.0.1
requirepass 换成强密码
maxmemory 1gb
maxmemory-policy allkeys-lru
appendonly yes
sudo systemctl restart redis-server
redis-cli -a '强密码' ping # PONG
6.6 手工导入数据库
cd /var/www/cert-agent/backend
mysql -h 127.0.0.1 -u cert_agent -p cert_agent < database/init.sql
mysql -h 127.0.0.1 -u cert_agent -p cert_agent < database/init_data.sql
必须用
utf8mb4导入,否则消息模板里的 emoji 会失败。init_data.sql开头已包含SET NAMES utf8mb4;。
导入后默认管理员为 admin / admin123,请立即登录修改。
6.7 手工写 .env
cd /var/www/cert-agent/backend
cp .env.example .env
编辑 .env:
APP_DEBUG = false
APP_TRACE = false
[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = cert_agent
USERNAME = cert_agent
PASSWORD = "你的数据库密码"
HOSTPORT = 3306
CHARSET = utf8mb4
PREFIX = ""
[REDIS]
HOST = "127.0.0.1"
PORT = 6379
PASSWORD = "你的Redis密码"
DB = 0
PREFIX = "cert:"
值用双引号包住,密码里的
#、;、$会按原样读取。 手工部署不需要创建runtime/install.lock;如果你希望顺便封掉安装向导,可以手工创建该文件。
验证 Redis:
cd /var/www/cert-agent/backend
php think redis:check
6.8 配置 Nginx 站点
新建 /etc/nginx/sites-available/cert-agent.conf:
server {
listen 80;
server_name cert.example.com;
root /var/www/cert-agent/backend/public;
index index.php index.html;
client_max_body_size 24m;
server_tokens off;
gzip on;
gzip_vary on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml image/svg+xml;
# PC 端
location /web/ {
try_files $uri $uri/ /web/index.html;
}
location = /web/index.html {
add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0" always;
}
location /web/assets/ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
}
# 手机端
location /mobile/ {
try_files $uri $uri/ /mobile/index.html;
}
location = /mobile/index.html {
add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0" always;
}
location /mobile/assets/ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
}
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_read_timeout 300s;
}
# 生产建议限制安装器
location = /install.php {
allow 127.0.0.1;
allow 192.168.0.0/16;
deny all;
}
}
启用并重载:
sudo ln -s /etc/nginx/sites-available/cert-agent.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
6.9 权限
sudo chown -R certagent:certagent /var/www/cert-agent/backend/runtime /var/www/cert-agent/backend/public/uploads
sudo chmod -R 755 /var/www/cert-agent/backend/runtime /var/www/cert-agent/backend/public/uploads
6.10 HTTPS
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d cert.example.com
开启 HTTPS 后,记得把
backend/config/security.php的 CORS 白名单改成https://cert.example.com。
6.11 定时任务
sudo crontab -u certagent -e
加入:
0 8 * * * cd /var/www/cert-agent/backend && /usr/bin/php think cert:checkexpire --catch-up >> runtime/cron.log 2>&1
30 8 * * * cd /var/www/cert-agent/backend && /usr/bin/php think gov:sync >> runtime/cron.log 2>&1
6.12 访问
- PC:
http://cert.example.com/web/ - 手机:
http://cert.example.com/mobile/
七、网页安装向导逐项说明
7.1 它能做什么
安装向导会:
- 检查 PHP 版本、扩展、目录权限;
- 实测 Redis 读写、过期、删除(不是只连一下);
- 连接 MySQL 并创建数据库(若不存在);
- 导入建表 SQL 与初始化数据;
- 创建管理员账号(bcrypt 加密);
- 生成
backend/.env; - 生成安装锁
backend/runtime/install.lock。
7.2 字段校验规则
| 字段 | 规则 |
|---|---|
| 数据库主机 | 必填 |
| 端口 | 1–65535 |
| 数据库名 | 1–64 位字母、数字、下划线 |
| 数据库用户名 | 必填 |
| 管理员账号 | 必填,建议 admin |
| 管理员密码 | 8–32 位,必须同时包含字母和数字 |
| Redis 主机/端口 | 必填,端口 1–65535 |
| Redis 密码 | 可空;有密码必须正确 |
| Redis DB | ≥ 0 的整数 |
| Redis 键前缀 | 必填,最多 128 字节,不能为空 |
7.3 安装锁与重装
- 安装成功后生成
backend/runtime/install.lock。 - 再次访问
install.php会提示已安装并拒绝执行。 - 重装前:先备份数据库与附件,再删除
backend/runtime/install.lock,然后重新访问安装向导。 - 重装会覆盖数据库中的同名表,不要在没有备份的情况下操作。
7.4 安装失败怎么办
| 提示 | 原因 | 处理 |
|---|---|---|
| 数据库连接失败 | 账号/密码/端口错,或 MySQL 未启动 | 用 mysql -h ... -u ... -p 手动验证 |
| 数据库名不合法 | 含横线、中文、空格 | 只用字母数字下划线 |
| Redis 检测失败 | 服务未启动、密码错、DB 不存在、ACL 不允许 SETEX/DEL | redis-cli -a 密码 ping,再执行 php think redis:check |
| 缺少 Redis 客户端 | 既没有 phpredis,也没有 vendor/predis | 安装扩展或恢复 backend/vendor |
| 目录不可写 | 权限不对 | chown -R www:www backend/runtime |
| 导入 SQL 失败 | 字符集不对、MySQL 版本过低、SQL 文件缺失 | 用 utf8mb4 建库,确认文件完整 |
八、安装完成后的首次配置
按下面顺序配置,可以少走很多弯路。
8.1 修改管理员密码
登录后点右上角头像 →「个人中心」→「修改密码」。
如果沿用了
admin123,请立刻修改。密码要求与安装时一致:8–32 位,含字母和数字。
8.2 系统信息设置
「系统管理 → 系统信息设置」:
| 配置 | 建议 |
|---|---|
| 系统名称 | 你的公司名 + 证照管理系统 |
| 系统简称 | 侧边栏显示用,2–4 个字 |
| 系统 Logo | 上传公司 Logo,或留空显示文字 |
| 运营主体 | 公司全称 |
| 联系方式 | 客服电话/微信 |
| 版权信息、备案号 | 按实际填写 |
| 站点根地址 | https://cert.example.com |
| 移动端 H5 地址 | https://cert.example.com/mobile |
| 敏感数据脱敏 | 建议开启 |
| 可查看明文的角色 | 只勾选超级管理员 |
| 登录超时 | 默认 3 小时,可按需调整 |
| 信任设备有效期 | 默认 3 天 |
移动端 H5 地址会影响推送消息里的「查看详情」链接,务必填写外网可访问地址。
8.3 建部门、建账号、配角色
- 「组织架构 → 部门管理」建立部门树(如:总经办、证照部、项目部、财务部)。
- 「组织架构 → 角色管理」确认内置角色: - 超级管理员 - 证照管理员 - 项目配证专员 - 财务专员 - 企业查看者 - 只读观察员
- 「组织架构 → 账号权限管理」新建员工账号,选择部门、角色、数据范围。
- 客户企业账号:角色选「企业查看者」,并在「可管企业」中关联对应企业。
客户账号只能看自己企业的数据,且是只读。内部员工按岗位分配角色即可。
8.4 录入基础数据
建议顺序:
- 企业客户:新增或 Excel 导入客户企业。
- 人员档案:新增或导入持证人员,补全身份证、电话、社保状态。
- 证照台账:为人员新增证书,选择证书类型/专业、到期日、扫描件。
- 证书借调:把证书借给客户企业,填写期限、费用、合同。
- 项目配证:建项目、填证件需求,再用智能匹配选人。
证书只归属持证人,企业通过「借调」使用证书。这是本系统最核心的业务模型,录入时不要搞反。
8.5 配置提醒与推送
- 「系统管理 → 提醒规则设置」:确认全局默认提醒节点(1 年 / 6 月 / 3 月 / 2 月 / 1 月 / 15 天 / 7 天 / 3 天 / 1 天)和提醒方式。
- 「推送中心 → 推送渠道管理」:新增短信 / 邮件 / 企微机器人 / 企微应用 / 公众号渠道,点「测试推送」验证。
- 「推送中心 → 企业接收人」:配置全局接收人和各企业接收人。
- 「推送中心 → 消息模板管理」:按场景 × 渠道检查模板内容。
- 「推送中心 → 提醒中心」:点「推送体检」,确认没有阻断项。
没有配置任何渠道时,系统会「模拟发送」并写日志,不会真正发出消息。上线前务必用「测试推送」验证一次。
8.6 配置企微(可选)
「系统管理 → 企微登录配置」填写 CorpID、AgentID、Secret,保存后点「测试连接」。
「组织架构 → 企微通讯录」可同步成员并绑定/创建系统账号。
8.7 配置政务网进度(可选)
- 「系统管理 → 字典管理」确认「政务网业务类型」「政务网平台」字典。
- 「政务网进度 → 申报进度」新增申报记录,填写申报号和申报密码。
- 点「同步」验证能否取回环节。
- 配置
gov:sync定时任务。
申报密码使用 AES-256-GCM 加密存储,列表只显示掩码。更换
GOV_PASSWORD_KEY会导致旧密码无法解密。
8.8 自检一遍
- [ ] 首页 KPI 正常显示,没有红色报错
- [ ] 新增一个人员、一本证书、一条借调,能保存
- [ ] 上传一个附件,能预览/下载
- [ ] 导出一个 Excel,文件名中文正常
- [ ] 「系统信息 → 清除缓存」执行成功
- [ ] 推送渠道「测试推送」成功
- [ ] 手动执行一次到期检测,日志正常
- [ ] 手机打开
/mobile/能登录
九、定时任务配置
9.1 三个命令
| 命令 | 作用 | 建议频率 |
|---|---|---|
php think cert:checkexpire |
证书到期检测、借调到期处理、生成提醒并推送 | 每天 1 次;加 --catch-up 可每小时 |
php think gov:sync |
政务网申报进度同步 | 每天 1 次(内部 20 小时幂等) |
php think redis:check |
Redis 连通性自检 | 排障时手动执行 |
9.2 cert:checkexpire 参数
| 参数 | 作用 |
|---|---|
| 无参数 | 正常执行:扫描证书、生成提醒、推送、标记过期 |
--catch-up |
补发最近 3 天漏跑的提醒节点,按「证书 + 节点 + 日期」去重 |
--dry-run |
只体检不写库,用于确认会命中哪些提醒 |
示例:
cd /www/wwwroot/cert-agent/backend
# 每天正常跑
/www/server/php/82/bin/php think cert:checkexpire
# 每小时跑并补发(推荐,任务停摆也不漏)
/www/server/php/82/bin/php think cert:checkexpire --catch-up
# 只看会发什么,不写库
/www/server/php/82/bin/php think cert:checkexpire --dry-run
它会:
- 把已过到期日、状态仍为「正常」的证书自动标记为「已过期」,写入状态变更日志;
- 把已过结束日、状态仍为「借调中」的借调标记为「已到期」,并生成提醒;
- 按提醒节点生成站内提醒,并通过已启用渠道推送;
- 单条脏数据只跳过并记录,不会让整次任务失败;
- 退出码非 0 表示存在推送失败或任务异常。
9.3 gov:sync 参数
| 参数 | 作用 |
|---|---|
| 无参数 | 同步所有未办结、未归档的申报(20 小时内不重复) |
--force |
忽略 20 小时限制,强制同步 |
--all |
包含已归档记录 |
--id=123 |
只同步指定 ID |
/www/server/php/82/bin/php think gov:sync
/www/server/php/82/bin/php think gov:sync --force
/www/server/php/82/bin/php think gov:sync --id=123
9.4 验证定时任务是否真的执行
- 看日志:
tail -n 100 /www/wwwroot/cert-agent/backend/runtime/cron.log
- 看页面:「推送中心 → 提醒中心 → 到期检测执行结果」,有执行时间、扫描数、推送数。
- 看「政务网进度 → 申报进度 → 执行记录」,有每次同步的结果。
- 手动跑一次命令,确认退出码为 0:
cd /www/wwwroot/cert-agent/backend
/www/server/php/82/bin/php think cert:checkexpire --dry-run
echo $?
9.5 定时任务常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 日志为空,任务显示成功 | PHP 路径不对,命令没真正执行 | 用绝对路径,先手动执行 |
Could not open input file: think |
没有 cd 到 backend |
脚本里加 cd |
| 报 Redis 连接失败 | 定时任务环境读不到 .env 或 Redis 密码错 |
用同版本 PHP CLI 执行 php think redis:check |
| 报函数被禁用 | exec/proc_open 被禁用 |
宝塔 PHP 禁用函数里删除 |
| 推送没收到 | 渠道/接收人/提醒规则未配好 | 用「推送体检」逐项排查 |
| 任务重复推送 | 同时配了每小时和每天两条 | 只保留一条,或用 --catch-up 去重 |
十、备份与恢复
10.1 必须备份的内容
| 内容 | 路径/方式 | 频率 |
|---|---|---|
| 数据库 | mysqldump |
每天 |
| 附件 | backend/public/uploads/ |
每天 |
| 配置文件 | backend/.env |
每次修改后 |
| 政务网密钥 | .env 中的 GOV_PASSWORD_KEY |
修改前 |
| 代码 | Git 仓库或整包 | 每次升级前 |
backend/runtime/下还有日志、导出临时文件、vault/。runtime/vault/如果存有加密文件,也要纳入备份。
10.2 数据库备份脚本
把数据库账号密码放到 /root/.my.cnf:
[client]
user=cert_agent
password=你的数据库密码
chmod 600 /root/.my.cnf
每日备份:
mkdir -p /backup/db
mysqldump --defaults-extra-file=/root/.my.cnf \
--single-transaction --quick --routines --triggers \
cert_agent | gzip > /backup/db/cert_agent_$(date +%F).sql.gz
rsync -a --delete /www/wwwroot/cert-agent/backend/public/uploads/ /backup/upload/
find /backup/db -name '*.sql.gz' -mtime +14 -delete
加入 crontab:
30 2 * * * /bin/bash /root/backup-certagent.sh >> /var/log/backup-certagent.log 2>&1
10.3 恢复步骤
# 1. 停应用(避免写入)
systemctl stop php8.2-fpm nginx
# 2. 恢复数据库(建议先建空库)
mysql -u root -p -e "DROP DATABASE IF EXISTS cert_agent; CREATE DATABASE cert_agent DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
gunzip < /backup/db/cert_agent_2026-11-01.sql.gz | mysql -u root -p cert_agent
# 3. 恢复附件
rsync -a /backup/upload/ /www/wwwroot/cert-agent/backend/public/uploads/
# 4. 清缓存并重启
cd /www/wwwroot/cert-agent/backend
php think clear
systemctl start php8.2-fpm nginx
php think clear会清理缓存,可能导致所有用户重新登录。
10.4 恢复演练
每季度至少做一次:
- 在测试服务器导入最近一份备份;
- 确认表数量正常(新建 70 张,运行后自愈表会出现,共 72 张左右);
- 确认管理员能登录;
- 随机打开 3 本证书,确认附件能下载;
- 执行一次
cert:checkexpire --dry-run。
只有备份文件、没验证过恢复,等于没有备份。
十一、在线升级
11.1 前提条件
| 条件 | 说明 |
|---|---|
| Gitee 私人令牌 | 私有仓库必须配置,否则检测返回 404 |
[UPGRADE] 配置 |
在 backend/.env 中 |
| 代码可写 | PHP 进程对项目目录有写权限 |
zip 扩展 |
解压升级包 |
curl 扩展 |
下载升级包 |
exec/proc_open/shell_exec 至少一个 |
调用 mysqldump 备份 |
mysqldump、mysql |
数据库备份与恢复 |
配置示例(backend/.env):
[UPGRADE]
GITEE_OWNER = "kxunyun"
GITEE_REPO = "cert-expiry-manager"
GITEE_TOKEN = "你的Gitee私人令牌"
; 可选:手工指定 mysqldump / mysql 路径
; MYSQLDUMP = "/usr/bin/mysqldump"
; MYSQL = "/usr/bin/mysql"
Gitee 令牌在「Gitee → 设置 → 私人令牌」生成,勾选
projects读权限。令牌只保存在服务器.env,不要发给别人,也不要提交到 Git。
11.2 页面升级流程
- 「系统管理 → 在线升级」。
- 查看「当前版本」和「环境能力检测」(zip / curl / exec / 可写)。
- 点「检查新版本」。
- 有新版时页面显示版本号、来源、更新内容。
- 点「立即备份」(强烈建议)。
- 点「执行升级」,等待进度完成。
- 页面提示完成后,重启 PHP-FPM(或重启 php 容器)。
- 强制刷新浏览器(Ctrl/Cmd + Shift + R)。
11.3 上传升级包
没有外网或没有 Gitee 令牌时:
- 拿到官方升级包(
.zip)。 - 在升级页「上传升级包」区域拖入或选择文件。
- 点「上传并校验」。
- 校验通过后点「执行升级」。
11.4 升级失败回滚
- 进入「在线升级 → 备份管理」。
- 找到升级前的备份,点「恢复」。
- 恢复会还原代码与数据库;附件不在升级包内,一般不受影响。
- 恢复后重启 PHP-FPM。
升级前手工备份一次数据库,永远是成本最低的保险。
11.5 升级注意事项
- 升级前确认磁盘剩余空间 ≥ 升级包大小的 3 倍。
- 升级期间不要多人同时操作。
- 升级后必须重启 PHP-FPM,否则 OPcache 仍执行旧代码。
- 升级后如页面空白,先强制刷新;仍空白请看
backend/runtime/log/当日日志。 - 跨大版本升级前,先阅读升级页的「更新内容」。
十二、性能与安全加固
12.1 Nginx
worker_processes auto;
worker_rlimit_nofile 65535;
events {
use epoll;
worker_connections 4096;
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
client_max_body_size 24m;
server_tokens off;
gzip on;
gzip_vary on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml image/svg+xml;
fastcgi_connect_timeout 10s;
fastcgi_send_timeout 300s;
fastcgi_read_timeout 300s;
}
12.2 MySQL
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
default-time-zone = '+08:00'
max_connections = 200
innodb_buffer_pool_size = 2G
innodb_buffer_pool_instances = 2
innodb_flush_log_at_trx_commit = 1
innodb_file_per_table = 1
table_open_cache = 2000
tmp_table_size = 64M
max_heap_table_size = 64M
wait_timeout = 600
slow_query_log = 1
long_query_time = 1
innodb_buffer_pool_size建议为物理内存的 50%–60%。4G 机器设 1G,8G 机器设 2–3G。
12.3 Redis
maxmemory 1gb
maxmemory-policy allkeys-lru
appendonly yes
appendfsync everysec
save 900 1
timeout 0
tcp-keepalive 300
12.4 安全清单
- [ ] 全站 HTTPS,HTTP 自动跳转 HTTPS
- [ ]
backend/.env中APP_DEBUG=false、APP_TRACE=false - [ ]
display_errors=Off - [ ] CORS 白名单改成实际域名,不用
* - [ ] 默认管理员密码已修改,演示账号已删除
- [ ] 数据库使用独立账号,不用 root
- [ ] MySQL、Redis 不暴露公网,Redis 必须设密码
- [ ] 服务器防火墙只放行 80/443 和受控 SSH
- [ ]
backend/runtime/权限最小化,runtime/vault/纳入备份 - [ ] 安装器已限制内网访问
- [ ] 定期检查磁盘使用率(80% 告警)、MySQL 慢查询、Redis 内存、5xx 比例
- [ ] 每季度做一次备份恢复演练
十三、上线验收清单
安装完成后,逐项打勾:
基础访问
- [ ]
https://域名/web/能打开登录页 - [ ]
https://域名/mobile/能打开手机端 - [ ] 直接访问
https://域名/能自动分流 - [ ] 登录页验证码能显示、能刷新
- [ ] 管理员能登录,登录后能正常退出
核心业务
- [ ] 新增企业成功
- [ ] 新增人员成功,身份证/手机号正常
- [ ] 新增证书成功,证书类型/专业联动正常
- [ ] 新增借调成功,冲突提示正常
- [ ] 新增项目、填证件需求、智能匹配能出结果
- [ ] 上传证书扫描件成功,能预览/下载
- [ ] 新增费用、结算、批量打印正常
数据与导出
- [ ] 人员/企业/证书导入模板能下载
- [ ] Excel 导入预览、失败名单正常
- [ ] 证书/企业/人员/费用导出正常,中文文件名不乱码
- [ ] 回收站能恢复删除的数据
提醒与推送
- [ ] 推送渠道「测试推送」成功
- [ ] 企业接收人已配置
- [ ] 提醒规则已启用
- [ ] 「推送体检」无阻断项
- [ ] 手动执行到期检测,有执行记录
系统
- [ ] 定时任务已配置,日志有输出
- [ ] 政务网同步(如启用)能成功
- [ ] 「清除缓存」执行成功
- [ ] 操作日志有记录
- [ ] 登录日志有记录
- [ ] 在线升级「环境能力检测」全部通过(如启用)
十四、常见故障排查
14.1 页面打不开
| 现象 | 排查顺序 |
|---|---|
| 浏览器提示「无法访问」 | 域名是否解析、服务器是否开机、80/443 是否放行、Nginx 是否启动 |
| 502 Bad Gateway | PHP-FPM 是否启动、socket 路径是否与 Nginx 一致、PHP-FPM 是否 OOM |
| 504 Gateway Timeout | 导入/同步耗时过长;调大 fastcgi_read_timeout、max_execution_time |
| 403 Forbidden | 目录权限、index.php 是否存在、Nginx index 配置 |
| 404 Not Found | 网站根目录是否指到 backend/public、伪静态是否生效 |
| 页面空白 | 强制刷新;看浏览器控制台;看 runtime/log 日志 |
14.2 500 错误
- 临时把
backend/.env的APP_DEBUG改为true,刷新看具体错误。 - 查看
backend/runtime/log/当日日志。 - 最常见原因:
-
runtime不可写; -open_basedir限制; - PHP 版本低于 8.1; - 缺少扩展(fileinfo、gd、pdo_mysql); -.env格式错误(值没加引号、有换行)。 - 处理完把
APP_DEBUG改回false。
14.3 登录后刷新 404
伪静态没生效。检查 Nginx 配置是否有:
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
宝塔用户检查「站点设置 → 伪静态」是否保存并重载。
14.4 验证码不显示 / 提示验证码错误
- 确认
gd扩展已安装; - 确认
backend/resource/font/下字体文件存在且可读; - 确认
runtime可写; - 浏览器时间是否正确(影响验证码有效期判断);
- 反向代理/多台服务器时,确认会话粘滞或 Redis 正常。
14.5 提示 Redis 不可用(503)
系统不会降级文件缓存,必须修复 Redis:
cd /www/wwwroot/cert-agent/backend
php think redis:check
按提示检查:
- Redis 是否启动:
systemctl status redis; - 密码是否正确:
redis-cli -a '密码' ping; .env的[REDIS]是否写对;- 是否连错 DB 或前缀冲突;
- 云 Redis 是否允许当前服务器 IP。
修复后重启 PHP-FPM,不需要重装。
14.6 数据库连接失败
.env中HOSTNAME、DATABASE、USERNAME、PASSWORD、HOSTPORT是否正确;- MySQL 是否启动;
- 账号是否允许从该主机连接(
user@localhostvsuser@127.0.0.1); - MySQL 8.0 认证插件问题:可临时改为
mysql_native_password; - 密码含特殊字符时是否用双引号包住;
putenv是否被禁用。
14.7 上传附件失败
upload_max_filesize、post_max_size、Nginxclient_max_body_size是否 ≥ 20M;public/uploads是否可写;- 磁盘是否已满;
- 文件扩展名是否在白名单内;
- 如果启用了 WebDAV,检查地址、账号、目录权限,点「测试连接」。
14.8 Excel 导入失败
| 提示 | 处理 |
|---|---|
| 文件格式不支持 | 只支持 .xlsx / .xls,且 ≤ 10MB |
| 模板列不匹配 | 重新下载最新模板,不要删改表头 |
| 日期格式错误 | 按模板格式填 YYYY-MM-DD,不要填 -、0 |
| 身份证/手机号格式错误 | 检查位数与字符 |
| 必填项缺失 | 看预览页的逐行原因,或下载失败名单 |
| 导入很慢/超时 | 分批导入,调大 max_execution_time |
14.9 中文乱码
- 数据库、表、连接字符集都必须是
utf8mb4; - 导入 SQL 时使用
SET NAMES utf8mb4;; - Nginx/PHP 默认字符集
UTF-8; - Excel 导出文件名乱码:确认代码为最新版(已使用 RFC 5987 编码)。
14.10 定时任务不执行
- 脚本里是否
cd到backend; - PHP 是否用绝对路径;
- 执行用户是否有权限读
.env; - 手动执行命令是否成功;
- 看
runtime/cron.log; - 宝塔计划任务日志是否显示成功但无输出(多为 PHP 路径错)。
14.11 到期提醒不推送
按顺序排查:
- 「推送中心 → 提醒中心 → 推送体检」,看阻断原因;
- 是否启用了至少一个推送渠道;
- 渠道配置是否完整(短信网关、SMTP、Webhook、企微 Secret);
- 是否有启用中的接收人;
- 企业提醒规则是否勾选了提醒方式;
- 证书剩余天数是否已落到提醒节点;
- 定时任务是否执行;
- 「推送消息日志」里是否有记录、失败原因是什么。
14.12 政务网同步失败
- 服务器能否访问
https://www.hnzwfw.gov.cn; - 申报号和申报密码是否正确;
- 平台是否临时维护;
- 申报是否已办结/归档(归档后不再自动同步);
- 查看「申报进度 → 执行记录」的具体错误;
- 用「修复历史环节」从原始响应重新解析。
14.13 企业微信相关失败
- CorpID、AgentID、Secret 是否正确;
- 服务器 IP 是否在企业微信可信 IP 中;
- 回调 URL 是否可公网访问、Token 是否一致;
- 通讯录同步权限是否已开通;
- 报 TLS 错误时检查服务器 CA 证书与时间。
14.14 升级后页面空白 / 报错
- 强制刷新(Ctrl/Cmd + Shift + R);
- 重启 PHP-FPM(OPcache 不自动感知文件变化);
- 检查
public/web/assets是否完整; - 看
runtime/log; - 用备份管理回滚。
十五、附录
15.1 关键目录
| 路径 | 说明 | 是否可写 |
|---|---|---|
backend/public/ |
网站根目录 | 只读 |
backend/public/web/ |
PC 端构建产物 | 只读 |
backend/public/mobile/ |
手机端构建产物 | 只读 |
backend/public/uploads/ |
本机附件 | 可写 |
backend/runtime/ |
缓存、日志、临时文件 | 可写 |
backend/runtime/log/ |
应用日志 | 可写 |
backend/runtime/export/ |
导出临时文件 | 可写 |
backend/runtime/vault/ |
敏感运行文件 | 可写,权限最小化 |
backend/.env |
环境配置 | 只读(仅运维可改) |
backend/database/init.sql |
建表 SQL | 只读 |
backend/database/init_data.sql |
初始化数据 | 只读 |
15.2 默认端口
| 服务 | 端口 |
|---|---|
| HTTP | 80 |
| HTTPS | 443 |
| MySQL | 3306 |
| Redis | 6379 |
| Docker 默认 HTTP | 8080 |
15.3 常用命令速查
# 进入后端目录
cd /www/wwwroot/cert-agent/backend
# Redis 自检
php think redis:check
# 清理本系统前缀下的缓存(会让用户重新登录)
php think redis:check --flush
# 只清理菜单缓存
php think redis:check --flush --ns=menu
# 到期检测(只体检)
php think cert:checkexpire --dry-run
# 到期检测(正常执行)
php think cert:checkexpire
# 到期检测(补发 3 天内漏跑节点)
php think cert:checkexpire --catch-up
# 政务网同步
php think gov:sync
# 政务网强制同步
php think gov:sync --force
# 查看日志
tail -f runtime/log/$(date +%Y%m)/$(date +%d).log
# 重启 PHP-FPM(Ubuntu)
systemctl restart php8.2-fpm
# 重启 Nginx
systemctl reload nginx
15.4 默认账号
| 场景 | 账号 | 密码 |
|---|---|---|
| 网页安装向导创建 | 你填写 | 你填写 |
手工导入 init_data.sql |
admin |
admin123 |
无论哪种方式,首次登录后都必须修改密码。
15.5 内置角色
| 角色 | 适用岗位 |
|---|---|
| 超级管理员 | 系统负责人,全部权限 |
| 证照管理员 | 人员、证书、延续、借调、提醒、客户、项目配证、政务网、报名 |
| 项目配证专员 | 项目配证、智能匹配、冲突、属地政策、报名 |
| 财务专员 | 费用台账、收款账户、服务合同 |
| 企业查看者 | 客户企业账号,只看本企业,只读 |
| 只读观察员 | 内部只读查看 |
角色菜单和按钮权限可在「角色管理」中按需调整。
安装部署到此完成。 如果按本文操作仍无法启动,请准备好以下信息再联系技术支持:
- 服务器系统版本、PHP 版本、MySQL 版本、Redis 版本;
- 出错页面的截图;
backend/runtime/log/下当日日志的最后 100 行;- 是否使用宝塔/Docker、站点根目录、伪静态配置;
- 已经尝试过的处理步骤。