# 七牛云区域配置修复说明

## 问题描述

上传文件到七牛云时出现区域错误：

```
xhr request failed, code: 400
response: {"error":"incorrect region, please use up-z2.qiniup.com, bucket is: yunzerwebsite"}
```

## 问题原因

前端代码中硬编码了七牛云区域为 `z0`（华东），但实际数据库配置的是 `z2`（华南）：

```javascript
// 错误的硬编码方式
const config = {
  useCdnDomain: true,
  region: qiniu.region.z0,  // ❌ 硬编码为华东
};
```

数据库实际配置：
- `qiniu_region = 'z2'` (华南)
- `qiniu_bucket = 'yunzerwebsite'`

## 解决方案

### 1. 添加区域映射函数

在 `platform/src/utils/qiniuUpload.js` 文件末尾添加了 `getQiniuRegion()` 函数：

```javascript
/**
 * 根据区域代码获取七牛云区域对象
 * @param {string} regionCode 区域代码 (z0, z1, z2, na0, as0, cn-east-2)
 * @returns {Object} 七牛云区域对象
 */
function getQiniuRegion(regionCode) {
  switch (regionCode) {
    case 'z0':
      return qiniu.region.z0; // 华东
    case 'z1':
      return qiniu.region.z1; // 华北
    case 'z2':
      return qiniu.region.z2; // 华南
    case 'na0':
      return qiniu.region.na0; // 北美
    case 'as0':
      return qiniu.region.as0; // 新加坡
    case 'cn-east-2':
      return qiniu.region.cnEast2; // 华东-浙江2
    default:
      return qiniu.region.z0; // 默认华东
  }
}
```

### 2. 动态获取区域配置

修改 `uploadToQiniu()` 函数，从后端返回的数据中读取区域配置：

```javascript
export async function uploadToQiniu(file, options = {}) {
  // 1. 获取上传凭证（包含区域信息）
  const tokenRes = await getQiniuToken();
  const { token, keyPrefix, domain, region, uploadUrl } = tokenRes.data;
  
  // 2. 根据后端返回的区域代码动态获取区域对象
  const qiniuRegion = getQiniuRegion(region);  // ✓ 动态获取
  
  const config = {
    useCdnDomain: true,
    region: qiniuRegion,  // ✓ 使用正确的区域
  };
  
  // 3. 上传文件
  const observable = qiniu.upload(file, key, token, putExtra, config);
  // ...
}
```

## 工作流程

```
1. 前端调用 getQiniuToken()
   ↓
2. 后端从数据库读取配置
   - storage_type: 'qiniu'
   - qiniu_region: 'z2'
   - qiniu_bucket: 'yunzerwebsite'
   ↓
3. 后端返回配置信息
   {
     token: "...",
     region: "z2",  ← 区域代码
     bucket: "yunzerwebsite",
     uploadUrl: "https://up-z2.qiniup.com"
   }
   ↓
4. 前端调用 getQiniuRegion('z2')
   返回: qiniu.region.z2
   ↓
5. 使用正确的区域上传文件
   上传地址: https://up-z2.qiniup.com
```

## 支持的区域

| 区域代码 | 区域名称 | qiniu-js 对象 | 上传地址 |
|---------|---------|--------------|---------|
| z0 | 华东 | qiniu.region.z0 | https://up-z0.qiniup.com |
| z1 | 华北 | qiniu.region.z1 | https://up-z1.qiniup.com |
| z2 | 华南 | qiniu.region.z2 | https://up-z2.qiniup.com |
| na0 | 北美 | qiniu.region.na0 | https://up-na0.qiniup.com |
| as0 | 新加坡 | qiniu.region.as0 | https://up-as0.qiniup.com |
| cn-east-2 | 华东-浙江2 | qiniu.region.cnEast2 | https://up-cn-east-2.qiniup.com |

## 验证步骤

### 1. 确认依赖已安装

```bash
cd platform
npm list qiniu-js
```

预期输出：
```
qiniu-js@3.4.4
```

✓ 已确认：`qiniu-js@^3.4.4` 已在 `package.json` 中

### 2. 重启后端服务

```bash
systemctl restart go-api
systemctl status go-api
```

### 3. 测试上传

1. 登录系统
2. 进入软件升级页面
3. 上传一个文件
4. 观察是否成功

### 4. 检查日志

```bash
# 后端日志
tail -f /www/wwwroot/api.yunzer.cn/go.log

# 前端控制台
# 打开浏览器开发者工具，查看 Network 标签
```

预期请求：
```
GET /platform/storage/config
→ { storageType: 'qiniu', qiniuRegion: 'z2' }

GET /platform/qiniu/token
→ { token: '...', region: 'z2', uploadUrl: 'https://up-z2.qiniup.com' }

POST https://up-z2.qiniup.com  ← 直接上传到七牛云
→ { key: '...', hash: '...', size: ... }

POST /platform/qiniu/save
→ { url: 'http://7colud.yunzer.cn/...', id: 123 }
```

## 修复的文件

### 前端
- `platform/src/utils/qiniuUpload.js`
  - 添加了 `getQiniuRegion()` 函数
  - 修改了 `uploadToQiniu()` 函数，使用动态区域配置

### 后端
- `go/controllers/qiniu_upload.go`
  - `GetUploadToken()` 方法返回 `region` 字段
  - `getQiniuUploadURL()` 函数根据区域返回正确的上传地址

## 优势

### 1. 灵活性
- 支持所有七牛云区域
- 无需修改代码即可切换区域
- 只需在数据库中修改配置

### 2. 可维护性
- 区域配置集中管理
- 代码更清晰易懂
- 便于扩展新区域

### 3. 正确性
- 自动使用正确的上传地址
- 避免区域不匹配错误
- 提高上传成功率

## 切换区域方法

如果需要切换到其他区域，只需修改数据库配置：

```sql
-- 切换到华东 (z0)
UPDATE system_storage_config 
SET qiniu_region = 'z0' 
WHERE id = 1;

-- 切换到华北 (z1)
UPDATE system_storage_config 
SET qiniu_region = 'z1' 
WHERE id = 1;

-- 切换到华南 (z2) - 当前配置
UPDATE system_storage_config 
SET qiniu_region = 'z2' 
WHERE id = 1;
```

前端会自动使用新的区域配置，无需重启或修改代码。

## 相关文档

- [七牛云直传配置说明](./七牛云直传配置.md)
- [七牛云上传测试步骤](./七牛云上传测试步骤.md)
- [七牛云官方文档 - 存储区域](https://developer.qiniu.com/kodo/1671/region-endpoint-fq)

## 更新日期

2026-04-09

## 状态

✅ 已完成
- 添加 `getQiniuRegion()` 函数
- 修改 `uploadToQiniu()` 使用动态区域
- 验证 `qiniu-js` 依赖已安装
- 创建测试文档

⏭️ 下一步
- 重启后端服务
- 测试文件上传功能
- 验证区域配置正确
