enterprise-saa-s-dashboard-.../DEMO_GUIDE.md

405 lines
13 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 授权文件功能演示说明
## 📸 功能界面说明
由于这是文本环境,以下用文字描述各功能的界面和操作流程。
## 1. 授权管理主页面
**访问路径**: http://localhost:3000/licenses
### 页面布局
```
┌─────────────────────────────────────────────────────────────┐
│ ← 授权管理 [导出] [选择授权项] │
│ 管理设备授权许可 │
├─────────────────────────────────────────────────────────────┤
每个设备型号对应一套授权模块配置... │
├─────────────────────────────────────────────────────────────┤
│ 筛选条件: [设备型号▼] [查询] │
├─────────────────────────────────────────────────────────────┤
│ 设备型号 | 授权模块 | 操作 │
│ GD-30 | [一维] [二维] [三维] | [预览] [下载] [编辑] │
│ GD-20 | [一维] [二维] | [预览] [下载] [编辑] │
├─────────────────────────────────────────────────────────────┤
│ 共 2 条 [<] [1] [2] [>] │
└─────────────────────────────────────────────────────────────┘
```
### 操作按钮说明
- **预览** 👁️ - 点击后弹出JSON预览窗口
- **下载** 📄 - 直接下载JSON文件到本地
- **编辑** ✏️ - 修改授权配置
## 2. 授权文件预览弹窗
### 触发方式
点击列表中的"预览"按钮
### 弹窗内容
```
┌──────────────────────────────────────────────────────────┐
│ 授权文件预览 - GD-30 [X] │
├──────────────────────────────────────────────────────────┤
│ { │
│ "version": "1.0", │
│ "generatedAt": "2026-04-30T16:00:00.000Z", │
│ "deviceModel": "GD-30 Supreme", │
│ "deviceSN": "", │
│ "validUntil": "2027-04-30", │
│ "status": "active", │
│ "authModules": [ │
│ { │
│ "id": "1D", │
│ "name": "一维自电/电阻率/激电测试模块", │
│ "category": "一维", │
│ "enabled": true │
│ }, │
│ ... │
│ ], │
│ "config": { │
│ "name": "CFG-GD30-v2.1", │
│ "emissionParams": {...}, │
│ "acquisitionParams": {...} │
│ }, │
│ "signature": { │
│ "algorithm": "SHA256", │
│ "value": "a1b2c3d4...", │
│ "publicKey": "platform-public-key-placeholder" │
│ } │
│ } │
├──────────────────────────────────────────────────────────┤
│ [下载JSON] [关闭] │
└──────────────────────────────────────────────────────────┘
```
### 功能特点
- JSON格式化显示带语法高亮
- 可滚动查看完整内容
- 支持一键下载JSON文件
- 点击背景或关闭按钮退出
## 3. 创建/编辑授权抽屉
### 触发方式
点击"选择授权项"按钮
### 抽屉内容
```
┌──────────────────────────────────────┐
│ 选择授权项 [X] │
├──────────────────────────────────────┤
│ 设备型号 │
│ [GD-30 Supreme ▼] │
│ │
│ 授权项目 [全选] [清空]│
│ ┌──────────────────────────────────┐ │
│ │ ☑ 分类 │ 名称 │ 说明 │ │
│ ├──────────────────────────────────┤ │
│ │ ☑ 一维 │ 一维自电... │ ... │ │
│ │ ☑ 二维 │ 二维自电... │ ... │ │
│ │ ☑ 三维 │ 三维自电... │ ... │ │
│ │ □ 水上 │ 水上... │ ... │ │
│ │ □ 跨孔 │ 跨孔... │ ... │ │
│ │ □ 电流场法│ 电流场法... │ ... │ │
│ └──────────────────────────────────┘ │
│ │
│ 已选择 3 项 │
│ │
授权文件由选定的授权项与对应型号的 │
│ 配置文件共同生成... │
│ │
│ [保存] │
└──────────────────────────────────────┘
```
### 交互说明
- 点击行可选中/取消选中
- 支持全选/清空快捷操作
- 保存时自动生成JSON授权文件
## 4. 手机APP调用流程演示
### 场景:设备启动时获取授权
#### Step 1: APP发起请求
```javascript
GET /api/licenses/download?sn=GD30-20260430-001
```
#### Step 2: 平台处理流程
```
接收请求
验证设备SN是否存在
查找设备级授权 (device_sn匹配)
↓ 未找到
查找型号级授权 (model匹配 + 状态生效 + 未过期)
获取关联的配置文件
生成/读取授权文件JSON
记录下载日志 (时间、IP、APP版本)
返回JSON响应
```
#### Step 3: APP接收响应
```json
{
"version": "1.0",
"deviceModel": "GD-30 Supreme",
"deviceSN": "GD30-20260430-001",
"validUntil": "2027-04-30",
"status": "active",
"authModules": [
{"id": "1D", "name": "...", "enabled": true},
{"id": "2D", "name": "...", "enabled": true},
{"id": "3D", "name": "...", "enabled": true}
],
"config": {
"emissionParams": {"maxVoltage": "1000V", ...},
"acquisitionParams": {"channels": 12, ...}
},
"signature": {...}
}
```
#### Step 4: APP处理授权
```javascript
// 1. 验证签名
if (!verifySignature(license)) {
throw new Error('授权文件被篡改');
}
// 2. 检查有效期
if (new Date(license.validUntil) < new Date()) {
throw new Error('授权已过期');
}
// 3. 启用功能模块
license.authModules.forEach(module => {
if (module.enabled) {
app.enableFeature(module.id);
}
});
// 4. 应用配置参数
app.applyConfig(license.config);
// 5. 显示授权信息
console.log(`授权有效期至: ${license.validUntil}`);
```
## 5. 数据库查询演示
### 查看授权记录
```sql
SELECT id, model, modules, expiry, status,
CASE WHEN license_file IS NOT NULL THEN '已生成' ELSE '未生成' END as file_status
FROM licenses
ORDER BY id DESC;
```
**示例输出:**
```
id | model | modules | expiry | status | file_status
1 | GD-30 | 一维, 二维, 三维| 2027-04-30 | 生效 | 已生成
2 | GD-20 | 一维, 二维 | 2027-04-30 | 生效 | 已生成
```
### 查看下载日志
```sql
SELECT l.device_sn, l.download_time, l.ip_address,
lic.model, lic.expiry
FROM license_download_logs l
JOIN licenses lic ON l.license_id = lic.id
ORDER BY l.download_time DESC
LIMIT 10;
```
**示例输出:**
```
device_sn | download_time | ip_address | model | expiry
GD30-20260430-001 | 2026-04-30 16:30:00 | 192.168.1.100 | GD-30 | 2027-04-30
GD30-20260430-002 | 2026-04-30 16:25:00 | 192.168.1.101 | GD-30 | 2027-04-30
```
## 6. 错误场景演示
### 场景A: 设备不存在
```bash
curl "http://localhost:3000/api/licenses/download?sn=INVALID-SN"
```
**响应:**
```json
{
"error": "设备不存在"
}
```
**HTTP状态码:** 404
### 场景B: 无有效授权
```bash
curl "http://localhost:3000/api/licenses/download?sn=GD30-NO-LICENSE"
```
**响应:**
```json
{
"error": "该设备暂无有效授权",
"deviceSN": "GD30-NO-LICENSE",
"deviceModel": "GD-30 Supreme"
}
```
**HTTP状态码:** 404
### 场景C: 缺少SN参数
```bash
curl "http://localhost:3000/api/licenses/download"
```
**响应:**
```json
{
"error": "设备SN不能为空"
}
```
**HTTP状态码:** 400
## 7. 性能测试演示
### 测试工具: Apache Bench (ab)
```bash
# 模拟100个并发请求总共1000次请求
ab -n 1000 -c 100 "http://localhost:3000/api/licenses/download?sn=GD30-TEST-001"
```
**预期结果:**
```
Requests per second: 500.00 [#/sec] (mean)
Time per request: 200.000 [ms] (mean)
Time per request: 2.000 [ms] (mean, across all concurrent requests)
```
### 优化建议
1. 首次生成后缓存到数据库,避免重复计算
2. 为licenses表添加索引
```sql
CREATE INDEX idx_license_device_sn ON licenses(device_sn);
CREATE INDEX idx_license_model ON licenses(model, status, expiry);
```
3. 生产环境使用Redis缓存热点授权
## 8. 安全测试演示
### 测试签名验证
```javascript
// 正常授权文件
const validLicense = await fetchLicense('GD30-TEST-001');
console.log(verifySignature(validLicense)); // true
// 篡改后的授权文件
const tamperedLicense = {...validLicense, validUntil: '2099-12-31'};
console.log(verifySignature(tamperedLicense)); // false
```
### 测试SQL注入防护
```bash
# 尝试SQL注入
curl "http://localhost:3000/api/licenses/download?sn='; DROP TABLE devices; --"
```
**结果:**
- 使用参数化查询SQL注入无效
- 返回"设备不存在"错误
## 9. 移动端适配说明
### iOS App (Swift)
```swift
func fetchLicense(deviceSN: String, completion: @escaping (Result<License, Error>) -> Void) {
let url = URL(string: "http://your-server.com/api/licenses/download?sn=\(deviceSN)")!
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let data = data,
let license = try? JSONDecoder().decode(License.self, from: data) else {
completion(.failure(NSError(domain: "Invalid response", code: -1)))
return
}
completion(.success(license))
}.resume()
}
```
### Android App (Kotlin)
```kotlin
suspend fun fetchLicense(deviceSN: String): License {
val response = httpClient.get("http://your-server.com/api/licenses/download?sn=$deviceSN")
if (!response.isSuccess) {
throw IOException("Failed to fetch license")
}
return response.body()
}
```
## 10. 监控和告警
### 关键指标监控
1. **API响应时间**
- P95 < 500ms
- P99 < 1000ms
2. **错误率**
- 4xx错误 < 5%
- 5xx错误 < 1%
3. **下载次数统计**
- 每日下载总量
- 按设备型号分组统计
- 异常下载频率检测
### 告警规则
```yaml
alerts:
- name: high_error_rate
condition: error_rate > 5%
duration: 5m
action: send_notification
- name: slow_response
condition: p95_latency > 1000ms
duration: 10m
action: send_notification
- name: unusual_download_pattern
condition: downloads_per_minute > 100
duration: 2m
action: send_notification_and_block_ip
```
---
**提示**: 实际使用时可以配合截图工具如SnipasteGreenshot截取各个界面的实际效果添加到文档中以便更直观地展示功能