# 晓镜书阁 · 书店进销存系统 — 部署说明

版本：1.0.0　打包时间：2026-10-27

## 一、包内结构

```
psi-erp-1.0.0/
├─ backend/
│  ├─ psi-backend.jar          后端服务（Spring Boot 3.2 + Java 21）
│  ├─ 启动后端.bat             Windows 一键启动（读取同目录 env.bat）
│  ├─ env.bat                  数据库与 JWT 配置模板
│  └─ start-backend.sh         Linux / macOS 启动脚本
├─ web/
│  ├─ dist/                    前端静态文件（Vue 3 + Vite 构建产物）
│  └─ nginx.conf               手工部署用 Nginx 配置（反代 127.0.0.1:8080）
├─ db/
│  ├─ schema.sql               建库建表（含最新字段：确认锁定 / 修订 / 归档）
│  ├─ data.sql                 初始数据（角色、权限、账号、基础资料）
│  ├─ upgrade-employee_no.sql  存量库增量脚本：员工编号
│  ├─ upgrade-order-lock-revision.sql  存量库增量脚本：确认锁定与修订审批
│  └─ upgrade-order-archive.sql        存量库增量脚本：单据归档
├─ docker/
│  ├─ docker-compose.yml       MySQL + 后端 + Web 全栈
│  ├─ Dockerfile.backend
│  ├─ Dockerfile.web
│  ├─ nginx.conf               容器内 Nginx 配置（反代 backend:8080）
│  └─ .env.example             端口与密码配置模板
└─ docs/README.md              项目说明
```

默认账号：`admin / 123456`　数据库名：`bookstore`

---

## 二、方案 A：Docker Compose（推荐，一条命令）

要求：Docker Engine 24+ 与 Compose v2（`docker compose version` 可用）。

```bash
cd docker
cp .env.example .env          # Windows: copy .env.example .env
# 按需修改 .env 中的密码与端口
docker compose up -d --build
```

启动后：

| 服务 | 地址 |
|---|---|
| Web 管理端 | http://localhost:8088 |
| 后端 API | http://localhost:8080/api |
| MySQL | localhost:13306（root / .env 中的密码） |

首次启动时 MySQL 会自动执行 `db/schema.sql` 与 `db/data.sql`（仅数据卷为空时执行一次）。

常用命令：

```bash
docker compose ps                  # 查看状态
docker compose logs -f backend     # 后端日志
docker compose down                # 停止（保留数据）
docker compose down -v             # 停止并清空数据库
```

> 旧库升级：不执行 `down -v`，进入容器手工执行 `db/upgrade-*.sql`：
> `docker compose exec -T mysql mysql -uroot -p bookstore < ../db/upgrade-order-archive.sql`

---

## 三、方案 B：手工部署（Windows / Linux 服务器）

### 1. 准备数据库

MySQL 8.0+，字符集 `utf8mb4`。

```bash
mysql -uroot -p -e "CREATE DATABASE IF NOT EXISTS bookstore DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -uroot -p bookstore < db/schema.sql
mysql -uroot -p bookstore < db/data.sql
```

已有旧库不要重跑 `schema.sql`（含 DROP TABLE），只按顺序执行 `db/upgrade-*.sql` 中缺失的脚本。

### 2. 启动后端

需要 Java 21（`java -version` 显示 21）。

Windows：编辑 `backend\env.bat` 后双击 `backend\启动后端.bat`。

Linux：

```bash
cd backend
export SPRING_DATASOURCE_URL="jdbc:mysql://127.0.0.1:3306/bookstore?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false"
export SPRING_DATASOURCE_USERNAME=root
export SPRING_DATASOURCE_PASSWORD=你的密码
export JWT_SECRET=至少32字节的随机字符串
chmod +x start-backend.sh && ./start-backend.sh
```

验证：`curl http://127.0.0.1:8080/api/auth/login -H "Content-Type: application/json" -d "{\"username\":\"admin\",\"password\":\"123456\"}"` 返回 `code:0`。

生产建议用 systemd 托管，示例：

```ini
[Unit]
Description=psi-backend
After=network.target mysql.service

[Service]
WorkingDirectory=/opt/psi-erp/backend
EnvironmentFile=/opt/psi-erp/backend/env.conf
ExecStart=/usr/bin/java -Xms256m -Xmx512m -jar /opt/psi-erp/backend/psi-backend.jar
Restart=always

[Install]
WantedBy=multi-user.target
```

### 3. 部署前端

1) 安装 Nginx，把 `web/dist/` 下所有文件复制到 Nginx 的 `html` 目录（如 `/usr/share/nginx/html` 或 `C:\nginx\html`）。
2) 把 `web/nginx.conf` 放到 `conf.d/`（或并入主配置的 `server{}`），重载：`nginx -s reload`。

`web/nginx.conf` 默认反代 `127.0.0.1:8080`，已包含 SPA 路由回退（`try_files ... /index.html`）与静态资源缓存，不要把 `location /` 的 `try_files` 去掉，否则刷新子页面会 404。

访问 `http://服务器IP/` 即可，默认账号 `admin / 123456`。

---

## 四、配置项

后端读取环境变量，未设置时使用圆括号内默认值：

| 变量 | 说明 | 默认 |
|---|---|---|
| `SPRING_DATASOURCE_URL` | JDBC 连接串 | `jdbc:mysql://localhost:3306/bookstore?...` |
| `SPRING_DATASOURCE_USERNAME` | 数据库用户 | `root` |
| `SPRING_DATASOURCE_PASSWORD` | 数据库密码 | `123456` |
| `JWT_SECRET` | 签名密钥，HS256 要求 ≥32 字节 | 内置示例值（生产必须改） |
| `JWT_EXPIRE_HOURS` | Token 有效期（小时） | `24` |

Docker 方案在 `docker/.env` 中配置：`MYSQL_ROOT_PASSWORD`、`BACKEND_PORT`、`WEB_PORT`、`JWT_SECRET`。

---

## 五、上线检查清单

- [ ] 修改 `admin` 初始密码，删除或禁用演示账号
- [ ] 更换 `JWT_SECRET` 为随机值
- [ ] 数据库账号改为最小权限的专用用户，不要直接用 root
- [ ] 前端走 HTTPS（Nginx 增加 443 与证书），并把 HTTP 跳转 HTTPS
- [ ] 设置 `server.port` 后仅监听内网，安全组只放行 80/443
- [ ] 配置数据库定时备份（`mysqldump` + 保留策略）
- [ ] 归档策略：单据管理 → 单据归档，按保留天数批量归档终态单据

---

## 六、常见问题

| 现象 | 处理 |
|---|---|
| 后端启动报 `Communications link failure` | 数据库未启动 / 连接串、账号密码错误 / 3306 未放行 |
| 登录返回 401 或 `code` 非 0 | 初始数据未导入（`data.sql`），或账号密码错误 |
| 页面能开但接口 404 | Nginx 未反代 `/api`，检查 `web/nginx.conf` 的 `proxy_pass` |
| 刷新子路由 404 | 缺少 SPA 回退，确认 `try_files $uri $uri/ /index.html` |
| Docker 首次启动后端连接失败 | 等 MySQL 健康检查通过，compose 已配置 `depends_on: service_healthy` |
| 时间显示相差 8 小时 | 容器/服务器设置 `TZ=Asia/Shanghai` |
