802 lines
22 KiB
Markdown
802 lines
22 KiB
Markdown
|
|
99# 云印享 - 付费打印服务系统架构设计
|
|||
|
|
|
|||
|
|
## 1. 项目概述
|
|||
|
|
|
|||
|
|
### 1.1 项目背景
|
|||
|
|
构建一个提供付费打印服务的微信小程序系统,用户可通过小程序上传文档/图片/压缩包,选择打印机并完成打印。系统包含用户端小程序、管理员端(Windows客户端)和后端服务。
|
|||
|
|
|
|||
|
|
### 1.2 核心功能需求
|
|||
|
|
|
|||
|
|
| 模块 | 功能点 |
|
|||
|
|
|------|--------|
|
|||
|
|
| 用户端小程序 | 上传文件(文档/图片/压缩包)、价目表展示、选择打印机、文件编辑(预览/水印/合并)、聊天记录选择文件、打印订单管理 |
|
|||
|
|
| 管理员端 | 文库管理(上传资料供用户打印)、订单处理、打印机管理、用户管理 |
|
|||
|
|
| 后端服务 | 用户认证、文件存储、订单处理、API网关 |
|
|||
|
|
| Windows客户端 | 调用Windows API连接打印机、执行打印任务、文件预处理 |
|
|||
|
|
|
|||
|
|
### 1.3 技术栈
|
|||
|
|
|
|||
|
|
- **小程序端**:Taro(跨平台框架)+ React技术栈
|
|||
|
|
- **后端**:Go + gRPC + MySQL + go-pay(微信支付)
|
|||
|
|
- **Windows客户端**:C# (.NET 8) + WPF
|
|||
|
|
- **管理后台**:React + Ant Design(网页端)
|
|||
|
|
- **文件存储**:本地存储 + MinIO(可选)
|
|||
|
|
- **通信**:gRPC + WebSocket
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 系统架构
|
|||
|
|
|
|||
|
|
### 2.1 整体架构图
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TB
|
|||
|
|
subgraph Client["客户端层"]
|
|||
|
|
MiniApp["Taro微信小程序<br/>用户端"]
|
|||
|
|
AdminWeb["React管理后台<br/>网页端"]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph Backend["后端服务层"]
|
|||
|
|
GRPC["gRPC Gateway<br/>:8080"]
|
|||
|
|
Auth["认证服务"]
|
|||
|
|
File["文件服务"]
|
|||
|
|
Order["订单服务"]
|
|||
|
|
Print["打印服务"]
|
|||
|
|
Pay["支付服务<br/>go-pay"]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph Data["数据层"]
|
|||
|
|
MySQL["MySQL<br/>数据库"]
|
|||
|
|
Redis["Redis<br/>缓存"]
|
|||
|
|
MinIO["MinIO<br/>文件存储"]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph PrintShop["打印店内部署"]
|
|||
|
|
WinClient["C# WPF客户端<br/>打印管理程序"]
|
|||
|
|
Printers["打印机列表"]
|
|||
|
|
LocalFiles["本地文库"]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
MiniApp -->|"HTTPS/gRPC"| GRPC
|
|||
|
|
AdminWeb -->|"HTTPS/gRPC"| GRPC
|
|||
|
|
WinClient -->|"gRPC| WebSocket"| GRPC
|
|||
|
|
|
|||
|
|
GRPC --> Auth
|
|||
|
|
GRPC --> File
|
|||
|
|
GRPC --> Order
|
|||
|
|
GRPC --> Print
|
|||
|
|
GRPC --> Pay
|
|||
|
|
|
|||
|
|
Auth --> Redis
|
|||
|
|
Order --> MySQL
|
|||
|
|
File --> MinIO
|
|||
|
|
File --> MySQL
|
|||
|
|
Pay --> WeChat["微信支付"]
|
|||
|
|
|
|||
|
|
WinClient --> Printers
|
|||
|
|
WinClient --> LocalFiles
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.2 部署架构
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart LR
|
|||
|
|
subgraph Internet["互联网"]
|
|||
|
|
User["用户<br/>微信小程序"]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph Cloud["云服务器"]
|
|||
|
|
API_Server["Go API Server"]
|
|||
|
|
DB["MySQL + Redis"]
|
|||
|
|
File_Storage["文件存储服务"]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph Local["打印店本地"]
|
|||
|
|
PC["Windows电脑<br/>C# WPF客户端"]
|
|||
|
|
Printer["打印机"]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
User -->|"上传文件/下单"| Cloud
|
|||
|
|
Cloud -->|"转发打印任务"| PC
|
|||
|
|
PC -->|"执行打印"| Printer
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 模块详细设计
|
|||
|
|
|
|||
|
|
### 3.1 微信小程序端
|
|||
|
|
|
|||
|
|
#### 3.1.1 页面结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
pages/
|
|||
|
|
├── index/ # 首页
|
|||
|
|
│ ├──价目表展示
|
|||
|
|
│ ├──快捷上传入口
|
|||
|
|
│ └──最近的打印历史
|
|||
|
|
├── upload/ # 文件上传
|
|||
|
|
│ ├──文件选择(支持聊天记录)
|
|||
|
|
│ ├──上传进度
|
|||
|
|
│ └──文件预览
|
|||
|
|
├── editor/ # 文件编辑
|
|||
|
|
│ ├──PDF预览
|
|||
|
|
│ ├──水印设置
|
|||
|
|
│ ├──页面合并
|
|||
|
|
│ └──打印参数设置
|
|||
|
|
├── printer/ # 打印机选择
|
|||
|
|
│ ├──打印机列表
|
|||
|
|
│ ├──打印机状态
|
|||
|
|
│ └──价格显示
|
|||
|
|
├── order/ # 订单管理
|
|||
|
|
│ ├──订单列表
|
|||
|
|
│ ├──订单详情
|
|||
|
|
│ └──支付
|
|||
|
|
├── library/ # 文库(用户浏览)
|
|||
|
|
│ ├──分类列表
|
|||
|
|
│ ├──文件搜索
|
|||
|
|
│ └──文件详情
|
|||
|
|
└── my/ # 个人中心
|
|||
|
|
├──打印记录
|
|||
|
|
├──账户余额
|
|||
|
|
└──设置
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.1.2 核心页面流程
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
Start["首页"] --> Upload{"选择上传方式"}
|
|||
|
|
Upload -->|"本地上传"| SelectFile["选择文件"]
|
|||
|
|
Upload -->|"聊天记录"| ChatFile["从聊天选择"]
|
|||
|
|
SelectFile --> Preview["文件预览"]
|
|||
|
|
ChatFile --> Preview
|
|||
|
|
Preview --> Edit{"需要编辑?"}
|
|||
|
|
Edit -->|"是"| Editor["编辑页面"]
|
|||
|
|
Edit -->|"否"| SelectPrinter["选择打印机"]
|
|||
|
|
Editor --> SelectPrinter
|
|||
|
|
SelectPrinter --> Confirm["确认订单"]
|
|||
|
|
Confirm --> Pay["支付"]
|
|||
|
|
Pay --> Success["下单成功"]
|
|||
|
|
Success --> Notify["通知打印店"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.1.3 文件编辑功能设计
|
|||
|
|
|
|||
|
|
| 功能 | 实现方式 | 说明 |
|
|||
|
|
|------|----------|------|
|
|||
|
|
| PDF预览 | pdf.js | 轻量级PDF预览,支持缩放、翻页 |
|
|||
|
|
| 添加水印 | 前端Canvas + 后端PDF处理 | 支持文字水印、位置、透明度 |
|
|||
|
|
| 页面合并 | pdf-lib | 合并多个PDF页面 |
|
|||
|
|
| 打印参数 | 份数、纸张大小、单双面、彩色/黑白 | 传递给Windows客户端 |
|
|||
|
|
|
|||
|
|
### 3.2 C# WPF打印客户端
|
|||
|
|
|
|||
|
|
#### 3.2.1 核心模块
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 项目结构
|
|||
|
|
CloudPrint.Client/
|
|||
|
|
├── App.xaml # 应用程序入口
|
|||
|
|
├── Services/
|
|||
|
|
│ ├── PrintService.cs # 打印服务(调用Windows API)
|
|||
|
|
│ ├── FileService.cs # 文件处理服务
|
|||
|
|
│ ├── GrpcService.cs # gRPC通信服务
|
|||
|
|
│ └── WebSocketService.cs # WebSocket备用通信
|
|||
|
|
├── ViewModels/
|
|||
|
|
│ ├── MainViewModel.cs # 主窗口
|
|||
|
|
│ ├── PrintQueueViewModel.cs # 打印队列
|
|||
|
|
│ ├── LibraryViewModel.cs # 文库管理
|
|||
|
|
│ └── SettingsViewModel.cs # 设置
|
|||
|
|
├── Views/
|
|||
|
|
│ ├── MainWindow.xaml
|
|||
|
|
│ ├── PrintQueueView.xaml
|
|||
|
|
│ ├── LibraryView.xaml
|
|||
|
|
│ └── SettingsView.xaml
|
|||
|
|
├── Models/
|
|||
|
|
│ ├── PrintJob.cs
|
|||
|
|
│ ├── Printer.cs
|
|||
|
|
│ └── Document.cs
|
|||
|
|
└── Helpers/
|
|||
|
|
├── WindowsPrintApi.cs # Windows打印API封装
|
|||
|
|
└── PdfProcessor.cs # PDF处理
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.2.2 Windows打印API集成
|
|||
|
|
|
|||
|
|
使用 P/Invoke 调用 Windows Print Spooler API:
|
|||
|
|
- `OpenPrinter`
|
|||
|
|
- `StartDocPrinter`
|
|||
|
|
- `StartPagePrinter`
|
|||
|
|
- `WritePrinter`
|
|||
|
|
- `EndPagePrinter`
|
|||
|
|
- `EndDocPrinter`
|
|||
|
|
- `ClosePrinter`
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 核心打印服务类
|
|||
|
|
public class PrintService
|
|||
|
|
{
|
|||
|
|
// 获取系统打印机列表
|
|||
|
|
public List<PrinterInfo> GetPrinters();
|
|||
|
|
|
|||
|
|
// 获取打印机状态
|
|||
|
|
public PrinterStatus GetPrinterStatus(string printerName);
|
|||
|
|
|
|||
|
|
// 提交打印任务
|
|||
|
|
public string SubmitPrintJob(PrintJob job);
|
|||
|
|
|
|||
|
|
// 取消打印任务
|
|||
|
|
public bool CancelPrintJob(string jobId);
|
|||
|
|
|
|||
|
|
// 获取打印任务状态
|
|||
|
|
public PrintJobStatus GetJobStatus(string jobId);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.2.3 gRPC通信
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 与后端gRPC服务通信
|
|||
|
|
public class GrpcService
|
|||
|
|
{
|
|||
|
|
// 连接gRPC服务器
|
|||
|
|
public async Task ConnectAsync(string address);
|
|||
|
|
|
|||
|
|
// 订阅打印任务流
|
|||
|
|
public async Task SubscribePrintJobsAsync(string printerName);
|
|||
|
|
|
|||
|
|
// 发送状态更新
|
|||
|
|
public async Task SendStatusUpdateAsync(PrintJobStatus status);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.3 后端服务(Go + gRPC + go-pay)
|
|||
|
|
|
|||
|
|
#### 3.3.1 项目结构
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
cloudprint-backend/
|
|||
|
|
├── cmd/
|
|||
|
|
│ └── server/
|
|||
|
|
│ └── main.go # 入口
|
|||
|
|
├── config/
|
|||
|
|
│ └── config.go # 配置
|
|||
|
|
├── internal/
|
|||
|
|
│ ├── grpc/ # gRPC服务
|
|||
|
|
│ │ ├── server.go # gRPC服务器入口
|
|||
|
|
│ │ ├── interceptor/ # 拦截器
|
|||
|
|
│ │ └── service/ # 服务实现
|
|||
|
|
│ │ ├── auth.go
|
|||
|
|
│ │ ├── file.go
|
|||
|
|
│ │ ├── order.go
|
|||
|
|
│ │ ├── print.go
|
|||
|
|
│ │ └── library.go
|
|||
|
|
│ ├── model/ # 数据模型
|
|||
|
|
│ ├── repository/ # 数据访问
|
|||
|
|
│ └── service/ # 业务逻辑
|
|||
|
|
├── pkg/
|
|||
|
|
│ ├── jwt/ # JWT认证
|
|||
|
|
│ ├── pay/ # 支付服务 (go-pay)
|
|||
|
|
│ └── upload/ # 文件上传
|
|||
|
|
├── proto/ # Protobuf定义
|
|||
|
|
│ ├── cloudprint.proto
|
|||
|
|
│ └── generated/ # 生成的代码
|
|||
|
|
├── scripts/
|
|||
|
|
│ └── db.sql # 数据库脚本
|
|||
|
|
└── go.mod
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.3.2 gRPC 服务设计
|
|||
|
|
|
|||
|
|
**认证服务 (AuthService)**
|
|||
|
|
|
|||
|
|
```protobuf
|
|||
|
|
service AuthService {
|
|||
|
|
rpc Login(LoginRequest) returns (LoginResponse);
|
|||
|
|
rpc RefreshToken(RefreshRequest) returns (RefreshResponse);
|
|||
|
|
rpc Logout(LogoutRequest) returns (Empty);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**文件服务 (FileService)**
|
|||
|
|
|
|||
|
|
```protobuf
|
|||
|
|
service FileService {
|
|||
|
|
rpc Upload(stream UploadRequest) returns (UploadResponse);
|
|||
|
|
rpc GetFile(GetFileRequest) returns (stream FileData);
|
|||
|
|
rpc DeleteFile(DeleteRequest) returns (Empty);
|
|||
|
|
rpc AddWatermark(WatermarkRequest) returns (WatermarkResponse);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**订单服务 (OrderService)**
|
|||
|
|
|
|||
|
|
```protobuf
|
|||
|
|
service OrderService {
|
|||
|
|
rpc CreateOrder(CreateOrderRequest) returns (OrderResponse);
|
|||
|
|
rpc GetOrderList(GetOrderListRequest) returns (OrderListResponse);
|
|||
|
|
rpc GetOrder(GetOrderRequest) returns (OrderResponse);
|
|||
|
|
rpc UpdateOrderStatus(UpdateStatusRequest) returns (Empty);
|
|||
|
|
rpc PayOrder(PayRequest) returns (PayResponse);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**打印服务 (PrintService)**
|
|||
|
|
|
|||
|
|
```protobuf
|
|||
|
|
service PrintService {
|
|||
|
|
rpc GetPrinters(Empty) returns (PrinterListResponse);
|
|||
|
|
rpc GetPrinterStatus(PrinterRequest) returns (PrinterStatusResponse);
|
|||
|
|
rpc SubmitPrintJob(PrintJobRequest) returns (PrintJobResponse);
|
|||
|
|
rpc CancelPrintJob(CancelRequest) returns (Empty);
|
|||
|
|
rpc SubscribeJobs(SubscriberRequest) returns (stream PrintJob);
|
|||
|
|
rpc ReportJobStatus(JobStatusReport) returns (Empty);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**文库服务 (LibraryService)**
|
|||
|
|
|
|||
|
|
```protobuf
|
|||
|
|
service LibraryService {
|
|||
|
|
rpc GetCategories(Empty) returns (CategoryListResponse);
|
|||
|
|
rpc GetFiles(GetFilesRequest) returns (FileListResponse);
|
|||
|
|
rpc UploadFile(stream UploadRequest) returns (UploadResponse);
|
|||
|
|
rpc DeleteFile(DeleteRequest) returns (Empty);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**支付服务 (PayService)**
|
|||
|
|
|
|||
|
|
```protobuf
|
|||
|
|
service PayService {
|
|||
|
|
rpc CreateWxPayOrder(WxPayRequest) returns (WxPayResponse);
|
|||
|
|
rpc QueryWxPayStatus(QueryRequest) returns (PayStatusResponse);
|
|||
|
|
rpc HandleWxPayCallback(CallbackRequest) returns (CallbackResponse);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.3.3 gRPC 通信流程
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant CSharp as C# WPF客户端
|
|||
|
|
participant Go as Go gRPC服务器
|
|||
|
|
participant DB as MySQL/Redis
|
|||
|
|
|
|||
|
|
CSharp->>Go: 连接gRPC服务 (认证)
|
|||
|
|
Go-->>CSharp: 连接成功
|
|||
|
|
CSharp->>Go: 注册打印机 (SubscribeJobs)
|
|||
|
|
Go->>DB: 查询待打印任务
|
|||
|
|
DB-->>Go: 任务列表
|
|||
|
|
|
|||
|
|
loop 等待新任务
|
|||
|
|
Go-->>CSharp: 推送新打印任务 (stream)
|
|||
|
|
CSharp->>CSharp: 处理文件/调用打印API
|
|||
|
|
CSharp->>Go: 上报状态 (ReportJobStatus)
|
|||
|
|
Go->>DB: 更新任务状态
|
|||
|
|
end
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.4 数据库设计
|
|||
|
|
|
|||
|
|
#### 3.4.1 ER 图
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
erDiagram
|
|||
|
|
User ||--o{ Order : places
|
|||
|
|
User {
|
|||
|
|
int id PK
|
|||
|
|
string openid UK
|
|||
|
|
string nickname
|
|||
|
|
decimal balance
|
|||
|
|
datetime created_at
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Order ||--|{ OrderItem : contains
|
|||
|
|
Order ||--o{ Payment : has
|
|||
|
|
Order {
|
|||
|
|
int id PK
|
|||
|
|
string order_no UK
|
|||
|
|
int user_id FK
|
|||
|
|
int status
|
|||
|
|
decimal total_amount
|
|||
|
|
datetime created_at
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
OrderItem {
|
|||
|
|
int id PK
|
|||
|
|
int order_id FK
|
|||
|
|
int file_id FK
|
|||
|
|
string printer_name
|
|||
|
|
int copies
|
|||
|
|
bool color
|
|||
|
|
bool duplex
|
|||
|
|
string page_range
|
|||
|
|
decimal price
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Payment {
|
|||
|
|
int id PK
|
|||
|
|
string order_no UK
|
|||
|
|
int pay_status
|
|||
|
|
string transaction_id
|
|||
|
|
datetime paid_at
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
File {
|
|||
|
|
int id PK
|
|||
|
|
string file_name
|
|||
|
|
string file_path
|
|||
|
|
string file_type
|
|||
|
|
int file_size
|
|||
|
|
string uploader_type
|
|||
|
|
int uploader_id
|
|||
|
|
datetime created_at
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Library |||--|{ LibraryFile : contains
|
|||
|
|
Library {
|
|||
|
|
int id PK
|
|||
|
|
string name
|
|||
|
|
string description
|
|||
|
|
int sort_order
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
LibraryFile ||--o{ File : references
|
|||
|
|
LibraryFile {
|
|||
|
|
int id PK
|
|||
|
|
int library_id FK
|
|||
|
|
int file_id FK
|
|||
|
|
string title
|
|||
|
|
string description
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Printer |||--o{ PrintJob : receives
|
|||
|
|
Printer {
|
|||
|
|
int id PK
|
|||
|
|
string name UK
|
|||
|
|
string display_name
|
|||
|
|
bool is_active
|
|||
|
|
string api_key UK
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PrintJob {
|
|||
|
|
int id PK
|
|||
|
|
string job_no UK
|
|||
|
|
int printer_id FK
|
|||
|
|
int order_item_id FK
|
|||
|
|
string status
|
|||
|
|
int progress
|
|||
|
|
datetime started_at
|
|||
|
|
datetime completed_at
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PriceList {
|
|||
|
|
int id PK
|
|||
|
|
string name
|
|||
|
|
string type
|
|||
|
|
decimal price
|
|||
|
|
string unit
|
|||
|
|
bool is_active
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.4.2 主要表结构
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 用户表
|
|||
|
|
CREATE TABLE `user` (
|
|||
|
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|||
|
|
`openid` VARCHAR(64) UNIQUE NOT NULL COMMENT '微信OpenID',
|
|||
|
|
`nickname` VARCHAR(128) DEFAULT '',
|
|||
|
|
`avatar` VARCHAR(512) DEFAULT '',
|
|||
|
|
`balance` DECIMAL(10,2) DEFAULT 0.00 COMMENT '余额',
|
|||
|
|
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|||
|
|
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 管理员表
|
|||
|
|
CREATE TABLE `admin` (
|
|||
|
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|||
|
|
`username` VARCHAR(64) UNIQUE NOT NULL,
|
|||
|
|
`password_hash` VARCHAR(256) NOT NULL,
|
|||
|
|
`nickname` VARCHAR(128) DEFAULT '',
|
|||
|
|
`role` TINYINT DEFAULT 1 COMMENT '1:普通管理员 2:超级管理员',
|
|||
|
|
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 打印机表
|
|||
|
|
CREATE TABLE `printer` (
|
|||
|
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|||
|
|
`name` VARCHAR(128) UNIQUE NOT NULL COMMENT '系统打印机名',
|
|||
|
|
`display_name` VARCHAR(128) NOT NULL COMMENT '显示名称',
|
|||
|
|
`api_key` VARCHAR(64) UNIQUE NOT NULL COMMENT '客户端认证Key',
|
|||
|
|
`is_active` TINYINT DEFAULT 1,
|
|||
|
|
`status` TINYINT DEFAULT 0 COMMENT '0:空闲 1:打印中 2:离线',
|
|||
|
|
`last_heartbeat` DATETIME,
|
|||
|
|
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 订单表
|
|||
|
|
CREATE TABLE `order` (
|
|||
|
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|||
|
|
`order_no` VARCHAR(32) UNIQUE NOT NULL COMMENT '订单号',
|
|||
|
|
`user_id` INT NOT NULL,
|
|||
|
|
`status` TINYINT DEFAULT 0 COMMENT '0:待支付 1:已支付 2:打印中 3:已完成 4:已取消',
|
|||
|
|
`total_amount` DECIMAL(10,2) NOT NULL,
|
|||
|
|
`remark` VARCHAR(512) DEFAULT '',
|
|||
|
|
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|||
|
|
`paid_at` DATETIME,
|
|||
|
|
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 订单明细表
|
|||
|
|
CREATE TABLE `order_item` (
|
|||
|
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|||
|
|
`order_id` INT NOT NULL,
|
|||
|
|
`file_id` INT NOT NULL,
|
|||
|
|
`printer_id` INT,
|
|||
|
|
`copies` INT DEFAULT 1,
|
|||
|
|
`color` TINYINT DEFAULT 0,
|
|||
|
|
`duplex` TINYINT DEFAULT 0,
|
|||
|
|
`page_range` VARCHAR(64) DEFAULT 'all',
|
|||
|
|
`price` DECIMAL(10,2) NOT NULL,
|
|||
|
|
FOREIGN KEY (`order_id`) REFERENCES `order`(`id`),
|
|||
|
|
FOREIGN KEY (`file_id`) REFERENCES `file`(`id`)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 文件表
|
|||
|
|
CREATE TABLE `file` (
|
|||
|
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|||
|
|
`file_name` VARCHAR(256) NOT NULL,
|
|||
|
|
`file_path` VARCHAR(512) NOT NULL,
|
|||
|
|
`file_type` VARCHAR(32) NOT NULL COMMENT 'pdf/doc/docx/xls/xlsx/ppt/pptx/txt/jpg/png/zip',
|
|||
|
|
`file_size` BIGINT NOT NULL COMMENT '字节',
|
|||
|
|
`uploader_type` VARCHAR(16) NOT NULL COMMENT 'user/admin/system',
|
|||
|
|
`uploader_id` INT NOT NULL,
|
|||
|
|
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 文库分类表
|
|||
|
|
CREATE TABLE `library_category` (
|
|||
|
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|||
|
|
`name` VARCHAR(128) NOT NULL,
|
|||
|
|
`icon` VARCHAR(128) DEFAULT '',
|
|||
|
|
`sort_order` INT DEFAULT 0,
|
|||
|
|
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 文库文件表
|
|||
|
|
CREATE TABLE `library_file` (
|
|||
|
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|||
|
|
`category_id` INT NOT NULL,
|
|||
|
|
`file_id` INT NOT NULL,
|
|||
|
|
`title` VARCHAR(256) NOT NULL,
|
|||
|
|
`description` VARCHAR(512) DEFAULT '',
|
|||
|
|
`page_count` INT DEFAULT 0,
|
|||
|
|
`download_count` INT DEFAULT 0,
|
|||
|
|
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|||
|
|
FOREIGN KEY (`category_id`) REFERENCES `library_category`(`id`),
|
|||
|
|
FOREIGN KEY (`file_id`) REFERENCES `file`(`id`)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 打印任务表
|
|||
|
|
CREATE TABLE `print_job` (
|
|||
|
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|||
|
|
`job_no` VARCHAR(32) UNIQUE NOT NULL,
|
|||
|
|
`printer_id` INT NOT NULL,
|
|||
|
|
`order_item_id` INT NOT NULL,
|
|||
|
|
`status` VARCHAR(16) DEFAULT 'pending' COMMENT 'pending/printing/completed/failed/cancelled',
|
|||
|
|
`progress` INT DEFAULT 0,
|
|||
|
|
`error_msg` VARCHAR(512) DEFAULT '',
|
|||
|
|
`started_at` DATETIME,
|
|||
|
|
`completed_at` DATETIME,
|
|||
|
|
FOREIGN KEY (`printer_id`) REFERENCES `printer`(`id`)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 价目表
|
|||
|
|
CREATE TABLE `price_list` (
|
|||
|
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|||
|
|
`name` VARCHAR(128) NOT NULL COMMENT '项目名称',
|
|||
|
|
`type` VARCHAR(32) NOT NULL COMMENT '纸张类型: A4/A3/照片纸',
|
|||
|
|
`price` DECIMAL(10,2) NOT NULL COMMENT '单价',
|
|||
|
|
`unit` VARCHAR(16) NOT NULL COMMENT '单位: 页/张/份',
|
|||
|
|
`color_enabled` TINYINT DEFAULT 1 COMMENT '是否支持彩色',
|
|||
|
|
`is_active` TINYINT DEFAULT 1,
|
|||
|
|
`sort_order` INT DEFAULT 0,
|
|||
|
|
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 支付记录表
|
|||
|
|
CREATE TABLE `payment` (
|
|||
|
|
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|||
|
|
`order_no` VARCHAR(32) UNIQUE NOT NULL,
|
|||
|
|
`pay_type` VARCHAR(16) DEFAULT 'wechat' COMMENT 'wechat/balance',
|
|||
|
|
`pay_status` TINYINT DEFAULT 0 COMMENT '0:待支付 1:支付中 2:成功 3:失败',
|
|||
|
|
`transaction_id` VARCHAR(64) DEFAULT '',
|
|||
|
|
`paid_at` DATETIME,
|
|||
|
|
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 核心流程
|
|||
|
|
|
|||
|
|
### 4.1 用户打印流程
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant User as 用户
|
|||
|
|
participant MiniApp as 微信小程序
|
|||
|
|
participant Backend as Go后端
|
|||
|
|
participant Windows as Windows客户端
|
|||
|
|
participant Printer as 打印机
|
|||
|
|
|
|||
|
|
User->>MiniApp: 选择文件上传
|
|||
|
|
MiniApp->>MiniApp: 文件预览/编辑
|
|||
|
|
User->>MiniApp: 确认打印参数
|
|||
|
|
MiniApp->>Backend: 创建订单
|
|||
|
|
Backend-->>MiniApp: 订单信息
|
|||
|
|
User->>MiniApp: 支付订单
|
|||
|
|
MiniApp->>Backend: 支付回调
|
|||
|
|
Backend->>Windows: WebSocket推送打印任务
|
|||
|
|
Windows->>Backend: 下载文件
|
|||
|
|
Windows->>Windows: PDF预处理
|
|||
|
|
Windows->>Printer: 发送打印指令
|
|||
|
|
Printer-->>Windows: 打印中
|
|||
|
|
Windows->>Backend: 更新任务状态
|
|||
|
|
Backend->>MiniApp: 推送状态更新
|
|||
|
|
Printer-->>User: 输出打印件
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.2 管理员上传文库流程
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
Admin["管理员登录Windows客户端"] --> Navigate["进入文库管理"]
|
|||
|
|
Navigate --> SelectCategory["选择分类"]
|
|||
|
|
SelectCategory --> Upload["上传文件"]
|
|||
|
|
Upload --> SetInfo["设置文件标题描述"]
|
|||
|
|
SetInfo --> Confirm["确认上传"]
|
|||
|
|
Confirm --> Save["保存到数据库"]
|
|||
|
|
Save --> Sync["同步到云端"]
|
|||
|
|
Sync --> Success["上传成功"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 文件处理
|
|||
|
|
|
|||
|
|
### 5.1 支持的文件格式
|
|||
|
|
|
|||
|
|
| 类型 | 格式 | 处理方式 |
|
|||
|
|
|------|------|----------|
|
|||
|
|
| 文档 | doc, docx, txt | 转为PDF后打印 |
|
|||
|
|
| 表格 | xls, xlsx | 转为PDF后打印 |
|
|||
|
|
| 演示 | ppt, pptx | 转为PDF后打印 |
|
|||
|
|
| 图片 | jpg, png, bmp, gif | 直接打印或转PDF |
|
|||
|
|
| 压缩包 | zip, rar | 解压后处理内部文件 |
|
|||
|
|
| PDF | pdf | 直接打印 |
|
|||
|
|
|
|||
|
|
### 5.2 C#端文件转换
|
|||
|
|
|
|||
|
|
使用以下库/工具进行文件转换:
|
|||
|
|
- **Word/Excel/PowerPoint**: Microsoft Office COM Automation 或 LibreOffice Headless
|
|||
|
|
- **图片**: System.Drawing
|
|||
|
|
- **压缩包**: SharpCompress
|
|||
|
|
- **PDF合并/水印**: PDFsharp 或 iTextSharp
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 安全设计
|
|||
|
|
|
|||
|
|
### 6.1 认证授权
|
|||
|
|
|
|||
|
|
- **用户端**: 微信 OAuth2.0 获取 OpenID
|
|||
|
|
- **管理后台**: 用户名密码 + JWT Token
|
|||
|
|
- **打印客户端**: API Key 认证 + gRPC TLS加密连接
|
|||
|
|
|
|||
|
|
### 6.2 数据安全
|
|||
|
|
|
|||
|
|
- 文件上传: 大小限制 (单文件 50MB)
|
|||
|
|
- 文件类型白名单验证
|
|||
|
|
- SQL注入防护: 使用参数化查询
|
|||
|
|
- XSS防护: 输出编码
|
|||
|
|
- gRPC传输加密: TLS 1.3
|
|||
|
|
|
|||
|
|
### 6.3 打印客户端认证
|
|||
|
|
|
|||
|
|
gRPC认证流程:
|
|||
|
|
1. 客户端使用API Key获取临时凭证
|
|||
|
|
2. 使用凭证建立gRPC TLS连接
|
|||
|
|
3. 服务端验证客户端身份
|
|||
|
|
4. 建立长连接后订阅打印任务流
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. 开发计划
|
|||
|
|
|
|||
|
|
### 7.1 项目模块划分
|
|||
|
|
|
|||
|
|
1. **cloudprint-miniapp** - Taro微信小程序用户端
|
|||
|
|
2. **cloudprint-backend** - Go + gRPC 后端服务
|
|||
|
|
3. **cloudprint-client** - C# (.NET 8) + WPF 打印客户端
|
|||
|
|
4. **cloudprint-admin** - React 管理后台网页端
|
|||
|
|
5. **cloudprint-proto** - Protobuf 定义共享库
|
|||
|
|
|
|||
|
|
### 7.2 开发顺序
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. cloudprint-proto (公共协议定义)
|
|||
|
|
├── 定义所有 gRPC 服务和消息类型
|
|||
|
|
├── 生成 Go、C#、TypeScript 代码
|
|||
|
|
|
|||
|
|
2. cloudprint-backend (Go + gRPC + go-pay)
|
|||
|
|
├── 数据库设计与初始化
|
|||
|
|
├── 基础框架搭建
|
|||
|
|
├── 认证模块 (JWT)
|
|||
|
|
├── 文件服务
|
|||
|
|
├── 订单服务
|
|||
|
|
├── 打印服务
|
|||
|
|
├── 文库服务
|
|||
|
|
└── 微信支付集成 (go-pay)
|
|||
|
|
|
|||
|
|
3. cloudprint-client (C# WPF)
|
|||
|
|
├── 项目初始化 (.NET 8)
|
|||
|
|
├── 打印服务开发 (P/Invoke Windows API)
|
|||
|
|
├── gRPC 通信 (Grpc.Net)
|
|||
|
|
├── WebSocket 通信 (用于推送)
|
|||
|
|
├── 文件处理
|
|||
|
|
└── 文库管理
|
|||
|
|
|
|||
|
|
4. cloudprint-admin (React + Ant Design)
|
|||
|
|
├── 项目初始化
|
|||
|
|
├── 登录认证
|
|||
|
|
├── 订单管理
|
|||
|
|
├── 用户管理
|
|||
|
|
├── 价目表管理
|
|||
|
|
└── 数据统计
|
|||
|
|
|
|||
|
|
5. cloudprint-miniapp (Taro)
|
|||
|
|
├── 项目初始化 (@tarojs/cli)
|
|||
|
|
├── 用户端页面开发
|
|||
|
|
├── 文件上传与编辑
|
|||
|
|
├── 订单流程
|
|||
|
|
└── 与后端 gRPC 对接
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. 部署方案
|
|||
|
|
|
|||
|
|
### 8.1 云服务器要求
|
|||
|
|
|
|||
|
|
- **配置**: 2核4G起步
|
|||
|
|
- **系统**: Ubuntu 22.04 / CentOS 8
|
|||
|
|
- **数据库**: MySQL 8.0
|
|||
|
|
- **缓存**: Redis 6.0
|
|||
|
|
- **文件存储**: 本地磁盘或 MinIO
|
|||
|
|
|
|||
|
|
### 8.2 打印店客户端部署
|
|||
|
|
|
|||
|
|
1. 在打印店电脑安装 Windows 10/11 + .NET 8 Runtime
|
|||
|
|
2. 运行 C# WPF 客户端程序,配置服务器地址
|
|||
|
|
3. 登录管理员账号
|
|||
|
|
4. 配置打印机
|
|||
|
|
5. 保持客户端在线
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. 风险与注意事项
|
|||
|
|
|
|||
|
|
| 风险 | 应对措施 |
|
|||
|
|
|------|----------|
|
|||
|
|
| 文件格式兼容 | C#客户端集成LibreOffice转换 |
|
|||
|
|
| 打印质量差异 | 客户端提供打印参数调试 |
|
|||
|
|
| 大文件传输 | 分片上传、断点续传 |
|
|||
|
|
| 客户端掉线 | gRPC心跳检测、自动重连 |
|
|||
|
|
| 支付安全 | 微信支付官方SDK (go-pay) |
|
|||
|
|
| 并发打印 | 任务队列、打印机组 |
|