2025-09-11 19:55:21 +08:00
|
|
|
|
# 活牛采购智能数字化系统 - 系统详细设计文档
|
|
|
|
|
|
|
|
|
|
|
|
## 版本历史
|
|
|
|
|
|
| 版本 | 日期 | 作者 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| v1.0 | 2024-05-15 | 系统架构师 | 基于现有项目架构整理更新 |
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 数据库详细设计
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1 核心数据表ER图
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
erDiagram
|
|
|
|
|
|
USER ||--o{ ORDER : creates
|
|
|
|
|
|
USER ||--o{ ORDER : manages
|
|
|
|
|
|
USER ||--o{ ORDER : supplies
|
|
|
|
|
|
USER ||--o{ TRANSPORT_TRACK : reports
|
|
|
|
|
|
ORDER ||--o{ TRANSPORT_TRACK : has
|
|
|
|
|
|
ORDER ||--o{ QUALITY_RECORD : has
|
|
|
|
|
|
ORDER ||--o{ SETTLEMENT : has
|
|
|
|
|
|
SUPPLIER ||--o{ ORDER : provides
|
|
|
|
|
|
|
|
|
|
|
|
USER {
|
|
|
|
|
|
BIGINT id PK
|
|
|
|
|
|
STRING uuid
|
|
|
|
|
|
STRING username
|
|
|
|
|
|
STRING password_hash
|
|
|
|
|
|
STRING phone
|
|
|
|
|
|
STRING email
|
|
|
|
|
|
STRING real_name
|
|
|
|
|
|
STRING avatar_url
|
|
|
|
|
|
ENUM user_type
|
|
|
|
|
|
ENUM status
|
|
|
|
|
|
DATE last_login_at
|
|
|
|
|
|
INT login_count
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ORDER {
|
|
|
|
|
|
BIGINT id PK
|
|
|
|
|
|
STRING orderNo
|
|
|
|
|
|
BIGINT buyerId FK
|
|
|
|
|
|
BIGINT supplierId FK
|
|
|
|
|
|
BIGINT traderId FK
|
|
|
|
|
|
STRING cattleBreed
|
|
|
|
|
|
INT cattleCount
|
|
|
|
|
|
DECIMAL expectedWeight
|
|
|
|
|
|
DECIMAL actualWeight
|
|
|
|
|
|
DECIMAL unitPrice
|
|
|
|
|
|
DECIMAL totalAmount
|
|
|
|
|
|
DECIMAL paidAmount
|
|
|
|
|
|
DECIMAL remainingAmount
|
|
|
|
|
|
ENUM status
|
|
|
|
|
|
STRING deliveryAddress
|
|
|
|
|
|
DATE expectedDeliveryDate
|
|
|
|
|
|
DATE actualDeliveryDate
|
|
|
|
|
|
STRING notes
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SUPPLIER {
|
|
|
|
|
|
BIGINT id PK
|
|
|
|
|
|
STRING name
|
|
|
|
|
|
STRING code
|
|
|
|
|
|
STRING contact
|
|
|
|
|
|
STRING phone
|
|
|
|
|
|
STRING address
|
|
|
|
|
|
STRING businessLicense
|
|
|
|
|
|
STRING qualificationLevel
|
|
|
|
|
|
JSON certifications
|
|
|
|
|
|
JSON cattleTypes
|
|
|
|
|
|
INT capacity
|
|
|
|
|
|
DECIMAL rating
|
|
|
|
|
|
DATE cooperationStartDate
|
|
|
|
|
|
ENUM status
|
|
|
|
|
|
STRING region
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TRANSPORT_TRACK {
|
|
|
|
|
|
BIGINT id PK
|
|
|
|
|
|
BIGINT orderId FK
|
|
|
|
|
|
BIGINT driverId FK
|
|
|
|
|
|
DECIMAL latitude
|
|
|
|
|
|
DECIMAL longitude
|
|
|
|
|
|
DECIMAL speed
|
|
|
|
|
|
DECIMAL direction
|
|
|
|
|
|
STRING cattle_status
|
|
|
|
|
|
STRING video_url
|
|
|
|
|
|
DATE timestamp
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QUALITY_RECORD {
|
|
|
|
|
|
BIGINT id PK
|
|
|
|
|
|
BIGINT orderId FK
|
|
|
|
|
|
STRING inspectionCode
|
|
|
|
|
|
STRING inspectorName
|
|
|
|
|
|
DATE inspectionDate
|
|
|
|
|
|
STRING inspectionLocation
|
|
|
|
|
|
INT cattleCount
|
|
|
|
|
|
INT samplingCount
|
|
|
|
|
|
STRING inspectionType
|
|
|
|
|
|
STRING healthStatus
|
|
|
|
|
|
STRING quarantineCertificate
|
|
|
|
|
|
JSON vaccineRecords
|
|
|
|
|
|
JSON diseaseTests
|
|
|
|
|
|
JSON weightCheck
|
|
|
|
|
|
STRING qualityGrade
|
|
|
|
|
|
INT qualityScore
|
|
|
|
|
|
JSON issues
|
|
|
|
|
|
JSON recommendations
|
|
|
|
|
|
JSON photos
|
|
|
|
|
|
ENUM status
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SETTLEMENT {
|
|
|
|
|
|
BIGINT id PK
|
|
|
|
|
|
BIGINT orderId FK
|
|
|
|
|
|
STRING settlementCode
|
|
|
|
|
|
DECIMAL prepaymentAmount
|
|
|
|
|
|
DECIMAL totalAmount
|
|
|
|
|
|
DECIMAL finalAmount
|
|
|
|
|
|
ENUM paymentStatus
|
|
|
|
|
|
DATE paymentDate
|
|
|
|
|
|
STRING invoiceNumber
|
|
|
|
|
|
ENUM invoiceStatus
|
|
|
|
|
|
DECIMAL taxAmount
|
|
|
|
|
|
DECIMAL actualPayment
|
|
|
|
|
|
STRING bankAccount
|
|
|
|
|
|
STRING bankName
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 1.2 核心表结构定义
|
|
|
|
|
|
|
|
|
|
|
|
#### 1.2.1 用户表 (users)
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
const User = sequelize.define('User', {
|
|
|
|
|
|
id: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
primaryKey: true,
|
|
|
|
|
|
autoIncrement: true
|
|
|
|
|
|
},
|
|
|
|
|
|
uuid: {
|
|
|
|
|
|
type: DataTypes.STRING(36),
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
unique: true,
|
|
|
|
|
|
defaultValue: DataTypes.UUIDV4
|
|
|
|
|
|
},
|
|
|
|
|
|
username: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
unique: true,
|
|
|
|
|
|
validate: {
|
|
|
|
|
|
len: [2, 50]
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
password_hash: {
|
|
|
|
|
|
type: DataTypes.STRING(255),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
phone: {
|
|
|
|
|
|
type: DataTypes.STRING(20),
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
unique: true,
|
|
|
|
|
|
validate: {
|
|
|
|
|
|
is: /^1[3-9]\d{9}$/
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
email: {
|
|
|
|
|
|
type: DataTypes.STRING(100),
|
|
|
|
|
|
validate: {
|
|
|
|
|
|
isEmail: true
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
real_name: DataTypes.STRING(50),
|
|
|
|
|
|
avatar_url: DataTypes.STRING(255),
|
|
|
|
|
|
user_type: {
|
|
|
|
|
|
type: DataTypes.ENUM('client', 'supplier', 'driver', 'staff', 'admin'),
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 'client'
|
|
|
|
|
|
},
|
|
|
|
|
|
status: {
|
|
|
|
|
|
type: DataTypes.ENUM('active', 'inactive', 'locked'),
|
|
|
|
|
|
defaultValue: 'active'
|
|
|
|
|
|
},
|
|
|
|
|
|
last_login_at: DataTypes.DATE,
|
|
|
|
|
|
login_count: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
defaultValue: 0
|
|
|
|
|
|
}
|
|
|
|
|
|
}, {
|
|
|
|
|
|
tableName: 'users',
|
|
|
|
|
|
timestamps: true,
|
|
|
|
|
|
paranoid: true, // 软删除
|
|
|
|
|
|
indexes: [
|
|
|
|
|
|
{ fields: ['phone'] },
|
|
|
|
|
|
{ fields: ['user_type'] },
|
|
|
|
|
|
{ fields: ['status'] },
|
|
|
|
|
|
{ fields: ['username'] }
|
|
|
|
|
|
]
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 1.2.2 订单表 (orders)
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
const Order = sequelize.define('Order', {
|
|
|
|
|
|
id: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
primaryKey: true,
|
|
|
|
|
|
autoIncrement: true
|
|
|
|
|
|
},
|
|
|
|
|
|
orderNo: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
unique: true
|
|
|
|
|
|
},
|
|
|
|
|
|
buyerId: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
buyerName: {
|
|
|
|
|
|
type: DataTypes.STRING(100),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
supplierId: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
supplierName: {
|
|
|
|
|
|
type: DataTypes.STRING(100),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
traderId: DataTypes.BIGINT,
|
|
|
|
|
|
traderName: DataTypes.STRING(100),
|
|
|
|
|
|
cattleBreed: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
cattleCount: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
expectedWeight: {
|
|
|
|
|
|
type: DataTypes.DECIMAL(10, 2),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
actualWeight: DataTypes.DECIMAL(10, 2),
|
|
|
|
|
|
unitPrice: {
|
|
|
|
|
|
type: DataTypes.DECIMAL(10, 2),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
totalAmount: {
|
|
|
|
|
|
type: DataTypes.DECIMAL(15, 2),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
paidAmount: {
|
|
|
|
|
|
type: DataTypes.DECIMAL(15, 2),
|
|
|
|
|
|
defaultValue: 0
|
|
|
|
|
|
},
|
|
|
|
|
|
remainingAmount: {
|
|
|
|
|
|
type: DataTypes.DECIMAL(15, 2),
|
|
|
|
|
|
defaultValue: 0
|
|
|
|
|
|
},
|
|
|
|
|
|
status: {
|
|
|
|
|
|
type: DataTypes.ENUM('pending', 'confirmed', 'preparing', 'shipping', 'delivered', 'accepted', 'completed', 'cancelled', 'refunded'),
|
|
|
|
|
|
defaultValue: 'pending'
|
|
|
|
|
|
},
|
|
|
|
|
|
deliveryAddress: {
|
|
|
|
|
|
type: DataTypes.STRING(200),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
expectedDeliveryDate: {
|
|
|
|
|
|
type: DataTypes.DATE,
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
actualDeliveryDate: DataTypes.DATE,
|
|
|
|
|
|
notes: DataTypes.TEXT
|
|
|
|
|
|
}, {
|
|
|
|
|
|
tableName: 'orders',
|
|
|
|
|
|
timestamps: true,
|
|
|
|
|
|
indexes: [
|
|
|
|
|
|
{ fields: ['orderNo'] },
|
|
|
|
|
|
{ fields: ['buyerId'] },
|
|
|
|
|
|
{ fields: ['supplierId'] },
|
|
|
|
|
|
{ fields: ['status'] },
|
|
|
|
|
|
{ fields: ['createdAt'] }
|
|
|
|
|
|
]
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 1.2.3 供应商表 (suppliers)
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
const Supplier = sequelize.define('Supplier', {
|
|
|
|
|
|
id: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
primaryKey: true,
|
|
|
|
|
|
autoIncrement: true
|
|
|
|
|
|
},
|
|
|
|
|
|
name: {
|
|
|
|
|
|
type: DataTypes.STRING(100),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
code: {
|
|
|
|
|
|
type: DataTypes.STRING(20),
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
unique: true
|
|
|
|
|
|
},
|
|
|
|
|
|
contact: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
phone: {
|
|
|
|
|
|
type: DataTypes.STRING(20),
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
unique: true
|
|
|
|
|
|
},
|
|
|
|
|
|
address: {
|
|
|
|
|
|
type: DataTypes.STRING(200),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
businessLicense: DataTypes.STRING(255),
|
|
|
|
|
|
qualificationLevel: {
|
|
|
|
|
|
type: DataTypes.STRING(10),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
certifications: DataTypes.JSON,
|
|
|
|
|
|
cattleTypes: DataTypes.JSON,
|
|
|
|
|
|
capacity: DataTypes.INTEGER,
|
|
|
|
|
|
rating: DataTypes.DECIMAL(3, 2),
|
|
|
|
|
|
cooperationStartDate: DataTypes.DATE,
|
|
|
|
|
|
status: {
|
|
|
|
|
|
type: DataTypes.ENUM('active', 'inactive', 'suspended'),
|
|
|
|
|
|
defaultValue: 'active'
|
|
|
|
|
|
},
|
|
|
|
|
|
region: {
|
|
|
|
|
|
type: DataTypes.STRING(20),
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
}
|
|
|
|
|
|
}, {
|
|
|
|
|
|
tableName: 'suppliers',
|
|
|
|
|
|
timestamps: true
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 1.2.4 运输跟踪表 (transport_tracks)
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
const TransportTrack = sequelize.define('TransportTrack', {
|
|
|
|
|
|
id: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
primaryKey: true,
|
|
|
|
|
|
autoIncrement: true
|
|
|
|
|
|
},
|
|
|
|
|
|
orderId: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
driverId: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
allowNull: false
|
|
|
|
|
|
},
|
|
|
|
|
|
latitude: DataTypes.DECIMAL(10, 8),
|
|
|
|
|
|
longitude: DataTypes.DECIMAL(11, 8),
|
|
|
|
|
|
speed: DataTypes.DECIMAL(5, 2),
|
|
|
|
|
|
direction: DataTypes.DECIMAL(5, 2),
|
|
|
|
|
|
cattle_status: DataTypes.STRING(50),
|
|
|
|
|
|
video_url: DataTypes.STRING(255)
|
|
|
|
|
|
}, {
|
|
|
|
|
|
tableName: 'transport_tracks',
|
|
|
|
|
|
timestamps: true
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 2. API详细设计
|
|
|
|
|
|
|
|
|
|
|
|
### 2.1 用户认证与管理API
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.1.1 登录接口
|
|
|
|
|
|
- **路径**: `/api/auth/login`
|
|
|
|
|
|
- **方法**: POST
|
|
|
|
|
|
- **请求体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"username": "string",
|
|
|
|
|
|
"password": "string"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **响应体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"success": true,
|
|
|
|
|
|
"message": "登录成功",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"token": "string",
|
|
|
|
|
|
"userInfo": {
|
|
|
|
|
|
"id": 1,
|
|
|
|
|
|
"username": "string",
|
|
|
|
|
|
"real_name": "string",
|
|
|
|
|
|
"user_type": "string",
|
|
|
|
|
|
"avatar_url": "string"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **错误码**: 401(认证失败), 403(账号锁定)
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.1.2 获取用户列表
|
|
|
|
|
|
- **路径**: `/api/users`
|
|
|
|
|
|
- **方法**: GET
|
|
|
|
|
|
- **请求参数**:
|
|
|
|
|
|
- page: 页码
|
|
|
|
|
|
- pageSize: 每页条数
|
|
|
|
|
|
- keyword: 搜索关键词
|
|
|
|
|
|
- userType: 用户类型
|
|
|
|
|
|
- status: 用户状态
|
|
|
|
|
|
- **响应体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"success": true,
|
|
|
|
|
|
"message": "查询成功",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"list": [],
|
|
|
|
|
|
"total": 0,
|
|
|
|
|
|
"page": 1,
|
|
|
|
|
|
"pageSize": 10
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **权限**: admin/staff
|
|
|
|
|
|
|
|
|
|
|
|
### 2.2 订单管理API
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.2.1 创建订单
|
|
|
|
|
|
- **路径**: `/api/orders`
|
|
|
|
|
|
- **方法**: POST
|
|
|
|
|
|
- **请求体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"buyerId": 1,
|
|
|
|
|
|
"supplierId": 2,
|
|
|
|
|
|
"traderId": 3,
|
|
|
|
|
|
"cattleBreed": "西门塔尔",
|
|
|
|
|
|
"cattleCount": 50,
|
|
|
|
|
|
"expectedWeight": 25000,
|
|
|
|
|
|
"unitPrice": 28.5,
|
|
|
|
|
|
"deliveryAddress": "山东省济南市某养殖场",
|
|
|
|
|
|
"expectedDeliveryDate": "2024-01-15",
|
|
|
|
|
|
"notes": "优质西门塔尔牛"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **响应体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"success": true,
|
|
|
|
|
|
"message": "创建成功",
|
|
|
|
|
|
"data": {}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **权限**: client/staff/admin
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.2.2 获取订单列表
|
|
|
|
|
|
- **路径**: `/api/orders`
|
|
|
|
|
|
- **方法**: GET
|
|
|
|
|
|
- **请求参数**:
|
|
|
|
|
|
- page: 页码
|
|
|
|
|
|
- pageSize: 每页条数
|
|
|
|
|
|
- orderNo: 订单编号
|
|
|
|
|
|
- buyerId: 采购方ID
|
|
|
|
|
|
- supplierId: 供应商ID
|
|
|
|
|
|
- status: 订单状态
|
|
|
|
|
|
- startDate: 开始日期
|
|
|
|
|
|
- endDate: 结束日期
|
|
|
|
|
|
- **响应体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"success": true,
|
|
|
|
|
|
"message": "查询成功",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"list": [],
|
|
|
|
|
|
"total": 0,
|
|
|
|
|
|
"page": 1,
|
|
|
|
|
|
"pageSize": 10
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **权限**: 所有登录用户(根据用户类型过滤数据)
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.2.3 更新订单状态
|
|
|
|
|
|
- **路径**: `/api/orders/{id}/status`
|
|
|
|
|
|
- **方法**: PUT
|
|
|
|
|
|
- **请求体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"status": "confirmed",
|
|
|
|
|
|
"notes": "确认订单"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **响应体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"success": true,
|
|
|
|
|
|
"message": "更新成功",
|
|
|
|
|
|
"data": {}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **权限**: 根据订单状态和用户类型控制
|
|
|
|
|
|
|
|
|
|
|
|
### 2.3 供应商管理API
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.3.1 创建供应商
|
|
|
|
|
|
- **路径**: `/api/suppliers`
|
|
|
|
|
|
- **方法**: POST
|
|
|
|
|
|
- **请求体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"name": "山东优质牲畜合作社",
|
|
|
|
|
|
"code": "SUP001",
|
|
|
|
|
|
"contact": "李经理",
|
|
|
|
|
|
"phone": "15888888888",
|
|
|
|
|
|
"address": "山东省济南市历城区牲畜养殖基地",
|
|
|
|
|
|
"qualificationLevel": "A",
|
|
|
|
|
|
"cattleTypes": ["肉牛", "奶牛"],
|
|
|
|
|
|
"capacity": 5000,
|
|
|
|
|
|
"region": "east"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **响应体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"success": true,
|
|
|
|
|
|
"message": "创建成功",
|
|
|
|
|
|
"data": {}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **权限**: staff/admin
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.3.2 获取供应商列表
|
|
|
|
|
|
- **路径**: `/api/suppliers`
|
|
|
|
|
|
- **方法**: GET
|
|
|
|
|
|
- **请求参数**:
|
|
|
|
|
|
- page: 页码
|
|
|
|
|
|
- pageSize: 每页条数
|
|
|
|
|
|
- keyword: 搜索关键词
|
|
|
|
|
|
- region: 地区
|
|
|
|
|
|
- qualificationLevel: 资质等级
|
|
|
|
|
|
- status: 状态
|
|
|
|
|
|
- **响应体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"success": true,
|
|
|
|
|
|
"message": "查询成功",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"list": [],
|
|
|
|
|
|
"total": 0,
|
|
|
|
|
|
"page": 1,
|
|
|
|
|
|
"pageSize": 10
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **权限**: staff/admin/client
|
|
|
|
|
|
|
|
|
|
|
|
### 2.4 财务管理API
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.4.1 创建结算单
|
|
|
|
|
|
- **路径**: `/api/finance/settlements`
|
|
|
|
|
|
- **方法**: POST
|
|
|
|
|
|
- **请求体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"orderId": 1,
|
|
|
|
|
|
"cattleCount": 50,
|
|
|
|
|
|
"unitPrice": 25000,
|
|
|
|
|
|
"paymentMethod": "bank_transfer",
|
|
|
|
|
|
"settlementDate": "2024-01-20",
|
|
|
|
|
|
"invoiceNumber": "INV001"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **响应体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"success": true,
|
|
|
|
|
|
"message": "创建成功",
|
|
|
|
|
|
"data": {}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **权限**: staff/admin
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.4.2 获取结算列表
|
|
|
|
|
|
- **路径**: `/api/finance/settlements`
|
|
|
|
|
|
- **方法**: GET
|
|
|
|
|
|
- **请求参数**:
|
|
|
|
|
|
- page: 页码
|
|
|
|
|
|
- pageSize: 每页条数
|
|
|
|
|
|
- keyword: 搜索关键词
|
|
|
|
|
|
- paymentStatus: 支付状态
|
|
|
|
|
|
- startDate: 开始日期
|
|
|
|
|
|
- endDate: 结束日期
|
|
|
|
|
|
- **响应体**:
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"success": true,
|
|
|
|
|
|
"message": "查询成功",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"list": [],
|
|
|
|
|
|
"total": 0,
|
|
|
|
|
|
"page": 1,
|
|
|
|
|
|
"pageSize": 10
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **权限**: staff/admin/finance
|
|
|
|
|
|
|
|
|
|
|
|
## 3. 核心业务逻辑流程
|
|
|
|
|
|
|
|
|
|
|
|
### 3.1 订单创建与处理流程
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant Buyer as 采购人
|
|
|
|
|
|
participant System as 系统
|
|
|
|
|
|
participant Trader as 贸易商
|
|
|
|
|
|
participant Supplier as 供应商
|
|
|
|
|
|
participant Driver as 司机
|
|
|
|
|
|
|
|
|
|
|
|
Buyer->>System: 创建采购订单
|
|
|
|
|
|
System-->>Buyer: 返回订单号
|
|
|
|
|
|
System->>Trader: 通知订单待确认
|
|
|
|
|
|
Trader->>System: 确认/拒绝订单
|
|
|
|
|
|
System->>Supplier: 转发订单给供应商
|
|
|
|
|
|
Supplier->>System: 接单/拒单
|
|
|
|
|
|
System->>Driver: 分配运输任务
|
|
|
|
|
|
Driver->>System: 上报运输状态
|
|
|
|
|
|
System->>Buyer: 实时更新订单状态
|
|
|
|
|
|
Driver->>System: 确认送达
|
|
|
|
|
|
Buyer->>System: 验收确认
|
|
|
|
|
|
System->>System: 自动计算结算金额
|
|
|
|
|
|
System->>Buyer: 生成结算单
|
|
|
|
|
|
Buyer->>System: 支付尾款
|
|
|
|
|
|
System->>Trader: 结算款项
|
|
|
|
|
|
System->>Supplier: 结算款项
|
|
|
|
|
|
System-->>Buyer: 订单完成通知
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3.2 牛只质量核验流程
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
A[开始
|
|
|
|
|
|
供应商提交牛只信息] --> B{系统检查
|
|
|
|
|
|
检疫证明}
|
|
|
|
|
|
B -- 合格 --> C[上传消毒证明
|
|
|
|
|
|
和空车过磅视频]
|
|
|
|
|
|
B -- 不合格 --> Z[结束
|
|
|
|
|
|
驳回申请]
|
|
|
|
|
|
C --> D{驻场兽医
|
|
|
|
|
|
在线确认}
|
|
|
|
|
|
D -- 确认 --> E[系统记录
|
|
|
|
|
|
核验信息]
|
|
|
|
|
|
D -- 驳回 --> Z
|
|
|
|
|
|
E --> F[进入装车环节]
|
|
|
|
|
|
F --> G[结束
|
|
|
|
|
|
核验通过]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3.3 运输状态跟踪流程
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant DriverApp as 司机APP
|
|
|
|
|
|
participant System as 系统
|
|
|
|
|
|
participant Backend as 管理后台
|
|
|
|
|
|
participant BuyerApp as 采购方APP
|
|
|
|
|
|
|
|
|
|
|
|
DriverApp->>System: 定时上报位置
|
|
|
|
|
|
DriverApp->>System: 上传视频状态
|
|
|
|
|
|
System->>Backend: 实时更新运输轨迹
|
|
|
|
|
|
System->>BuyerApp: 推送运输状态
|
|
|
|
|
|
Backend->>System: 查询运输详情
|
|
|
|
|
|
BuyerApp->>System: 查询运输详情
|
|
|
|
|
|
|
|
|
|
|
|
alt 异常情况
|
|
|
|
|
|
DriverApp->>System: 上报异常
|
|
|
|
|
|
System->>Backend: 推送异常警报
|
|
|
|
|
|
System->>BuyerApp: 推送异常警报
|
|
|
|
|
|
Backend->>System: 处理异常
|
|
|
|
|
|
end
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 前端组件设计
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 管理后台组件结构
|
|
|
|
|
|
```
|
|
|
|
|
|
├── layouts/ # 布局组件
|
|
|
|
|
|
│ └── index.vue # 主布局
|
|
|
|
|
|
├── views/ # 页面组件
|
|
|
|
|
|
│ ├── dashboard/ # 数据驾驶舱
|
|
|
|
|
|
│ ├── login/ # 登录页面
|
|
|
|
|
|
│ ├── order/ # 订单管理
|
|
|
|
|
|
│ ├── user/ # 用户管理
|
|
|
|
|
|
│ ├── supplier/ # 供应商管理
|
|
|
|
|
|
│ ├── transport/ # 运输管理
|
|
|
|
|
|
│ ├── finance/ # 财务管理
|
|
|
|
|
|
│ ├── quality/ # 质量管理
|
|
|
|
|
|
│ └── settings/ # 系统设置
|
|
|
|
|
|
├── components/ # 公共组件
|
|
|
|
|
|
│ ├── common/ # 通用组件
|
|
|
|
|
|
│ └── business/ # 业务组件
|
|
|
|
|
|
├── api/ # API调用
|
|
|
|
|
|
├── stores/ # 状态管理
|
|
|
|
|
|
└── utils/ # 工具函数
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 核心组件设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 4.2.1 订单管理组件
|
|
|
|
|
|
- **功能**: 订单列表展示、筛选、排序、详情查看、状态更新
|
|
|
|
|
|
- **关键属性**:
|
|
|
|
|
|
- orderList: 订单数据列表
|
|
|
|
|
|
- loading: 加载状态
|
|
|
|
|
|
- searchParams: 搜索参数
|
|
|
|
|
|
- pagination: 分页信息
|
|
|
|
|
|
- **关键方法**:
|
|
|
|
|
|
- fetchOrders(): 获取订单列表
|
|
|
|
|
|
- handleStatusChange(): 处理订单状态变更
|
|
|
|
|
|
- handleSearch(): 处理搜索
|
|
|
|
|
|
- handlePagination(): 处理分页
|
|
|
|
|
|
|
|
|
|
|
|
#### 4.2.2 地图跟踪组件
|
|
|
|
|
|
- **功能**: 实时展示运输轨迹、车辆位置、牛只状态
|
|
|
|
|
|
- **关键属性**:
|
|
|
|
|
|
- orderId: 订单ID
|
|
|
|
|
|
- trackPoints: 轨迹点数据
|
|
|
|
|
|
- currentLocation: 当前位置
|
|
|
|
|
|
- cattleStatus: 牛只状态
|
|
|
|
|
|
- **关键方法**:
|
|
|
|
|
|
- initMap(): 初始化地图
|
|
|
|
|
|
- updateTrack(): 更新轨迹
|
|
|
|
|
|
- updateStatus(): 更新状态
|
|
|
|
|
|
- startTracking(): 开始跟踪
|
|
|
|
|
|
- stopTracking(): 停止跟踪
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 系统配置与部署
|
|
|
|
|
|
|
|
|
|
|
|
### 5.1 环境配置
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.1.1 开发环境配置 (.env.development)
|
|
|
|
|
|
```
|
|
|
|
|
|
NODE_ENV=development
|
|
|
|
|
|
PORT=3000
|
|
|
|
|
|
DB_HOST=129.211.213.226
|
|
|
|
|
|
DB_PORT=9527
|
|
|
|
|
|
DB_NAME=jiebandata
|
|
|
|
|
|
DB_USER=root
|
|
|
|
|
|
DB_PASSWORD=aiotAiot123!
|
|
|
|
|
|
DB_DIALECT=mysql
|
|
|
|
|
|
JWT_SECRET=your_jwt_secret
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.1.2 生产环境配置 (.env.production)
|
|
|
|
|
|
```
|
|
|
|
|
|
NODE_ENV=production
|
|
|
|
|
|
PORT=80
|
|
|
|
|
|
DB_HOST=129.211.213.226
|
|
|
|
|
|
DB_PORT=9527
|
|
|
|
|
|
DB_NAME=jiebandata
|
|
|
|
|
|
DB_USER=root
|
|
|
|
|
|
DB_PASSWORD=aiotAiot123!
|
|
|
|
|
|
DB_DIALECT=mysql
|
|
|
|
|
|
JWT_SECRET=your_production_jwt_secret
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5.2 部署步骤
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.2.1 后端部署
|
|
|
|
|
|
1. 安装Node.js环境
|
|
|
|
|
|
2. 克隆代码仓库
|
|
|
|
|
|
3. 安装依赖: `npm install`
|
|
|
|
|
|
4. 配置环境变量
|
|
|
|
|
|
5. 启动服务: `npm start` (推荐使用PM2管理)
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.2.2 前端部署
|
|
|
|
|
|
1. 安装Node.js环境
|
|
|
|
|
|
2. 克隆代码仓库
|
|
|
|
|
|
3. 安装依赖: `npm install`
|
|
|
|
|
|
4. 构建项目: `npm run build`
|
|
|
|
|
|
5. 部署静态文件到Web服务器(Nginx等)
|
|
|
|
|
|
|
|
|
|
|
|
### 5.3 监控与维护
|
|
|
|
|
|
- **日志监控**: 使用日志收集工具收集和分析系统日志
|
|
|
|
|
|
- **性能监控**: 监控系统响应时间、数据库查询性能等指标
|
|
|
|
|
|
- **安全审计**: 定期检查系统安全漏洞,更新依赖包
|
|
|
|
|
|
- **数据备份**: 定期备份数据库,确保数据安全
|
|
|
|
|
|
|
|
|
|
|
|
## 6. 测试策略
|
|
|
|
|
|
|
|
|
|
|
|
### 6.1 单元测试
|
|
|
|
|
|
- 使用Jest框架进行后端API单元测试
|
|
|
|
|
|
- 重点测试业务逻辑和数据验证部分
|
|
|
|
|
|
- 覆盖率目标: ≥80%
|
|
|
|
|
|
|
|
|
|
|
|
### 6.2 集成测试
|
|
|
|
|
|
- 测试API接口之间的交互
|
|
|
|
|
|
- 测试前后端集成
|
|
|
|
|
|
- 测试数据库事务处理
|
|
|
|
|
|
|
|
|
|
|
|
### 6.3 端到端测试
|
|
|
|
|
|
- 使用Cypress或Puppeteer进行UI自动化测试
|
|
|
|
|
|
- 模拟用户真实操作流程
|
|
|
|
|
|
- 重点测试核心业务流程
|
|
|
|
|
|
|
|
|
|
|
|
### 6.4 性能测试
|
|
|
|
|
|
- 使用压测工具测试系统并发处理能力
|
|
|
|
|
|
- 测试大数据量下的系统响应性能
|
|
|
|
|
|
- 确保满足性能要求: 响应时间<2秒,支持100+并发用户
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 文档与培训
|
|
|
|
|
|
|
|
|
|
|
|
### 7.1 开发文档
|
|
|
|
|
|
- 代码注释规范
|
|
|
|
|
|
- API文档(Swagger)
|
|
|
|
|
|
- 数据库设计文档
|
|
|
|
|
|
|
|
|
|
|
|
### 7.2 用户文档
|
|
|
|
|
|
- 操作手册
|
|
|
|
|
|
- 常见问题解答
|
|
|
|
|
|
- 视频教程
|
|
|
|
|
|
|
|
|
|
|
|
### 7.3 培训计划
|
|
|
|
|
|
- 管理员培训
|
|
|
|
|
|
- 操作人员培训
|
|
|
|
|
|
- 技术支持人员培训
|
|
|
|
|
|
|
2025-09-18 08:55:32 +08:00
|
|
|
|
## 8. 小程序端详细设计
|
2025-09-11 19:55:21 +08:00
|
|
|
|
|
2025-09-18 08:55:32 +08:00
|
|
|
|
### 8.1 小程序矩阵架构
|
|
|
|
|
|
|
|
|
|
|
|
系统包含四个独立的小程序应用,分别服务于不同的用户角色:
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.1.1 采购人小程序 (client-mp)
|
|
|
|
|
|
- **目标用户**: 活牛采购方
|
|
|
|
|
|
- **核心功能**:
|
|
|
|
|
|
- 采购订单创建和管理
|
|
|
|
|
|
- 订单状态实时跟踪
|
|
|
|
|
|
- 到货验收和质量确认
|
|
|
|
|
|
- 在线支付和结算查看
|
|
|
|
|
|
- 供应商评价和选择
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.1.2 供应商小程序 (supplier-mp)
|
|
|
|
|
|
- **目标用户**: 牛只供应商
|
|
|
|
|
|
- **核心功能**:
|
|
|
|
|
|
- 订单接收和处理
|
|
|
|
|
|
- 牛只信息管理和维护
|
|
|
|
|
|
- 检疫证明上传管理
|
|
|
|
|
|
- 装车过程视频记录
|
|
|
|
|
|
- 结算款项查看
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.1.3 司机小程序 (driver-mp)
|
|
|
|
|
|
- **目标用户**: 运输司机
|
|
|
|
|
|
- **核心功能**:
|
|
|
|
|
|
- 运输任务接收和确认
|
|
|
|
|
|
- 实时位置上报和轨迹记录
|
|
|
|
|
|
- 牛只状态视频记录
|
|
|
|
|
|
- 异常情况上报
|
|
|
|
|
|
- 到货确认和单据交接
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.1.4 内部员工小程序 (staff-mp)
|
|
|
|
|
|
- **目标用户**: 系统管理员和内部员工
|
|
|
|
|
|
- **核心功能**:
|
|
|
|
|
|
- 全流程订单监控
|
|
|
|
|
|
- 运输实时跟踪管理
|
|
|
|
|
|
- 数据统计和分析
|
|
|
|
|
|
- 系统设置和配置
|
|
|
|
|
|
- 用户管理和权限控制
|
|
|
|
|
|
|
|
|
|
|
|
### 8.2 技术架构设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.2.1 前端技术栈
|
|
|
|
|
|
- **框架**: uni-app + Vue 3 + TypeScript
|
|
|
|
|
|
- **状态管理**: Pinia
|
|
|
|
|
|
- **UI组件**: uni-ui 原生组件
|
|
|
|
|
|
- **构建工具**: Vite
|
|
|
|
|
|
- **代码规范**: ESLint + Prettier
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.2.2 项目结构规范
|
|
|
|
|
|
```
|
|
|
|
|
|
mini_program/
|
|
|
|
|
|
├── client-mp/ # 采购人小程序
|
|
|
|
|
|
├── supplier-mp/ # 供应商小程序
|
|
|
|
|
|
├── driver-mp/ # 司机小程序
|
|
|
|
|
|
├── staff-mp/ # 内部员工小程序
|
|
|
|
|
|
└── shared/ # 共享代码和组件
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
每个小程序项目结构:
|
|
|
|
|
|
```
|
|
|
|
|
|
src/
|
|
|
|
|
|
├── api/ # API接口封装
|
|
|
|
|
|
├── components/ # 公共组件
|
|
|
|
|
|
├── pages/ # 页面组件
|
|
|
|
|
|
├── stores/ # 状态管理
|
|
|
|
|
|
├── utils/ # 工具函数
|
|
|
|
|
|
├── static/ # 静态资源
|
|
|
|
|
|
└── types/ # TypeScript类型定义
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 8.3 核心功能模块设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.3.1 订单管理模块
|
|
|
|
|
|
- **功能**: 订单创建、状态跟踪、详情查看
|
|
|
|
|
|
- **组件**: OrderList, OrderDetail, OrderCreate
|
|
|
|
|
|
- **API**: /api/orders, /api/orders/{id}, /api/orders/{id}/status
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.3.2 运输跟踪模块
|
|
|
|
|
|
- **功能**: 实时位置展示、轨迹回放、状态上报
|
|
|
|
|
|
- **组件**: TransportMap, TrackHistory, StatusReport
|
|
|
|
|
|
- **API**: /api/transport/tracks, /api/transport/{orderId}
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.3.3 质量管理模块
|
|
|
|
|
|
- **功能**: 检疫证明管理、质量验收、异常处理
|
|
|
|
|
|
- **组件**: QualityInspection, CertificateUpload, IssueReport
|
|
|
|
|
|
- **API**: /api/quality/records, /api/quality/certificates
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.3.4 财务管理模块
|
|
|
|
|
|
- **功能**: 结算单查看、在线支付、交易记录
|
|
|
|
|
|
- **组件**: SettlementList, PaymentForm, TransactionHistory
|
|
|
|
|
|
- **API**: /api/finance/settlements, /api/finance/payments
|
|
|
|
|
|
|
|
|
|
|
|
### 8.4 API接口设计规范
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.4.1 统一响应格式
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
interface ApiResponse<T = any> {
|
|
|
|
|
|
success: boolean;
|
|
|
|
|
|
message: string;
|
|
|
|
|
|
data: T;
|
|
|
|
|
|
code?: number;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.4.2 错误处理规范
|
|
|
|
|
|
- **400**: 请求参数错误
|
|
|
|
|
|
- **401**: 未授权访问
|
|
|
|
|
|
- **403**: 权限不足
|
|
|
|
|
|
- **404**: 资源不存在
|
|
|
|
|
|
- **500**: 服务器内部错误
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.4.3 分页查询规范
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
interface PaginationParams {
|
|
|
|
|
|
page?: number;
|
|
|
|
|
|
pageSize?: number;
|
|
|
|
|
|
keyword?: string;
|
|
|
|
|
|
[key: string]: any;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
interface PaginationResponse<T> {
|
|
|
|
|
|
list: T[];
|
|
|
|
|
|
total: number;
|
|
|
|
|
|
page: number;
|
|
|
|
|
|
pageSize: number;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 8.5 性能优化策略
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.5.1 前端性能优化
|
|
|
|
|
|
- 组件懒加载和代码分割
|
|
|
|
|
|
- 图片压缩和CDN加速
|
|
|
|
|
|
- 接口请求合并和缓存
|
|
|
|
|
|
- 本地数据持久化存储
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.5.2 后端接口优化
|
|
|
|
|
|
- 接口响应数据精简
|
|
|
|
|
|
- 分页查询支持
|
|
|
|
|
|
- 缓存策略实施
|
|
|
|
|
|
- 数据库查询优化
|
|
|
|
|
|
|
|
|
|
|
|
### 8.6 安全设计考虑
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.6.1 数据传输安全
|
|
|
|
|
|
- HTTPS强制启用
|
|
|
|
|
|
- 敏感数据加密传输
|
|
|
|
|
|
- JWT token认证机制
|
|
|
|
|
|
- 请求签名验证
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.6.2 权限控制
|
|
|
|
|
|
- 基于角色的访问控制(RBAC)
|
|
|
|
|
|
- 接口级别权限验证
|
|
|
|
|
|
- 数据隔离和过滤
|
|
|
|
|
|
|
|
|
|
|
|
### 8.7 测试策略
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.7.1 单元测试
|
|
|
|
|
|
- 组件单元测试(Vitest)
|
|
|
|
|
|
- 工具函数测试
|
|
|
|
|
|
- 状态管理测试
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.7.2 集成测试
|
|
|
|
|
|
- 页面流程测试
|
|
|
|
|
|
- API接口集成测试
|
|
|
|
|
|
- 跨端兼容性测试
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.7.3 E2E测试
|
|
|
|
|
|
- 核心业务流程测试
|
|
|
|
|
|
- 用户操作场景测试
|
|
|
|
|
|
- 性能监控测试
|
|
|
|
|
|
|
|
|
|
|
|
### 8.8 部署和发布
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.8.1 开发环境
|
|
|
|
|
|
- 本地开发服务器
|
|
|
|
|
|
- API mock支持
|
|
|
|
|
|
- 热重载和调试
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.8.2 生产环境
|
|
|
|
|
|
- 多平台构建(微信小程序、H5、App)
|
|
|
|
|
|
- 自动化部署流水线
|
|
|
|
|
|
- 版本管理和回滚
|
|
|
|
|
|
|
|
|
|
|
|
### 8.9 监控和维护
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.9.1 性能监控
|
|
|
|
|
|
- 页面加载性能监控
|
|
|
|
|
|
- 接口响应时间监控
|
|
|
|
|
|
- 错误率和异常监控
|
|
|
|
|
|
|
|
|
|
|
|
#### 8.9.2 用户行为分析
|
|
|
|
|
|
- 用户操作路径分析
|
|
|
|
|
|
- 功能使用率统计
|
|
|
|
|
|
- 用户反馈收集
|
|
|
|
|
|
|
|
|
|
|
|
## 9. 小程序端详细设计与实现
|
|
|
|
|
|
|
|
|
|
|
|
### 9.1 内部员工小程序 (staff-mp) 详细设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.1.1 核心功能模块
|
|
|
|
|
|
|
|
|
|
|
|
**订单监控模块**
|
|
|
|
|
|
- 实时订单状态看板
|
|
|
|
|
|
- 多维度订单筛选和搜索
|
|
|
|
|
|
- 订单详情查看和操作
|
|
|
|
|
|
- 批量订单处理功能
|
|
|
|
|
|
|
|
|
|
|
|
**运输监控模块**
|
|
|
|
|
|
- 实时地图轨迹展示
|
|
|
|
|
|
- 运输状态实时更新
|
|
|
|
|
|
- 异常运输预警提醒
|
|
|
|
|
|
- 历史轨迹回放功能
|
|
|
|
|
|
|
|
|
|
|
|
**数据统计模块**
|
|
|
|
|
|
- 业务数据可视化展示
|
|
|
|
|
|
- 多维度统计分析
|
|
|
|
|
|
- 自定义报表生成
|
|
|
|
|
|
- 数据导出功能
|
|
|
|
|
|
|
|
|
|
|
|
**系统管理模块**
|
|
|
|
|
|
- 用户权限管理
|
|
|
|
|
|
- 系统参数配置
|
|
|
|
|
|
- 操作日志查看
|
|
|
|
|
|
- 系统状态监控
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.1.2 技术架构实现
|
|
|
|
|
|
|
|
|
|
|
|
**前端技术栈**
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 项目技术栈配置
|
|
|
|
|
|
{
|
|
|
|
|
|
framework: "uni-app + Vue 3 + TypeScript",
|
|
|
|
|
|
stateManagement: "Pinia",
|
|
|
|
|
|
uiComponents: "uni-ui + 自定义业务组件",
|
|
|
|
|
|
buildTool: "Vite",
|
|
|
|
|
|
codeQuality: "ESLint + Prettier + Husky",
|
|
|
|
|
|
testing: "Vitest + Vue Test Utils"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**项目结构规范**
|
|
|
|
|
|
```
|
|
|
|
|
|
staff-mp/
|
|
|
|
|
|
├── src/
|
|
|
|
|
|
│ ├── api/ # API接口封装
|
|
|
|
|
|
│ │ ├── order.ts # 订单相关API
|
|
|
|
|
|
│ │ ├── transport.ts # 运输相关API
|
|
|
|
|
|
│ │ ├── statistics.ts # 统计相关API
|
|
|
|
|
|
│ │ └── system.ts # 系统相关API
|
|
|
|
|
|
│ ├── components/ # 组件库
|
|
|
|
|
|
│ │ ├── common/ # 通用组件
|
|
|
|
|
|
│ │ │ ├── AppPagination.vue
|
|
|
|
|
|
│ │ │ ├── AppSearchBar.vue
|
|
|
|
|
|
│ │ │ └── AppFilterPanel.vue
|
|
|
|
|
|
│ │ └── business/ # 业务组件
|
|
|
|
|
|
│ │ ├── OrderCard.vue # 订单卡片
|
|
|
|
|
|
│ │ ├── TransportMap.vue # 运输地图
|
|
|
|
|
|
│ │ └── DataChart.vue # 数据图表
|
|
|
|
|
|
│ ├── pages/ # 页面组件
|
|
|
|
|
|
│ │ ├── index/ # 首页
|
|
|
|
|
|
│ │ │ └── index.vue # 数据驾驶舱
|
|
|
|
|
|
│ │ ├── order/ # 订单管理
|
|
|
|
|
|
│ │ │ └── order-monitor.vue # 订单监控
|
|
|
|
|
|
│ │ ├── transport/ # 运输管理
|
|
|
|
|
|
│ │ │ └── transport-monitor.vue # 运输监控
|
|
|
|
|
|
│ │ ├── statistics/ # 统计分析
|
|
|
|
|
|
│ │ │ └── data-dashboard.vue # 数据看板
|
|
|
|
|
|
│ │ └── system/ # 系统设置
|
|
|
|
|
|
│ │ └── system-settings.vue # 系统设置
|
|
|
|
|
|
│ ├── stores/ # 状态管理
|
|
|
|
|
|
│ │ ├── orderStore.ts # 订单状态管理
|
|
|
|
|
|
│ │ ├── transportStore.ts # 运输状态管理
|
|
|
|
|
|
│ │ └── userStore.ts # 用户状态管理
|
|
|
|
|
|
│ ├── utils/ # 工具函数
|
|
|
|
|
|
│ │ ├── api.ts # API请求工具
|
|
|
|
|
|
│ │ ├── date.ts # 日期处理工具
|
|
|
|
|
|
│ │ └── validation.ts # 数据验证工具
|
|
|
|
|
|
│ ├── types/ # TypeScript类型定义
|
|
|
|
|
|
│ │ ├── order.ts # 订单相关类型
|
|
|
|
|
|
│ │ ├── transport.ts # 运输相关类型
|
|
|
|
|
|
│ │ └── user.ts # 用户相关类型
|
|
|
|
|
|
│ └── static/ # 静态资源
|
|
|
|
|
|
│ └── tabbar/ # 标签栏图标
|
|
|
|
|
|
└── package.json # 项目配置
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.1.3 API接口设计
|
|
|
|
|
|
|
|
|
|
|
|
**订单相关API**
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 获取订单列表
|
|
|
|
|
|
GET /api/staff/orders
|
|
|
|
|
|
Params: {
|
|
|
|
|
|
page?: number;
|
|
|
|
|
|
pageSize?: number;
|
|
|
|
|
|
status?: string;
|
|
|
|
|
|
keyword?: string;
|
|
|
|
|
|
startDate?: string;
|
|
|
|
|
|
endDate?: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取订单详情
|
|
|
|
|
|
GET /api/staff/orders/{id}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新订单状态
|
|
|
|
|
|
PUT /api/staff/orders/{id}/status
|
|
|
|
|
|
Body: {
|
|
|
|
|
|
status: string;
|
|
|
|
|
|
notes?: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 批量处理订单
|
|
|
|
|
|
POST /api/staff/orders/batch
|
|
|
|
|
|
Body: {
|
|
|
|
|
|
action: string;
|
|
|
|
|
|
orderIds: number[];
|
|
|
|
|
|
data?: any;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**运输相关API**
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 获取运输轨迹
|
|
|
|
|
|
GET /api/staff/transport/tracks
|
|
|
|
|
|
Params: {
|
|
|
|
|
|
orderId: number;
|
|
|
|
|
|
startTime?: string;
|
|
|
|
|
|
endTime?: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 实时运输状态
|
|
|
|
|
|
GET /api/staff/transport/realtime
|
|
|
|
|
|
Params: {
|
|
|
|
|
|
orderIds?: number[];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 运输异常上报
|
|
|
|
|
|
POST /api/staff/transport/issues
|
|
|
|
|
|
Body: {
|
|
|
|
|
|
orderId: number;
|
|
|
|
|
|
type: string;
|
|
|
|
|
|
description: string;
|
|
|
|
|
|
images?: string[];
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.1.4 状态管理设计
|
|
|
|
|
|
|
|
|
|
|
|
**订单状态管理 (orderStore.ts)**
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
interface OrderState {
|
|
|
|
|
|
orders: Order[];
|
|
|
|
|
|
currentOrder: Order | null;
|
|
|
|
|
|
loading: boolean;
|
|
|
|
|
|
error: string | null;
|
|
|
|
|
|
pagination: Pagination;
|
|
|
|
|
|
filters: OrderFilters;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const useOrderStore = defineStore('order', {
|
|
|
|
|
|
state: (): OrderState => ({
|
|
|
|
|
|
orders: [],
|
|
|
|
|
|
currentOrder: null,
|
|
|
|
|
|
loading: false,
|
|
|
|
|
|
error: null,
|
|
|
|
|
|
pagination: { page: 1, pageSize: 10, total: 0 },
|
|
|
|
|
|
filters: {}
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
|
|
getters: {
|
|
|
|
|
|
filteredOrders: (state) => {
|
|
|
|
|
|
// 订单筛选逻辑
|
|
|
|
|
|
},
|
|
|
|
|
|
orderStats: (state) => {
|
|
|
|
|
|
// 订单统计逻辑
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
actions: {
|
|
|
|
|
|
async fetchOrders(params?: OrderQueryParams) {
|
|
|
|
|
|
// 获取订单列表
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
async fetchOrderDetail(id: number) {
|
|
|
|
|
|
// 获取订单详情
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
async updateOrderStatus(payload: OrderStatusUpdate) {
|
|
|
|
|
|
// 更新订单状态
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.1.5 组件设计规范
|
|
|
|
|
|
|
|
|
|
|
|
**订单卡片组件 (OrderCard.vue)**
|
|
|
|
|
|
```vue
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<view class="order-card">
|
|
|
|
|
|
<view class="header">
|
|
|
|
|
|
<text class="order-no">{{ order.orderNo }}</text>
|
|
|
|
|
|
<order-status-badge :status="order.status" />
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="content">
|
|
|
|
|
|
<order-info-row label="品种" :value="order.cattleBreed" />
|
|
|
|
|
|
<order-info-row label="数量" :value="`${order.cattleCount}头`" />
|
|
|
|
|
|
<order-info-row label="重量" :value="`${order.expectedWeight}kg`" />
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="actions">
|
|
|
|
|
|
<button @click="handleViewDetail">查看详情</button>
|
|
|
|
|
|
<button v-if="canOperate" @click="handleOperate">操作</button>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
interface Props {
|
|
|
|
|
|
order: Order;
|
|
|
|
|
|
showActions?: boolean;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const props = defineProps<Props>();
|
|
|
|
|
|
const emit = defineEmits(['view-detail', 'operate']);
|
|
|
|
|
|
|
|
|
|
|
|
const canOperate = computed(() => {
|
|
|
|
|
|
// 操作权限判断
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.1.6 性能优化策略
|
|
|
|
|
|
|
|
|
|
|
|
**前端性能优化**
|
|
|
|
|
|
- 组件懒加载和代码分割
|
|
|
|
|
|
- 接口数据缓存和本地存储
|
|
|
|
|
|
- 图片懒加载和CDN加速
|
|
|
|
|
|
- 列表虚拟滚动支持
|
|
|
|
|
|
|
|
|
|
|
|
**后端接口优化**
|
|
|
|
|
|
- 接口响应数据精简
|
|
|
|
|
|
- 分页查询支持
|
|
|
|
|
|
- 缓存策略实施
|
|
|
|
|
|
- 数据库查询优化
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.1.7 安全设计考虑
|
|
|
|
|
|
|
|
|
|
|
|
**数据传输安全**
|
|
|
|
|
|
- HTTPS强制启用
|
|
|
|
|
|
- 敏感数据加密传输
|
|
|
|
|
|
- JWT token认证机制
|
|
|
|
|
|
- 请求签名验证
|
|
|
|
|
|
|
|
|
|
|
|
**权限控制**
|
|
|
|
|
|
- 基于角色的访问控制(RBAC)
|
|
|
|
|
|
- 接口级别权限验证
|
|
|
|
|
|
- 数据隔离和过滤
|
|
|
|
|
|
|
|
|
|
|
|
### 9.2 测试策略
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.2.1 单元测试
|
|
|
|
|
|
- 组件单元测试(Vitest)
|
|
|
|
|
|
- 工具函数测试
|
|
|
|
|
|
- 状态管理测试
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.2.2 集成测试
|
|
|
|
|
|
- 页面流程测试
|
|
|
|
|
|
- API接口集成测试
|
|
|
|
|
|
- 跨端兼容性测试
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.2.3 E2E测试
|
|
|
|
|
|
- 核心业务流程测试
|
|
|
|
|
|
- 用户操作场景测试
|
|
|
|
|
|
- 性能监控测试
|
|
|
|
|
|
|
|
|
|
|
|
### 9.3 部署和发布
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.3.1 开发环境
|
|
|
|
|
|
- 本地开发服务器
|
|
|
|
|
|
- API mock支持
|
|
|
|
|
|
- 热重载和调试
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.3.2 生产环境
|
|
|
|
|
|
- 多平台构建(微信小程序、H5、App)
|
|
|
|
|
|
- 自动化部署流水线
|
|
|
|
|
|
- 版本管理和回滚
|
|
|
|
|
|
|
|
|
|
|
|
### 9.4 监控和维护
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.4.1 性能监控
|
|
|
|
|
|
- 页面加载性能监控
|
|
|
|
|
|
- 接口响应时间监控
|
|
|
|
|
|
- 错误率和异常监控
|
|
|
|
|
|
|
|
|
|
|
|
#### 9.4.2 用户行为分析
|
|
|
|
|
|
- 用户操作路径分析
|
|
|
|
|
|
- 功能使用率统计
|
|
|
|
|
|
- 用户反馈收集
|
|
|
|
|
|
|
|
|
|
|
|
## 10. 其他小程序端详细设计
|
|
|
|
|
|
|
|
|
|
|
|
### 10.1 采购人小程序 (client-mp) 详细设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.1.1 核心功能模块
|
|
|
|
|
|
- **订单管理**: 采购订单创建、查看、状态跟踪
|
|
|
|
|
|
- **运输监控**: 实时地图轨迹、牛只状态查看
|
|
|
|
|
|
- **到货验收**: 扫码验收、质量确认、异常处理
|
|
|
|
|
|
- **支付结算**: 在线支付、交易记录、发票管理
|
|
|
|
|
|
- **供应商管理**: 供应商选择、评价、收藏
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.1.2 技术实现特点
|
|
|
|
|
|
- 简化操作流程,一键式功能设计
|
|
|
|
|
|
- 扫码快速操作支持
|
|
|
|
|
|
- 离线操作能力
|
|
|
|
|
|
- 支付流程优化
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.1.3 用户体验重点
|
|
|
|
|
|
- 直观的订单状态展示
|
|
|
|
|
|
- 便捷的验收操作流程
|
|
|
|
|
|
- 安全的支付环境
|
|
|
|
|
|
- 及时的异常通知
|
|
|
|
|
|
|
|
|
|
|
|
### 10.2 供应商小程序 (supplier-mp) 详细设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.2.1 核心功能模块
|
|
|
|
|
|
- **订单处理**: 订单接收、确认、状态更新
|
|
|
|
|
|
- **牛只管理**: 牛只信息维护、检疫证明管理
|
|
|
|
|
|
- **装车管理**: 装车过程记录、视频上传
|
|
|
|
|
|
- **结算管理**: 结算款项查看、交易记录
|
|
|
|
|
|
- **资质管理**: 证件管理、资质维护
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.2.2 技术实现特点
|
|
|
|
|
|
- 证件上传和管理的便捷性
|
|
|
|
|
|
- 视频录制和上传功能
|
|
|
|
|
|
- 离线数据同步能力
|
|
|
|
|
|
- 多证件类型支持
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.2.3 用户体验重点
|
|
|
|
|
|
- 清晰的订单状态可视化
|
|
|
|
|
|
- 简便的证件上传流程
|
|
|
|
|
|
- 稳定的视频录制功能
|
|
|
|
|
|
- 及时的结算通知
|
|
|
|
|
|
|
|
|
|
|
|
### 10.3 司机小程序 (driver-mp) 详细设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.3.1 核心功能模块
|
|
|
|
|
|
- **任务管理**: 运输任务接收、确认、完成
|
|
|
|
|
|
- **位置上报**: 自动位置上报、轨迹记录
|
|
|
|
|
|
- **状态记录**: 牛只状态视频记录、异常上报
|
|
|
|
|
|
- **单据管理**: 运输单据查看、交接确认
|
|
|
|
|
|
- **紧急处理**: 异常情况快速上报、求助
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.3.2 技术实现特点
|
|
|
|
|
|
- 后台位置持续上报
|
|
|
|
|
|
- 离线操作支持
|
|
|
|
|
|
- 低功耗运行优化
|
|
|
|
|
|
- 紧急情况快速响应
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.3.3 用户体验重点
|
|
|
|
|
|
- 简洁的任务界面
|
|
|
|
|
|
- 一键式状态上报
|
|
|
|
|
|
- 清晰的导航指引
|
|
|
|
|
|
- 紧急情况快速处理
|
|
|
|
|
|
|
|
|
|
|
|
### 10.4 小程序矩阵技术架构统一性
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.4.1 共享技术栈
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 统一技术栈配置
|
|
|
|
|
|
const sharedTechStack = {
|
|
|
|
|
|
framework: "uni-app + Vue 3 + TypeScript",
|
|
|
|
|
|
stateManagement: "Pinia",
|
|
|
|
|
|
buildTool: "Vite",
|
|
|
|
|
|
codeQuality: "ESLint + Prettier",
|
|
|
|
|
|
testing: "Vitest"
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.4.2 共享组件库
|
|
|
|
|
|
- 统一的基础UI组件
|
|
|
|
|
|
- 通用的业务组件
|
|
|
|
|
|
- 标准的设计规范
|
|
|
|
|
|
- 一致的交互模式
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.4.3 统一API规范
|
|
|
|
|
|
- 一致的响应格式
|
|
|
|
|
|
- 标准的错误处理
|
|
|
|
|
|
- 统一的认证机制
|
|
|
|
|
|
- 规范的接口文档
|
|
|
|
|
|
|
|
|
|
|
|
### 10.5 小程序间数据流设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.5.1 订单状态同步
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
A[采购人创建订单] --> B[系统生成订单]
|
|
|
|
|
|
B --> C[贸易商确认转发]
|
|
|
|
|
|
C --> D[供应商接收订单]
|
|
|
|
|
|
D --> E[司机接收运输任务]
|
|
|
|
|
|
E --> F[实时状态更新]
|
|
|
|
|
|
F --> G[各端状态同步]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 10.5.2 运输状态同步
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant Driver as 司机APP
|
|
|
|
|
|
participant System as 系统服务
|
|
|
|
|
|
participant Client as 采购人APP
|
|
|
|
|
|
participant Supplier as 供应商APP
|
|
|
|
|
|
participant Staff as 内部员工APP
|
|
|
|
|
|
|
|
|
|
|
|
Driver->>System: 实时位置上报
|
|
|
|
|
|
System->>Client: 推送运输状态
|
|
|
|
|
|
System->>Supplier: 推送运输状态
|
|
|
|
|
|
System->>Staff: 更新监控数据
|
|
|
|
|
|
Client->>System: 查询运输详情
|
|
|
|
|
|
Supplier->>System: 查询运输详情
|
|
|
|
|
|
Staff->>System: 获取监控数据
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 11. 小程序端部署与运维
|
|
|
|
|
|
|
|
|
|
|
|
### 11.1 开发环境配置
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.1.1 开发工具要求
|
|
|
|
|
|
- Node.js: 16.x 或更高版本
|
|
|
|
|
|
- npm: 8.x 或更高版本
|
|
|
|
|
|
- HBuilderX: 最新版本(可选)
|
|
|
|
|
|
- 微信开发者工具: 最新版本
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.1.2 环境变量配置
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# .env.development
|
|
|
|
|
|
VITE_APP_ENV=development
|
|
|
|
|
|
VITE_APP_API_BASE=http://localhost:3000/api
|
|
|
|
|
|
VITE_APP_WS_URL=ws://localhost:3000
|
|
|
|
|
|
VITE_APP_MAP_KEY=your_map_sdk_key
|
|
|
|
|
|
|
|
|
|
|
|
# .env.production
|
|
|
|
|
|
VITE_APP_ENV=production
|
|
|
|
|
|
VITE_APP_API_BASE=https://api.example.com/api
|
|
|
|
|
|
VITE_APP_WS_URL=wss://api.example.com
|
|
|
|
|
|
VITE_APP_MAP_KEY=your_production_map_key
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.1.3 依赖安装
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 安装项目依赖
|
|
|
|
|
|
npm install
|
|
|
|
|
|
|
|
|
|
|
|
# 安装uni-app编译器
|
|
|
|
|
|
npm install @dcloudio/uni-app
|
|
|
|
|
|
|
|
|
|
|
|
# 安装类型定义
|
|
|
|
|
|
npm install @types/wechat-miniprogram -D
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 11.2 构建和部署
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.2.1 开发环境运行
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 启动开发服务器
|
|
|
|
|
|
npm run dev
|
|
|
|
|
|
|
|
|
|
|
|
# 指定平台运行
|
|
|
|
|
|
npm run dev:mp-weixin # 微信小程序
|
|
|
|
|
|
npm run dev:h5 # H5端
|
|
|
|
|
|
npm run dev:app # App端
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.2.2 生产环境构建
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 构建生产版本
|
|
|
|
|
|
npm run build
|
|
|
|
|
|
|
|
|
|
|
|
# 指定平台构建
|
|
|
|
|
|
npm run build:mp-weixin # 微信小程序
|
|
|
|
|
|
npm run build:h5 # H5端
|
|
|
|
|
|
npm run build:app # App端
|
|
|
|
|
|
|
|
|
|
|
|
# 构建并预览
|
|
|
|
|
|
npm run build:preview
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.2.3 微信小程序部署
|
|
|
|
|
|
1. 使用微信开发者工具打开项目
|
|
|
|
|
|
2. 点击"上传"按钮发布体验版
|
|
|
|
|
|
3. 在微信公众平台提交审核
|
|
|
|
|
|
4. 审核通过后发布正式版
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.2.4 自动化部署流程
|
|
|
|
|
|
```yaml
|
|
|
|
|
|
# GitHub Actions 部署配置
|
|
|
|
|
|
name: Deploy Mini Program
|
|
|
|
|
|
|
|
|
|
|
|
on:
|
|
|
|
|
|
push:
|
|
|
|
|
|
branches: [ main ]
|
|
|
|
|
|
paths:
|
|
|
|
|
|
- 'mini_program/**'
|
|
|
|
|
|
|
|
|
|
|
|
jobs:
|
|
|
|
|
|
deploy:
|
|
|
|
|
|
runs-on: ubuntu-latest
|
|
|
|
|
|
steps:
|
|
|
|
|
|
- uses: actions/checkout@v3
|
|
|
|
|
|
- name: Setup Node.js
|
|
|
|
|
|
uses: actions/setup-node@v3
|
|
|
|
|
|
with:
|
|
|
|
|
|
node-version: '18'
|
|
|
|
|
|
cache: 'npm'
|
|
|
|
|
|
cache-dependency-path: mini_program/**/package-lock.json
|
|
|
|
|
|
|
|
|
|
|
|
- name: Install dependencies
|
|
|
|
|
|
run: |
|
|
|
|
|
|
cd mini_program/staff-mp
|
|
|
|
|
|
npm ci
|
|
|
|
|
|
|
|
|
|
|
|
- name: Build project
|
|
|
|
|
|
run: |
|
|
|
|
|
|
cd mini_program/staff-mp
|
|
|
|
|
|
npm run build:mp-weixin
|
|
|
|
|
|
|
|
|
|
|
|
- name: Deploy to CDN
|
|
|
|
|
|
uses: actions/upload-artifact@v3
|
|
|
|
|
|
with:
|
|
|
|
|
|
name: dist
|
|
|
|
|
|
path: mini_program/staff-mp/dist/**
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 11.3 监控和维护
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.3.1 性能监控指标
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 性能监控配置
|
|
|
|
|
|
const performanceMetrics = {
|
|
|
|
|
|
pageLoadTime: '< 2s', // 页面加载时间
|
|
|
|
|
|
apiResponseTime: '< 1s', // API响应时间
|
|
|
|
|
|
fps: '> 50', // 帧率
|
|
|
|
|
|
memoryUsage: '< 50MB', // 内存使用
|
|
|
|
|
|
crashRate: '< 0.1%' // 崩溃率
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.3.2 错误监控
|
|
|
|
|
|
- 前端错误日志收集
|
|
|
|
|
|
- 接口异常监控
|
|
|
|
|
|
- 用户操作异常记录
|
|
|
|
|
|
- 崩溃报告自动上报
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.3.3 用户行为分析
|
|
|
|
|
|
- 页面访问统计
|
|
|
|
|
|
- 功能使用率分析
|
|
|
|
|
|
- 用户操作路径追踪
|
|
|
|
|
|
- 转化率分析
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.3.4 定期维护任务
|
|
|
|
|
|
- 依赖包版本更新
|
|
|
|
|
|
- 安全漏洞修复
|
|
|
|
|
|
- 性能优化调整
|
|
|
|
|
|
- 兼容性测试
|
|
|
|
|
|
|
|
|
|
|
|
### 11.4 故障处理流程
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.4.1 紧急故障处理
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
A[监控系统告警] --> B[确认故障影响范围]
|
|
|
|
|
|
B --> C{故障级别}
|
|
|
|
|
|
C -- P0紧急故障 --> D[立即启动应急响应]
|
|
|
|
|
|
C -- P1重要故障 --> E[2小时内处理]
|
|
|
|
|
|
C -- P2一般故障 --> F[24小时内处理]
|
|
|
|
|
|
D --> G[故障定位和修复]
|
|
|
|
|
|
E --> G
|
|
|
|
|
|
F --> G
|
|
|
|
|
|
G --> H[验证修复效果]
|
|
|
|
|
|
H --> I[故障复盘和改进]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 11.4.2 用户反馈处理
|
|
|
|
|
|
- 建立用户反馈渠道
|
|
|
|
|
|
- 快速响应机制
|
|
|
|
|
|
- 问题跟踪和解决
|
|
|
|
|
|
- 用户满意度回访
|
|
|
|
|
|
|
|
|
|
|
|
## 12. 测试策略与质量保证
|
|
|
|
|
|
|
|
|
|
|
|
### 12.1 测试金字塔策略
|
|
|
|
|
|
|
|
|
|
|
|
#### 12.1.1 单元测试 (Unit Testing)
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 示例:订单状态工具函数测试
|
|
|
|
|
|
describe('orderStatusUtils', () => {
|
|
|
|
|
|
test('should return correct status text', () => {
|
|
|
|
|
|
expect(getStatusText('pending')).toBe('待确认');
|
|
|
|
|
|
expect(getStatusText('shipping')).toBe('运输中');
|
|
|
|
|
|
expect(getStatusText('completed')).toBe('已完成');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should validate order data', () => {
|
|
|
|
|
|
expect(validateOrder(validOrder)).toBe(true);
|
|
|
|
|
|
expect(validateOrder(invalidOrder)).toBe(false);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 12.1.2 组件测试 (Component Testing)
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 示例:订单卡片组件测试
|
|
|
|
|
|
describe('OrderCard', () => {
|
|
|
|
|
|
test('renders order information correctly', () => {
|
|
|
|
|
|
const wrapper = mount(OrderCard, {
|
|
|
|
|
|
props: { order: mockOrder }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
expect(wrapper.find('.order-no').text()).toBe(mockOrder.orderNo);
|
|
|
|
|
|
expect(wrapper.find('.status-badge').exists()).toBe(true);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('emits events on button click', async () => {
|
|
|
|
|
|
const wrapper = mount(OrderCard, {
|
|
|
|
|
|
props: { order: mockOrder, showActions: true }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
await wrapper.find('.view-detail-btn').trigger('click');
|
|
|
|
|
|
expect(wrapper.emitted('view-detail')).toBeTruthy();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 12.1.3 端到端测试 (E2E Testing)
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 示例:订单创建流程测试
|
|
|
|
|
|
describe('Order Creation Flow', () => {
|
|
|
|
|
|
test('should create order successfully', async () => {
|
|
|
|
|
|
// 登录系统
|
|
|
|
|
|
await page.goto('/login');
|
|
|
|
|
|
await page.fill('#username', 'testuser');
|
|
|
|
|
|
await page.fill('#password', 'password123');
|
|
|
|
|
|
await page.click('#login-btn');
|
|
|
|
|
|
|
|
|
|
|
|
// 创建订单
|
|
|
|
|
|
await page.click('#create-order-btn');
|
|
|
|
|
|
await page.fill('#cattle-breed', '西门塔尔');
|
|
|
|
|
|
await page.fill('#cattle-count', '50');
|
|
|
|
|
|
await page.click('#submit-btn');
|
|
|
|
|
|
|
|
|
|
|
|
// 验证结果
|
|
|
|
|
|
await expect(page).toHaveText('订单创建成功');
|
|
|
|
|
|
await expect(page).toHaveText('待确认');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 12.2 测试覆盖率要求
|
|
|
|
|
|
|
|
|
|
|
|
#### 12.2.1 覆盖率目标
|
|
|
|
|
|
```yaml
|
|
|
|
|
|
# 测试覆盖率配置
|
|
|
|
|
|
coverage:
|
|
|
|
|
|
statements: 80% # 语句覆盖率
|
|
|
|
|
|
branches: 75% # 分支覆盖率
|
|
|
|
|
|
functions: 85% # 函数覆盖率
|
|
|
|
|
|
lines: 80% # 行覆盖率
|
|
|
|
|
|
exclude: # 排除文件
|
|
|
|
|
|
- '**/*.d.ts'
|
|
|
|
|
|
- '**/mock/**'
|
|
|
|
|
|
- '**/test/**'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 12.2.2 关键模块覆盖率要求
|
|
|
|
|
|
- **核心业务逻辑**: ≥90%
|
|
|
|
|
|
- **工具函数**: ≥85%
|
|
|
|
|
|
- **组件逻辑**: ≥80%
|
|
|
|
|
|
- **API调用**: ≥75%
|
|
|
|
|
|
|
|
|
|
|
|
### 12.3 自动化测试流程
|
|
|
|
|
|
|
|
|
|
|
|
#### 12.3.1 CI/CD集成
|
|
|
|
|
|
```yaml
|
|
|
|
|
|
# GitHub Actions 测试配置
|
|
|
|
|
|
name: Test Mini Program
|
|
|
|
|
|
|
|
|
|
|
|
on:
|
|
|
|
|
|
pull_request:
|
|
|
|
|
|
branches: [ main ]
|
|
|
|
|
|
push:
|
|
|
|
|
|
branches: [ main ]
|
|
|
|
|
|
|
|
|
|
|
|
jobs:
|
|
|
|
|
|
test:
|
|
|
|
|
|
runs-on: ubuntu-latest
|
|
|
|
|
|
steps:
|
|
|
|
|
|
- uses: actions/checkout@v3
|
|
|
|
|
|
- name: Setup Node.js
|
|
|
|
|
|
uses: actions/setup-node@v3
|
|
|
|
|
|
with:
|
|
|
|
|
|
node-version: '18'
|
|
|
|
|
|
cache: 'npm'
|
|
|
|
|
|
cache-dependency-path: mini_program/**/package-lock.json
|
|
|
|
|
|
|
|
|
|
|
|
- name: Install dependencies
|
|
|
|
|
|
run: |
|
|
|
|
|
|
cd mini_program/staff-mp
|
|
|
|
|
|
npm ci
|
|
|
|
|
|
|
|
|
|
|
|
- name: Run unit tests
|
|
|
|
|
|
run: |
|
|
|
|
|
|
cd mini_program/staff-mp
|
|
|
|
|
|
npm run test:unit
|
|
|
|
|
|
|
|
|
|
|
|
- name: Run component tests
|
|
|
|
|
|
run: |
|
|
|
|
|
|
cd mini_program/staff-mp
|
|
|
|
|
|
npm run test:component
|
|
|
|
|
|
|
|
|
|
|
|
- name: Run E2E tests
|
|
|
|
|
|
run: |
|
|
|
|
|
|
cd mini_program/staff-mp
|
|
|
|
|
|
npm run test:e2e
|
|
|
|
|
|
|
|
|
|
|
|
- name: Upload coverage
|
|
|
|
|
|
uses: codecov/codecov-action@v3
|
|
|
|
|
|
with:
|
|
|
|
|
|
file: mini_program/staff-mp/coverage/lcov.info
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 12.3.2 测试环境管理
|
|
|
|
|
|
- **开发环境**: 本地测试和调试
|
|
|
|
|
|
- **测试环境**: 集成测试和API测试
|
|
|
|
|
|
- **预发布环境**: 生产环境模拟测试
|
|
|
|
|
|
- **生产环境**: 监控和真实用户测试
|
|
|
|
|
|
|
|
|
|
|
|
### 12.4 质量度量指标
|
|
|
|
|
|
|
|
|
|
|
|
#### 12.4.1 代码质量指标
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 代码质量监控指标
|
|
|
|
|
|
const codeQualityMetrics = {
|
|
|
|
|
|
complexity: {
|
|
|
|
|
|
cyclomatic: '< 10', // 圈复杂度
|
|
|
|
|
|
cognitive: '< 15' // 认知复杂度
|
|
|
|
|
|
},
|
|
|
|
|
|
maintainability: {
|
|
|
|
|
|
index: '> 65', // 可维护性指数
|
|
|
|
|
|
technicalDebt: '< 5%' // 技术债务比例
|
|
|
|
|
|
},
|
|
|
|
|
|
duplication: {
|
|
|
|
|
|
lines: '< 3%', // 重复代码行比例
|
|
|
|
|
|
blocks: '< 2%' // 重复代码块比例
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 12.4.2 性能质量指标
|
|
|
|
|
|
- **加载性能**: FCP < 1.5s, LCP < 2.5s
|
|
|
|
|
|
- **交互性能**: FID < 100ms, TTI < 3.5s
|
|
|
|
|
|
- **内存使用**: Heap size < 50MB
|
|
|
|
|
|
- **网络请求**: API成功率 > 99.9%
|
|
|
|
|
|
|
|
|
|
|
|
### 12.5 安全测试策略
|
|
|
|
|
|
|
|
|
|
|
|
#### 12.5.1 安全测试范围
|
|
|
|
|
|
- **身份认证**: 登录安全、会话管理
|
|
|
|
|
|
- **权限控制**: 角色权限、数据访问控制
|
|
|
|
|
|
- **输入验证**: XSS、SQL注入防护
|
|
|
|
|
|
- **数据传输**: HTTPS、数据加密
|
|
|
|
|
|
- **存储安全**: 本地数据加密
|
|
|
|
|
|
|
|
|
|
|
|
#### 12.5.2 安全测试工具
|
|
|
|
|
|
- **静态分析**: ESLint安全规则、SonarQube
|
|
|
|
|
|
- **动态分析**: OWASP ZAP、Burp Suite
|
|
|
|
|
|
- **依赖扫描**: npm audit、Snyk
|
|
|
|
|
|
- **渗透测试**: 定期安全审计
|
|
|
|
|
|
|
|
|
|
|
|
## 13. 小程序端详细设计与实现
|
|
|
|
|
|
|
|
|
|
|
|
### 13.1 小程序矩阵详细设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.1.1 采购人小程序 (client-mp) 详细功能
|
|
|
|
|
|
|
|
|
|
|
|
**核心业务流程:**
|
|
|
|
|
|
1. **采购需求创建**
|
|
|
|
|
|
- 品种选择:西门塔尔、安格斯、利木赞等
|
|
|
|
|
|
- 数量重量:头数、预估重量范围
|
|
|
|
|
|
- 交付要求:期望交付日期、交付地点
|
|
|
|
|
|
- 预算控制:单价范围、总预算限制
|
|
|
|
|
|
|
|
|
|
|
|
2. **订单跟踪管理**
|
|
|
|
|
|
- 实时状态:待确认、已确认、准备中、运输中、待验收、已完成
|
|
|
|
|
|
- 地图轨迹:实时运输位置、预计到达时间
|
|
|
|
|
|
- 牛只状态:视频监控查看、健康状态报告
|
|
|
|
|
|
|
|
|
|
|
|
3. **到货验收流程**
|
|
|
|
|
|
- 扫码验收:二维码快速识别订单
|
|
|
|
|
|
- 质量检查:牛只健康状况检查
|
|
|
|
|
|
- 重量确认:实际到货重量记录
|
|
|
|
|
|
- 异常处理:差异记录和问题上报
|
|
|
|
|
|
|
|
|
|
|
|
4. **支付结算功能**
|
|
|
|
|
|
- 结算单查看:自动计算金额明细
|
|
|
|
|
|
- 在线支付:微信支付集成
|
|
|
|
|
|
- 发票管理:电子发票申请和管理
|
|
|
|
|
|
- 交易记录:历史交易查询和导出
|
|
|
|
|
|
|
|
|
|
|
|
**技术实现要点:**
|
|
|
|
|
|
- 采用uni-app跨端框架,支持微信小程序和H5
|
|
|
|
|
|
- 集成腾讯地图SDK实现运输轨迹展示
|
|
|
|
|
|
- 微信支付API集成,支持多种支付方式
|
|
|
|
|
|
- 二维码生成和识别功能
|
|
|
|
|
|
- 离线操作支持,网络恢复后自动同步
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.1.2 供应商小程序 (supplier-mp) 详细功能
|
|
|
|
|
|
|
|
|
|
|
|
**核心业务流程:**
|
|
|
|
|
|
1. **订单接收处理**
|
|
|
|
|
|
- 订单通知:实时推送新订单提醒
|
|
|
|
|
|
- 订单确认:接单/拒单操作
|
|
|
|
|
|
- 产能匹配:可用牛只数量检查
|
|
|
|
|
|
- 时间安排:装车时间确认
|
|
|
|
|
|
|
|
|
|
|
|
2. **牛只准备管理**
|
|
|
|
|
|
- 牛只信息:品种、年龄、重量、健康状态
|
|
|
|
|
|
- 检疫证明:电子证件上传和管理
|
|
|
|
|
|
- 隔离管理:空水空槽时间记录
|
|
|
|
|
|
- 装车准备:装车顺序和分组安排
|
|
|
|
|
|
|
|
|
|
|
|
3. **装车过程管理**
|
|
|
|
|
|
- 视频记录:装车全过程视频录制
|
|
|
|
|
|
- 数量清点:装车数量确认和记录
|
|
|
|
|
|
- 重量记录:空车和重车过磅记录
|
|
|
|
|
|
- 消毒证明:车辆消毒记录上传
|
|
|
|
|
|
|
|
|
|
|
|
4. **结算管理**
|
|
|
|
|
|
- 结算单查看:已完成订单结算明细
|
|
|
|
|
|
- 收款记录:历史收款记录查询
|
|
|
|
|
|
- 对账功能:月度对账单生成
|
|
|
|
|
|
- 发票管理:发票申请和邮寄
|
|
|
|
|
|
|
|
|
|
|
|
**技术实现要点:**
|
|
|
|
|
|
- 视频录制和压缩上传功能
|
|
|
|
|
|
- 证件OCR识别和自动填充
|
|
|
|
|
|
- 离线数据采集,网络恢复后批量上传
|
|
|
|
|
|
- 实时消息推送,重要状态变更通知
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.1.3 司机小程序 (driver-mp) 详细功能
|
|
|
|
|
|
|
|
|
|
|
|
**核心业务流程:**
|
|
|
|
|
|
1. **任务接收确认**
|
|
|
|
|
|
- 任务推送:新运输任务通知
|
|
|
|
|
|
- 路线规划:最优运输路线建议
|
|
|
|
|
|
- 时间确认:预计装车和到达时间
|
|
|
|
|
|
- 车辆检查:车辆状态确认
|
|
|
|
|
|
|
|
|
|
|
|
2. **运输过程管理**
|
|
|
|
|
|
- 位置上报:自动每10分钟上报位置
|
|
|
|
|
|
- 状态记录:牛只状态视频记录
|
|
|
|
|
|
- 异常上报:运输途中问题及时上报
|
|
|
|
|
|
- 路线调整:实时路况避让建议
|
|
|
|
|
|
|
|
|
|
|
|
3. **到货交接流程**
|
|
|
|
|
|
- 到货通知:提前通知采购方预计到达时间
|
|
|
|
|
|
- 单据交接:运输单据电子签收
|
|
|
|
|
|
- 现场协调:卸车现场秩序维护
|
|
|
|
|
|
- 问题记录:交接过程问题记录
|
|
|
|
|
|
|
|
|
|
|
|
4. **紧急处理功能**
|
|
|
|
|
|
- 紧急求助:一键联系客服和支持
|
|
|
|
|
|
- 应急指南:常见问题处理流程
|
|
|
|
|
|
- 保险报案:事故快速报案通道
|
|
|
|
|
|
- 医疗救助:紧急医疗联系信息
|
|
|
|
|
|
|
|
|
|
|
|
**技术实现要点:**
|
|
|
|
|
|
- 后台持续定位服务,低功耗优化
|
|
|
|
|
|
- 离线地图数据缓存,无网络时可用
|
|
|
|
|
|
- 紧急情况一键求助功能
|
|
|
|
|
|
- 语音输入和命令支持,驾驶中便捷操作
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.1.4 内部员工小程序 (staff-mp) 详细功能
|
|
|
|
|
|
|
|
|
|
|
|
**核心业务流程:**
|
|
|
|
|
|
1. **全流程监控**
|
|
|
|
|
|
- 订单总览:所有订单状态Dashboard
|
|
|
|
|
|
- 实时跟踪:运输过程实时监控
|
|
|
|
|
|
- 异常预警:自动检测和预警异常情况
|
|
|
|
|
|
- 数据统计:关键业务指标实时展示
|
|
|
|
|
|
|
|
|
|
|
|
2. **运营管理**
|
|
|
|
|
|
- 用户管理:用户账号管理和权限分配
|
|
|
|
|
|
- 供应商管理:供应商资质审核和管理
|
|
|
|
|
|
- 司机管理:司机信息和绩效管理
|
|
|
|
|
|
- 参数配置:系统运行参数设置
|
|
|
|
|
|
|
|
|
|
|
|
3. **数据统计分析**
|
|
|
|
|
|
- 业务报表:多维度业务数据报表
|
|
|
|
|
|
- 绩效分析:各环节效率和质量分析
|
|
|
|
|
|
- 趋势预测:业务量趋势分析和预测
|
|
|
|
|
|
- 数据导出:Excel格式数据导出
|
|
|
|
|
|
|
|
|
|
|
|
4. **系统维护**
|
|
|
|
|
|
- 日志查看:系统操作日志审计
|
|
|
|
|
|
- 性能监控:系统运行状态监控
|
|
|
|
|
|
- 故障处理:问题排查和处理流程
|
|
|
|
|
|
- 数据备份:重要数据备份和恢复
|
|
|
|
|
|
|
|
|
|
|
|
**技术实现要点:**
|
|
|
|
|
|
- 数据可视化图表组件
|
|
|
|
|
|
- 实时数据推送和更新
|
|
|
|
|
|
- 多维度数据分析和筛选
|
|
|
|
|
|
- 权限精细控制,不同角色不同视图
|
|
|
|
|
|
|
|
|
|
|
|
### 13.2 小程序技术架构统一规范
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.2.1 开发规范
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 项目统一配置规范
|
|
|
|
|
|
const projectConfig = {
|
|
|
|
|
|
// 代码规范
|
|
|
|
|
|
codeStyle: {
|
|
|
|
|
|
indent: 2, // 缩进2个空格
|
|
|
|
|
|
semi: true, // 使用分号
|
|
|
|
|
|
singleQuote: true, // 使用单引号
|
|
|
|
|
|
trailingComma: 'es5' // 尾随逗号
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 目录结构规范
|
|
|
|
|
|
directoryStructure: {
|
|
|
|
|
|
components: 'src/components', // 组件目录
|
|
|
|
|
|
pages: 'src/pages', // 页面目录
|
|
|
|
|
|
stores: 'src/stores', // 状态管理
|
|
|
|
|
|
utils: 'src/utils', // 工具函数
|
|
|
|
|
|
types: 'src/types', // 类型定义
|
|
|
|
|
|
assets: 'src/assets' // 静态资源
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 命名规范
|
|
|
|
|
|
namingConvention: {
|
|
|
|
|
|
components: 'PascalCase', // 组件大驼峰
|
|
|
|
|
|
variables: 'camelCase', // 变量小驼峰
|
|
|
|
|
|
constants: 'UPPER_CASE', // 常量全大写
|
|
|
|
|
|
files: 'kebab-case' // 文件短横线
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.2.2 API调用规范
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 统一API请求封装
|
|
|
|
|
|
class ApiClient {
|
|
|
|
|
|
private baseURL: string;
|
|
|
|
|
|
private token: string | null;
|
|
|
|
|
|
|
|
|
|
|
|
constructor(baseURL: string) {
|
|
|
|
|
|
this.baseURL = baseURL;
|
|
|
|
|
|
this.token = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 统一请求方法
|
|
|
|
|
|
async request<T>(endpoint: string, options: RequestInit = {}): Promise<ApiResponse<T>> {
|
|
|
|
|
|
const url = `${this.baseURL}${endpoint}`;
|
|
|
|
|
|
const headers = {
|
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
|
'Authorization': this.token ? `Bearer ${this.token}` : '',
|
|
|
|
|
|
...options.headers,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await fetch(url, { ...options, headers });
|
|
|
|
|
|
const data = await response.json();
|
|
|
|
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
|
throw new ApiError(response.status, data.message || '请求失败');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
throw new ApiError(500, '网络请求失败');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 常用HTTP方法封装
|
|
|
|
|
|
get<T>(endpoint: string, params?: Record<string, any>) {
|
|
|
|
|
|
const queryString = params ? `?${new URLSearchParams(params)}` : '';
|
|
|
|
|
|
return this.request<T>(`${endpoint}${queryString}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
post<T>(endpoint: string, data?: any) {
|
|
|
|
|
|
return this.request<T>(endpoint, {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
body: JSON.stringify(data),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
put<T>(endpoint: string, data?: any) {
|
|
|
|
|
|
return this.request<T>(endpoint, {
|
|
|
|
|
|
method: 'PUT',
|
|
|
|
|
|
body: JSON.stringify(data),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
delete<T>(endpoint: string) {
|
|
|
|
|
|
return this.request<T>(endpoint, { method: 'DELETE' });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 统一错误处理
|
|
|
|
|
|
class ApiError extends Error {
|
|
|
|
|
|
constructor(public status: number, message: string) {
|
|
|
|
|
|
super(message);
|
|
|
|
|
|
this.name = 'ApiError';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.2.3 状态管理规范
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// Pinia状态管理规范
|
|
|
|
|
|
import { defineStore } from 'pinia';
|
|
|
|
|
|
import { ref, computed } from 'vue';
|
|
|
|
|
|
import type { Order } from '@/types/order';
|
|
|
|
|
|
|
|
|
|
|
|
export const useOrderStore = defineStore('order', () => {
|
|
|
|
|
|
// 状态定义
|
|
|
|
|
|
const orders = ref<Order[]>([]);
|
|
|
|
|
|
const currentOrder = ref<Order | null>(null);
|
|
|
|
|
|
const loading = ref(false);
|
|
|
|
|
|
const error = ref<string | null>(null);
|
|
|
|
|
|
|
|
|
|
|
|
// Getter计算属性
|
|
|
|
|
|
const pendingOrders = computed(() =>
|
|
|
|
|
|
orders.value.filter(order => order.status === 'pending')
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const completedOrders = computed(() =>
|
|
|
|
|
|
orders.value.filter(order => order.status === 'completed')
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// Action方法
|
|
|
|
|
|
const fetchOrders = async (params?: OrderQueryParams) => {
|
|
|
|
|
|
loading.value = true;
|
|
|
|
|
|
error.value = null;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await apiClient.get<Order[]>('/api/orders', params);
|
|
|
|
|
|
orders.value = response.data;
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
error.value = err instanceof Error ? err.message : '获取订单失败';
|
|
|
|
|
|
throw err;
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
loading.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const updateOrderStatus = async (orderId: number, status: OrderStatus) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await apiClient.put(`/api/orders/${orderId}/status`, { status });
|
|
|
|
|
|
const index = orders.value.findIndex(order => order.id === orderId);
|
|
|
|
|
|
|
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
|
orders.value[index] = { ...orders.value[index], status };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
error.value = err instanceof Error ? err.message : '更新订单状态失败';
|
|
|
|
|
|
throw err;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
// 状态
|
|
|
|
|
|
orders,
|
|
|
|
|
|
currentOrder,
|
|
|
|
|
|
loading,
|
|
|
|
|
|
error,
|
|
|
|
|
|
|
|
|
|
|
|
// Getter
|
|
|
|
|
|
pendingOrders,
|
|
|
|
|
|
completedOrders,
|
|
|
|
|
|
|
|
|
|
|
|
// Action
|
|
|
|
|
|
fetchOrders,
|
|
|
|
|
|
updateOrderStatus,
|
|
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 13.3 性能优化策略
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.3.1 前端性能优化
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 图片懒加载优化
|
|
|
|
|
|
const useLazyLoad = () => {
|
|
|
|
|
|
const observer = ref<IntersectionObserver | null>(null);
|
|
|
|
|
|
const observedElements = ref(new Set<Element>());
|
|
|
|
|
|
|
|
|
|
|
|
const initLazyLoad = (container: HTMLElement | null) => {
|
|
|
|
|
|
if (!container) return;
|
|
|
|
|
|
|
|
|
|
|
|
observer.value = new IntersectionObserver((entries) => {
|
|
|
|
|
|
entries.forEach((entry) => {
|
|
|
|
|
|
if (entry.isIntersecting) {
|
|
|
|
|
|
const img = entry.target as HTMLImageElement;
|
|
|
|
|
|
const src = img.dataset.src;
|
|
|
|
|
|
|
|
|
|
|
|
if (src) {
|
|
|
|
|
|
img.src = src;
|
|
|
|
|
|
img.removeAttribute('data-src');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
observer.value?.unobserve(img);
|
|
|
|
|
|
observedElements.value.delete(img);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}, { threshold: 0.1 });
|
|
|
|
|
|
|
|
|
|
|
|
// 观察容器内的所有图片
|
|
|
|
|
|
const images = container.querySelectorAll('img[data-src]');
|
|
|
|
|
|
images.forEach((img) => {
|
|
|
|
|
|
observer.value?.observe(img);
|
|
|
|
|
|
observedElements.value.add(img);
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const destroy = () => {
|
|
|
|
|
|
observedElements.value.forEach((el) => {
|
|
|
|
|
|
observer.value?.unobserve(el);
|
|
|
|
|
|
});
|
|
|
|
|
|
observedElements.value.clear();
|
|
|
|
|
|
observer.value?.disconnect();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return { initLazyLoad, destroy };
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 数据缓存策略
|
|
|
|
|
|
const useCache = <T>() => {
|
|
|
|
|
|
const cache = ref(new Map<string, { data: T; timestamp: number }>());
|
|
|
|
|
|
const CACHE_DURATION = 5 * 60 * 1000; // 5分钟
|
|
|
|
|
|
|
|
|
|
|
|
const get = (key: string): T | null => {
|
|
|
|
|
|
const item = cache.value.get(key);
|
|
|
|
|
|
if (!item) return null;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查缓存是否过期
|
|
|
|
|
|
if (Date.now() - item.timestamp > CACHE_DURATION) {
|
|
|
|
|
|
cache.value.delete(key);
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return item.data;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const set = (key: string, data: T) => {
|
|
|
|
|
|
cache.value.set(key, { data, timestamp: Date.now() });
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const clear = (key?: string) => {
|
|
|
|
|
|
if (key) {
|
|
|
|
|
|
cache.value.delete(key);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
cache.value.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return { get, set, clear };
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.3.2 网络请求优化
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 请求防抖和节流
|
|
|
|
|
|
const useRequestOptimization = () => {
|
|
|
|
|
|
const pendingRequests = ref(new Map<string, Promise<any>>());
|
|
|
|
|
|
const debounceTimers = ref(new Map<string, NodeJS.Timeout>());
|
|
|
|
|
|
|
|
|
|
|
|
// 请求去重
|
|
|
|
|
|
const dedupeRequest = <T>(key: string, request: () => Promise<T>): Promise<T> => {
|
|
|
|
|
|
if (pendingRequests.value.has(key)) {
|
|
|
|
|
|
return pendingRequests.value.get(key)!;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const promise = request().finally(() => {
|
|
|
|
|
|
pendingRequests.value.delete(key);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
pendingRequests.value.set(key, promise);
|
|
|
|
|
|
return promise;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 防抖请求
|
|
|
|
|
|
const debounceRequest = <T>(
|
|
|
|
|
|
key: string,
|
|
|
|
|
|
request: () => Promise<T>,
|
|
|
|
|
|
delay: number = 300
|
|
|
|
|
|
): Promise<T> => {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
if (debounceTimers.value.has(key)) {
|
|
|
|
|
|
clearTimeout(debounceTimers.value.get(key));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const timer = setTimeout(async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const result = await request();
|
|
|
|
|
|
resolve(result);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
reject(error);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
debounceTimers.value.delete(key);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, delay);
|
|
|
|
|
|
|
|
|
|
|
|
debounceTimers.value.set(key, timer);
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 批量请求
|
|
|
|
|
|
const batchRequests = async <T>(
|
|
|
|
|
|
requests: Array<() => Promise<T>>,
|
|
|
|
|
|
batchSize: number = 5
|
|
|
|
|
|
): Promise<T[]> => {
|
|
|
|
|
|
const results: T[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < requests.length; i += batchSize) {
|
|
|
|
|
|
const batch = requests.slice(i, i + batchSize);
|
|
|
|
|
|
const batchResults = await Promise.all(batch.map(req => req()));
|
|
|
|
|
|
results.push(...batchResults);
|
|
|
|
|
|
|
|
|
|
|
|
// 添加延迟避免请求过于频繁
|
|
|
|
|
|
if (i + batchSize < requests.length) {
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return results;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return { dedupeRequest, debounceRequest, batchRequests };
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 13.4 安全设计与隐私保护
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.4.1 数据安全策略
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 敏感数据加密处理
|
|
|
|
|
|
const useDataEncryption = () => {
|
|
|
|
|
|
const encryptData = (data: any, key: string): string => {
|
|
|
|
|
|
// 简单的加密实现,实际项目中使用更安全的加密算法
|
|
|
|
|
|
const jsonStr = JSON.stringify(data);
|
|
|
|
|
|
const encoded = btoa(unescape(encodeURIComponent(jsonStr)));
|
|
|
|
|
|
return `encrypted:${encoded}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const decryptData = (encryptedData: string, key: string): any => {
|
|
|
|
|
|
if (!encryptedData.startsWith('encrypted:')) {
|
|
|
|
|
|
throw new Error('Invalid encrypted data format');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const encoded = encryptedData.slice(10);
|
|
|
|
|
|
const jsonStr = decodeURIComponent(escape(atob(encoded)));
|
|
|
|
|
|
return JSON.parse(jsonStr);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 本地存储加密
|
|
|
|
|
|
const setEncryptedStorage = (key: string, data: any) => {
|
|
|
|
|
|
const encrypted = encryptData(data, 'storage-key');
|
|
|
|
|
|
uni.setStorageSync(key, encrypted);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const getEncryptedStorage = (key: string): any => {
|
|
|
|
|
|
const encrypted = uni.getStorageSync(key);
|
|
|
|
|
|
if (!encrypted) return null;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
return decryptData(encrypted, 'storage-key');
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return { encryptData, decryptData, setEncryptedStorage, getEncryptedStorage };
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 权限验证中间件
|
|
|
|
|
|
const useAuthMiddleware = () => {
|
|
|
|
|
|
const checkPermission = (requiredPermissions: string[]): boolean => {
|
|
|
|
|
|
const userPermissions = useUserStore().permissions;
|
|
|
|
|
|
return requiredPermissions.every(perm => userPermissions.includes(perm));
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const routeGuard = (to: any, from: any, next: any) => {
|
|
|
|
|
|
const requiredPermissions = to.meta?.permissions || [];
|
|
|
|
|
|
|
|
|
|
|
|
if (requiredPermissions.length > 0 && !checkPermission(requiredPermissions)) {
|
|
|
|
|
|
next({ path: '/403' }); // 无权限页面
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
next();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return { checkPermission, routeGuard };
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.4.2 隐私保护措施
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 用户数据脱敏处理
|
|
|
|
|
|
const useDataMasking = () => {
|
|
|
|
|
|
const maskPhone = (phone: string): string => {
|
|
|
|
|
|
if (!phone || phone.length < 7) return phone;
|
|
|
|
|
|
return `${phone.slice(0, 3)}****${phone.slice(-4)}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const maskIdCard = (idCard: string): string => {
|
|
|
|
|
|
if (!idCard || idCard.length < 15) return idCard;
|
|
|
|
|
|
return `${idCard.slice(0, 6)}********${idCard.slice(-4)}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const maskBankCard = (bankCard: string): string => {
|
|
|
|
|
|
if (!bankCard || bankCard.length < 12) return bankCard;
|
|
|
|
|
|
return `**** **** **** ${bankCard.slice(-4)}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const maskEmail = (email: string): string => {
|
|
|
|
|
|
if (!email || !email.includes('@')) return email;
|
|
|
|
|
|
|
|
|
|
|
|
const [name, domain] = email.split('@');
|
|
|
|
|
|
if (name.length <= 2) return email;
|
|
|
|
|
|
|
|
|
|
|
|
const maskedName = `${name.slice(0, 2)}***`;
|
|
|
|
|
|
return `${maskedName}@${domain}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return { maskPhone, maskIdCard, maskBankCard, maskEmail };
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 数据收集合规性检查
|
|
|
|
|
|
const usePrivacyCompliance = () => {
|
|
|
|
|
|
const checkDataCollection = (purpose: string, dataTypes: string[]): boolean => {
|
|
|
|
|
|
// 检查数据收集是否符合隐私政策
|
|
|
|
|
|
const allowedPurposes = ['order_processing', 'shipping', 'payment'];
|
|
|
|
|
|
const sensitiveDataTypes = ['phone', 'id_card', 'bank_card'];
|
|
|
|
|
|
|
|
|
|
|
|
if (!allowedPurposes.includes(purpose)) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 敏感数据类型需要额外授权
|
|
|
|
|
|
const hasSensitiveData = dataTypes.some(type => sensitiveDataTypes.includes(type));
|
|
|
|
|
|
if (hasSensitiveData) {
|
|
|
|
|
|
const consent = useUserStore().privacyConsent;
|
|
|
|
|
|
return consent?.sensitiveData === true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const getDataRetentionPeriod = (dataType: string): number => {
|
|
|
|
|
|
// 根据数据类型返回保留期限(天)
|
|
|
|
|
|
const retentionPeriods: Record<string, number> = {
|
|
|
|
|
|
'order_data': 365 * 3, // 3年
|
|
|
|
|
|
'user_profile': 365 * 1, // 1年
|
|
|
|
|
|
'log_data': 30, // 30天
|
|
|
|
|
|
'temp_data': 7, // 7天
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return retentionPeriods[dataType] || 30;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return { checkDataCollection, getDataRetentionPeriod };
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 13.5 测试与质量保证
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.5.1 自动化测试策略
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 单元测试示例
|
|
|
|
|
|
describe('Order Utilities', () => {
|
|
|
|
|
|
test('calculateOrderAmount should return correct amount', () => {
|
|
|
|
|
|
const order = {
|
|
|
|
|
|
cattleCount: 10,
|
|
|
|
|
|
unitPrice: 25000,
|
|
|
|
|
|
expectedWeight: 5000
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const amount = calculateOrderAmount(order);
|
|
|
|
|
|
expect(amount).toBe(250000); // 10 * 25000
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('validateOrder should reject invalid data', () => {
|
|
|
|
|
|
const invalidOrder = {
|
|
|
|
|
|
cattleCount: 0, // 数量不能为0
|
|
|
|
|
|
unitPrice: -100 // 单价不能为负数
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
expect(() => validateOrder(invalidOrder)).toThrow();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 组件测试示例
|
|
|
|
|
|
describe('OrderCard Component', () => {
|
|
|
|
|
|
test('renders order information correctly', () => {
|
|
|
|
|
|
const order = {
|
|
|
|
|
|
orderNo: 'ORDER123',
|
|
|
|
|
|
cattleBreed: '西门塔尔',
|
|
|
|
|
|
cattleCount: 50,
|
|
|
|
|
|
status: 'pending'
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const wrapper = mount(OrderCard, { props: { order } });
|
|
|
|
|
|
|
|
|
|
|
|
expect(wrapper.find('.order-no').text()).toBe('ORDER123');
|
|
|
|
|
|
expect(wrapper.find('.breed').text()).toBe('西门塔尔');
|
|
|
|
|
|
expect(wrapper.find('.status').text()).toBe('待确认');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('emits view-detail event on button click', async () => {
|
|
|
|
|
|
const wrapper = mount(OrderCard, {
|
|
|
|
|
|
props: { order: mockOrder, showActions: true }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
await wrapper.find('.view-detail-btn').trigger('click');
|
|
|
|
|
|
expect(wrapper.emitted('view-detail')).toBeTruthy();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// E2E测试示例
|
|
|
|
|
|
describe('Order Creation Flow', () => {
|
|
|
|
|
|
test('should create order successfully', async () => {
|
|
|
|
|
|
// 登录
|
|
|
|
|
|
await page.goto('/login');
|
|
|
|
|
|
await page.fill('#username', 'testuser');
|
|
|
|
|
|
await page.fill('#password', 'password123');
|
|
|
|
|
|
await page.click('#login-btn');
|
|
|
|
|
|
|
|
|
|
|
|
// 创建订单
|
|
|
|
|
|
await page.click('#create-order');
|
|
|
|
|
|
await page.select('#cattle-breed', '西门塔尔');
|
|
|
|
|
|
await page.fill('#cattle-count', '50');
|
|
|
|
|
|
await page.fill('#expected-weight', '25000');
|
|
|
|
|
|
await page.click('#submit-btn');
|
|
|
|
|
|
|
|
|
|
|
|
// 验证结果
|
|
|
|
|
|
await expect(page).toHaveText('订单创建成功');
|
|
|
|
|
|
await expect(page).toHaveText('待确认');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 13.5.2 性能测试指标
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 性能监控配置
|
|
|
|
|
|
const performanceMetrics = {
|
|
|
|
|
|
// 加载性能
|
|
|
|
|
|
loading: {
|
|
|
|
|
|
firstContentfulPaint: 1500, // FCP < 1.5s
|
|
|
|
|
|
largestContentfulPaint: 2500, // LCP < 2.5s
|
|
|
|
|
|
timeToInteractive: 3500, // TTI < 3.5s
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 交互性能
|
|
|
|
|
|
interaction: {
|
|
|
|
|
|
firstInputDelay: 100, // FID < 100ms
|
|
|
|
|
|
cumulativeLayoutShift: 0.1, // CLS < 0.1
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 资源性能
|
|
|
|
|
|
resources: {
|
|
|
|
|
|
bundleSize: 2000, // 主包大小 < 2MB
|
|
|
|
|
|
imageSize: 500, // 图片平均大小 < 500KB
|
|
|
|
|
|
requestCount: 30, // 页面请求数 < 30
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 内存性能
|
|
|
|
|
|
memory: {
|
|
|
|
|
|
heapSize: 50, // 堆内存 < 50MB
|
|
|
|
|
|
jsHeapSize: 30, // JS堆内存 < 30MB
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 性能监控实现
|
|
|
|
|
|
const usePerformanceMonitor = () => {
|
|
|
|
|
|
const metrics = ref(new Map<string, number>());
|
|
|
|
|
|
|
|
|
|
|
|
const startMonitoring = () => {
|
|
|
|
|
|
// 监听性能指标
|
|
|
|
|
|
if ('PerformanceObserver' in window) {
|
|
|
|
|
|
const observer = new PerformanceObserver((list) => {
|
|
|
|
|
|
list.getEntries().forEach((entry) => {
|
|
|
|
|
|
metrics.value.set(entry.name, entry.value);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
observer.observe({ entryTypes: ['paint', 'largest-contentful-paint', 'layout-shift'] });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 监听内存使用
|
|
|
|
|
|
if ('memory' in performance) {
|
|
|
|
|
|
setInterval(() => {
|
|
|
|
|
|
const memory = (performance as any).memory;
|
|
|
|
|
|
if (memory) {
|
|
|
|
|
|
metrics.value.set('jsHeapSize', memory.usedJSHeapSize / 1024 / 1024);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 5000);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const reportMetrics = async () => {
|
|
|
|
|
|
const reportData = Object.fromEntries(metrics.value);
|
|
|
|
|
|
await apiClient.post('/api/performance/metrics', reportData);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return { startMonitoring, reportMetrics, metrics };
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 14. 扩展性与未来规划
|
|
|
|
|
|
|
|
|
|
|
|
### 14.1 系统扩展性设计
|
2025-09-11 19:55:21 +08:00
|
|
|
|
- 模块化设计,便于功能扩展
|
|
|
|
|
|
- API标准化,便于集成第三方系统
|
|
|
|
|
|
- 数据库分库分表策略预留
|
|
|
|
|
|
- 微服务架构转型路径
|
|
|
|
|
|
|
2025-09-18 08:55:32 +08:00
|
|
|
|
### 14.2 未来功能规划
|
2025-09-11 19:55:21 +08:00
|
|
|
|
- 数据分析与报表功能增强
|
|
|
|
|
|
- AI辅助决策系统
|
|
|
|
|
|
- 区块链追溯系统集成
|
|
|
|
|
|
- 物联网设备接入
|
|
|
|
|
|
- 国际业务支持与多语言功能
|