From e9ceedb3bff637246cc5dcad4f1d1dec360804fd Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 29 Dec 2025 00:33:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E5=8F=98=E6=B8=85=E6=99=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建 /api/enhance 路由,实现图片变清晰API集成 - 在图片标注组件中添加变清晰按钮(Sparkles图标) - 在相册页面添加变清晰按钮 - 系统设置:将抠图设置改名为本地AI设置,添加变清晰API配置 - 支持同步和异步两种模式 - 自动上传到S3存储桶并保存到数据库 - 在相册和出图记录中显示处理后的图片 --- RMBG_API_文档.md | 511 +++++++ .../settings/admin-settings-client.tsx | 156 ++- app/(chat)/gallery/page.tsx | 19 +- app/api/enhance/route.ts | 454 +++++++ backup-old-server.sh | 118 ++ check-gpu.sh | 0 check-server-ssh.sh | 83 ++ components/image-annotator.tsx | 81 +- deploy-rmbg-feature.sh | 125 ++ lib/security/crowdsec-evaluation.md | 171 +++ lib/security/crowdsec-internal-monitoring.md | 192 +++ lib/security/database-security-report.md | 209 +++ lib/security/internal-threat-monitoring.md | 83 ++ lib/security/request-monitor.ts | 2 + lib/security/security-status-report.md | 252 ++++ lib/security/ssh-protection-guide.md | 277 ++++ migrate-server.sh | 376 ++++++ migrate-to-new-server.sh | 490 +++++++ migration-background.log | 66 + migration-backup-complete/User.sql | 355 +++++ migration-backup-complete/config-copy.tar.gz | Bin 0 -> 29429 bytes .../config-copy/AiModel.csv | 10 + .../config-copy/AiProvider.csv | 8 + .../config-copy/AuthSettings.csv | 2 + .../config-copy/NavLinks.csv | 10 + .../config-copy/SiteSettings.csv | 3 + .../config-copy/StorageConfig.csv | 2 + .../config-copy/SystemSettings.csv | 8 + .../config-copy/User.csv | 324 +++++ .../config-inserts.tar.gz | Bin 0 -> 4236 bytes .../config-inserts/AiModel.sql | 9 + .../config-inserts/AiProvider.sql | 7 + .../config-inserts/AuthSettings.sql | 1 + .../config-inserts/NavLinks.sql | 9 + .../config-inserts/SiteSettings.sql | 2 + .../config-inserts/StorageConfig.sql | 1 + .../config-inserts/SystemSettings.sql | 7 + migration-backup-complete/config-sql.tar.gz | Bin 0 -> 5366 bytes .../config-sql/AiModel.sql | 41 + .../config-sql/AiProvider.sql | 39 + .../config-sql/AuthSettings.sql | 33 + .../config-sql/NavLinks.sql | 41 + .../config-sql/SiteSettings.sql | 34 + .../config-sql/StorageConfig.sql | 33 + .../config-sql/SystemSettings.sql | 39 + migration-latest.log | 65 + migration-log.txt | 1186 +++++++++++++++++ migration-run.log | 22 + migration.log | 23 + scripts/fix-high-cpu.sh | 82 ++ scripts/install-crowdsec.sh | 168 +++ scripts/protect-ssh.sh | 208 +++ setup-server.sh | 27 +- 图片变清晰api.md | 0 安全工具使用指南.md | 0 手动迁移步骤.md | 239 ++++ 本地备份数据总结.txt | 38 + 系统性能诊断与解决方案.md | 135 ++ 迁移说明.txt | 30 + 配置安全组指南.md | 0 60 files changed, 6896 insertions(+), 10 deletions(-) create mode 100644 RMBG_API_文档.md create mode 100644 app/api/enhance/route.ts create mode 100755 backup-old-server.sh mode change 100644 => 100755 check-gpu.sh create mode 100755 check-server-ssh.sh create mode 100755 deploy-rmbg-feature.sh create mode 100644 lib/security/crowdsec-evaluation.md create mode 100644 lib/security/crowdsec-internal-monitoring.md create mode 100644 lib/security/database-security-report.md create mode 100644 lib/security/internal-threat-monitoring.md create mode 100644 lib/security/security-status-report.md create mode 100644 lib/security/ssh-protection-guide.md create mode 100755 migrate-server.sh create mode 100755 migrate-to-new-server.sh create mode 100644 migration-background.log create mode 100644 migration-backup-complete/User.sql create mode 100644 migration-backup-complete/config-copy.tar.gz create mode 100644 migration-backup-complete/config-copy/AiModel.csv create mode 100644 migration-backup-complete/config-copy/AiProvider.csv create mode 100644 migration-backup-complete/config-copy/AuthSettings.csv create mode 100644 migration-backup-complete/config-copy/NavLinks.csv create mode 100644 migration-backup-complete/config-copy/SiteSettings.csv create mode 100644 migration-backup-complete/config-copy/StorageConfig.csv create mode 100644 migration-backup-complete/config-copy/SystemSettings.csv create mode 100644 migration-backup-complete/config-copy/User.csv create mode 100644 migration-backup-complete/config-inserts.tar.gz create mode 100644 migration-backup-complete/config-inserts/AiModel.sql create mode 100644 migration-backup-complete/config-inserts/AiProvider.sql create mode 100644 migration-backup-complete/config-inserts/AuthSettings.sql create mode 100644 migration-backup-complete/config-inserts/NavLinks.sql create mode 100644 migration-backup-complete/config-inserts/SiteSettings.sql create mode 100644 migration-backup-complete/config-inserts/StorageConfig.sql create mode 100644 migration-backup-complete/config-inserts/SystemSettings.sql create mode 100644 migration-backup-complete/config-sql.tar.gz create mode 100644 migration-backup-complete/config-sql/AiModel.sql create mode 100644 migration-backup-complete/config-sql/AiProvider.sql create mode 100644 migration-backup-complete/config-sql/AuthSettings.sql create mode 100644 migration-backup-complete/config-sql/NavLinks.sql create mode 100644 migration-backup-complete/config-sql/SiteSettings.sql create mode 100644 migration-backup-complete/config-sql/StorageConfig.sql create mode 100644 migration-backup-complete/config-sql/SystemSettings.sql create mode 100644 migration-latest.log create mode 100644 migration-log.txt create mode 100644 migration-run.log create mode 100644 migration.log create mode 100755 scripts/fix-high-cpu.sh create mode 100755 scripts/install-crowdsec.sh create mode 100755 scripts/protect-ssh.sh create mode 100644 图片变清晰api.md create mode 100644 安全工具使用指南.md create mode 100644 手动迁移步骤.md create mode 100644 本地备份数据总结.txt create mode 100644 系统性能诊断与解决方案.md create mode 100644 迁移说明.txt create mode 100644 配置安全组指南.md diff --git a/RMBG_API_文档.md b/RMBG_API_文档.md new file mode 100644 index 0000000..243b8a6 --- /dev/null +++ b/RMBG_API_文档.md @@ -0,0 +1,511 @@ +# RMBG-2.0 API 接口文档 + +## 服务信息 + +- **服务地址**: http://156.225.27.52:8000 +- **API版本**: 2.0.0 +- **模型**: RMBG-2.0 (背景移除模型) +- **框架**: FastAPI +- **API文档**: http://156.225.27.52:8000/docs +- **OpenAPI规范**: http://156.225.27.52:8000/openapi.json +- **API密钥**: 所有核心接口需要API密钥认证(详见下方认证说明) + +--- + +## 认证方式 + +所有核心接口(`/rmbg/file` 和 `/rmbg/base64`)需要在请求头中添加API密钥: + +**请求头**: +``` +X-API-Key: rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG +``` + +**注意**: 以下端点无需API密钥: +- `GET /` - 根端点(服务状态检查) +- `GET /health` - 健康检查 +- `GET /api-key-info` - API密钥信息 + +--- + +## 接口列表 + +### 1. 根端点 - 服务状态检查 + +**接口地址**: `GET /` + +**描述**: 检查服务是否正常运行 + +**请求示例**: +```bash +curl http://156.225.27.52:8000/ +``` + +**响应示例**: +```json +{ + "message": "RMBG-2.0 API 服务运行正常", + "version": "2.0.0", + "model": "RMBG-2.0" +} +``` + +--- + +### 2. 健康检查 + +**接口地址**: `GET /health` + +**描述**: 检查服务健康状态和模型加载状态(无需API密钥) + +**请求示例**: +```bash +curl http://156.225.27.52:8000/health +``` + +**响应示例**: +```json +{ + "status": "healthy", + "model_loaded": true, + "model": "RMBG-2.0" +} +``` + +--- + +### 3. API密钥信息 + +**接口地址**: `GET /api-key-info` + +**描述**: 获取API密钥使用说明(无需API密钥) + +**请求示例**: +```bash +curl http://156.225.27.52:8000/api-key-info +``` + +**响应示例**: +```json +{ + "api_key_name": "X-API-Key", + "description": "请在请求头中添加API密钥" +} +``` + +--- + +### 4. 文件上传背景移除 + +**接口地址**: `POST /rmbg/file` + +**描述**: 通过文件上传方式移除图片背景(需要API密钥) + +**Content-Type**: `multipart/form-data` + +**请求头**: +``` +X-API-Key: rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG +``` + +**请求参数**: +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| file | File | 是 | 图片文件(支持常见图片格式) | + +**请求示例 (cURL)**: +```bash +curl -X POST http://156.225.27.52:8000/rmbg/file \ + -H "X-API-Key: rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG" \ + -F "file=@/path/to/your/image.jpg" +``` + +**请求示例 (Python)**: +```python +import requests + +url = "http://156.225.27.52:8000/rmbg/file" +headers = { + "X-API-Key": "rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG" +} +files = {"file": open("image.jpg", "rb")} +response = requests.post(url, files=files, headers=headers) + +# 保存结果 +with open("result.png", "wb") as f: + f.write(response.content) + +print(f"处理时间: {response.headers.get('X-Processing-Time')} 秒") +``` + +**请求示例 (JavaScript/Node.js)**: +```javascript +const FormData = require('form-data'); +const fs = require('fs'); +const axios = require('axios'); + +const form = new FormData(); +form.append('file', fs.createReadStream('image.jpg')); + +axios.post('http://156.225.27.52:8000/rmbg/file', form, { + headers: { + ...form.getHeaders(), + 'X-API-Key': 'rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG' + }, + responseType: 'arraybuffer' +}) +.then(response => { + fs.writeFileSync('result.png', response.data); + console.log('处理时间:', response.headers['x-processing-time'], '秒'); +}); +``` + +**响应**: +- **Content-Type**: `image/png` +- **Body**: PNG格式的图片二进制数据(背景已移除) +- **Headers**: + - `X-Processing-Time`: 处理时间(秒) + +**错误响应**: +```json +{ + "detail": "Invalid API key" +} +``` +(当API密钥无效或缺失时) + +或 +```json +{ + "detail": "只支持图片文件" +} +``` +(当文件格式不支持时) + +或 +```json +{ + "detail": "处理失败: [错误信息]" +} +``` +(当处理失败时) + +--- + +### 5. Base64 图片背景移除 + +**接口地址**: `POST /rmbg/base64` + +**描述**: 通过Base64编码的图片数据移除背景(需要API密钥) + +**Content-Type**: `application/json` + +**请求头**: +``` +X-API-Key: rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG +``` + +**请求体**: +```json +{ + "image_base64": "base64编码的图片字符串" +} +``` + +**请求参数**: +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| image_base64 | string | 是 | Base64编码的图片数据 | + +**请求示例 (cURL)**: +```bash +curl -X POST http://156.225.27.52:8000/rmbg/base64 \ + -H "Content-Type: application/json" \ + -H "X-API-Key: rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG" \ + -d '{ + "image_base64": "iVBORw0KGgoAAAANSUhEUgAA..." + }' +``` + +**请求示例 (Python)**: +```python +import requests +import base64 + +# 读取图片并转换为base64 +with open("image.jpg", "rb") as f: + image_base64 = base64.b64encode(f.read()).decode('utf-8') + +url = "http://156.225.27.52:8000/rmbg/base64" +headers = { + "Content-Type": "application/json", + "X-API-Key": "rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG" +} +data = {"image_base64": image_base64} +response = requests.post(url, json=data, headers=headers) + +result = response.json() +if result["success"]: + # 保存结果 + result_image = base64.b64decode(result["image_base64"]) + with open("result.png", "wb") as f: + f.write(result_image) + print(f"处理时间: {result['processing_time']} 秒") +``` + +**请求示例 (JavaScript)**: +```javascript +const fs = require('fs'); +const axios = require('axios'); + +// 读取图片并转换为base64 +const imageBuffer = fs.readFileSync('image.jpg'); +const imageBase64 = imageBuffer.toString('base64'); + +axios.post('http://156.225.27.52:8000/rmbg/base64', { + image_base64: imageBase64 +}, { + headers: { + 'Content-Type': 'application/json', + 'X-API-Key': 'rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG' + } +}) +.then(response => { + if (response.data.success) { + const resultImage = Buffer.from(response.data.image_base64, 'base64'); + fs.writeFileSync('result.png', resultImage); + console.log('处理时间:', response.data.processing_time, '秒'); + } +}); +``` + +**响应示例**: +```json +{ + "success": true, + "image_base64": "iVBORw0KGgoAAAANSUhEUgAA...", + "processing_time": 1.234 +} +``` + +**响应参数**: +| 参数名 | 类型 | 说明 | +|--------|------|------| +| success | boolean | 是否成功 | +| image_base64 | string | Base64编码的结果图片(PNG格式) | +| processing_time | number | 处理时间(秒) | + +**错误响应**: +```json +{ + "detail": "Invalid API key" +} +``` +(当API密钥无效或缺失时) + +或 +```json +{ + "detail": "处理失败: [错误信息]" +} +``` +(当处理失败时) + +--- + +## 错误码说明 + +| HTTP状态码 | 说明 | +|-----------|------| +| 200 | 请求成功 | +| 400 | 请求参数错误(如文件格式不支持) | +| 401 | 未授权(API密钥无效或缺失) | +| 422 | 请求参数验证失败 | +| 500 | 服务器内部错误(如处理失败) | + +--- + +## 注意事项 + +1. **API密钥认证**: + - 所有核心接口(`/rmbg/file` 和 `/rmbg/base64`)都需要在请求头中添加 `X-API-Key` + - API密钥:`rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG` + - 健康检查和根端点无需密钥 +2. **支持的图片格式**: 所有常见图片格式(JPG, PNG, JPEG等) +3. **输出格式**: 所有接口返回PNG格式的透明背景图片(RGBA模式) +4. **文件大小**: 建议图片大小不超过50MB +5. **处理时间**: 处理时间取决于图片大小和服务器负载,通常在0.5-5秒之间 +6. **CORS**: 服务已配置CORS,支持跨域请求 + +--- + +## 完整使用示例 + +### Python完整示例 +```python +import requests +import base64 +from pathlib import Path + +# 方法1: 文件上传 +def remove_bg_file(image_path): + url = "http://156.225.27.52:8000/rmbg/file" + headers = { + "X-API-Key": "rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG" + } + with open(image_path, "rb") as f: + files = {"file": f} + response = requests.post(url, files=files, headers=headers) + + if response.status_code == 200: + output_path = Path(image_path).stem + "_nobg.png" + with open(output_path, "wb") as f: + f.write(response.content) + print(f"✅ 成功! 结果已保存到: {output_path}") + return output_path + else: + print(f"❌ 失败: {response.json()}") + return None + +# 方法2: Base64 +def remove_bg_base64(image_path): + url = "http://156.225.27.52:8000/rmbg/base64" + headers = { + "Content-Type": "application/json", + "X-API-Key": "rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG" + } + + with open(image_path, "rb") as f: + image_base64 = base64.b64encode(f.read()).decode('utf-8') + + data = {"image_base64": image_base64} + response = requests.post(url, json=data, headers=headers) + + if response.status_code == 200: + result = response.json() + if result["success"]: + output_path = Path(image_path).stem + "_nobg.png" + result_image = base64.b64decode(result["image_base64"]) + with open(output_path, "wb") as f: + f.write(result_image) + print(f"✅ 成功! 处理时间: {result['processing_time']:.2f}秒") + return output_path + else: + print(f"❌ 失败: {response.json()}") + return None + +# 使用示例 +if __name__ == "__main__": + image_path = "test_image.jpg" + + # 使用文件上传方式 + remove_bg_file(image_path) + + # 或使用Base64方式 + # remove_bg_base64(image_path) +``` + +### JavaScript/Node.js完整示例 +```javascript +const axios = require('axios'); +const FormData = require('form-data'); +const fs = require('fs'); +const path = require('path'); + +// 方法1: 文件上传 +async function removeBgFile(imagePath) { + const form = new FormData(); + form.append('file', fs.createReadStream(imagePath)); + + try { + const response = await axios.post( + 'http://156.225.27.52:8000/rmbg/file', + form, + { + headers: { + ...form.getHeaders(), + 'X-API-Key': 'rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG' + }, + responseType: 'arraybuffer' + } + ); + + const outputPath = path.parse(imagePath).name + '_nobg.png'; + fs.writeFileSync(outputPath, response.data); + console.log(`✅ 成功! 结果已保存到: ${outputPath}`); + return outputPath; + } catch (error) { + console.error('❌ 失败:', error.response?.data || error.message); + return null; + } +} + +// 方法2: Base64 +async function removeBgBase64(imagePath) { + const imageBuffer = fs.readFileSync(imagePath); + const imageBase64 = imageBuffer.toString('base64'); + + try { + const response = await axios.post( + 'http://156.225.27.52:8000/rmbg/base64', + { image_base64: imageBase64 }, + { + headers: { + 'Content-Type': 'application/json', + 'X-API-Key': 'rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG' + } + } + ); + + if (response.data.success) { + const outputPath = path.parse(imagePath).name + '_nobg.png'; + const resultImage = Buffer.from(response.data.image_base64, 'base64'); + fs.writeFileSync(outputPath, resultImage); + console.log(`✅ 成功! 处理时间: ${response.data.processing_time.toFixed(2)}秒`); + return outputPath; + } + } catch (error) { + console.error('❌ 失败:', error.response?.data || error.message); + return null; + } +} + +// 使用示例 +(async () => { + const imagePath = 'test_image.jpg'; + + // 使用文件上传方式 + await removeBgFile(imagePath); + + // 或使用Base64方式 + // await removeBgBase64(imagePath); +})(); +``` + +--- + +## 交互式API文档 + +访问 http://156.225.27.52:8000/docs 可以在浏览器中查看交互式API文档(Swagger UI),支持在线测试接口。 + +**注意**: 在Swagger UI中测试需要API密钥的接口时,需要先点击右上角的"Authorize"按钮(如果有),或者直接在请求头中添加 `X-API-Key`。 + +--- + +## API密钥 + +当前API密钥: +``` +rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG +``` + +**请求头格式**: +``` +X-API-Key: rmbg_sk_live_7K9mP2nQ5rT8vW1xY4zA6bC9dE0fG3hI6jK9mL2nO5pQ8rS1tU4vW7xY0zA3bC6dE9fG +``` + +**安全提示**: +- 请妥善保管API密钥,不要将其暴露在客户端代码中 +- 建议通过环境变量或配置文件管理API密钥 +- 定期更换API密钥以提高安全性 + diff --git a/app/(admin)/settings/admin-settings-client.tsx b/app/(admin)/settings/admin-settings-client.tsx index 796ca42..7a29d1a 100644 --- a/app/(admin)/settings/admin-settings-client.tsx +++ b/app/(admin)/settings/admin-settings-client.tsx @@ -347,6 +347,14 @@ export function AdminSettingsClient() { apiKey: "", }); + // 变清晰API配置状态 + const [enhanceConfig, setEnhanceConfig] = useState({ + apiUrl: "", + apiKey: "", + type: "clean", // "clean" | "face" + scaleFactor: "", // "" | "1" | "2" | "4" + }); + // 加载抠图API配置 const { data: rmbgConfigData } = useSWR("/api/admin/settings?key=rmbg_api_config", fetcher); useEffect(() => { @@ -359,6 +367,25 @@ export function AdminSettingsClient() { } }, [rmbgConfigData]); + // 加载变清晰API配置 + const { data: enhanceConfigData } = useSWR("/api/admin/settings?key=enhance_api_config", fetcher); + useEffect(() => { + if (enhanceConfigData?.setting?.value) { + const config = enhanceConfigData.setting.value as { + apiUrl?: string; + apiKey?: string; + type?: string; + scaleFactor?: number; + }; + setEnhanceConfig({ + apiUrl: config.apiUrl || "", + apiKey: config.apiKey || "", + type: config.type || "clean", + scaleFactor: config.scaleFactor ? String(config.scaleFactor) : "", + }); + } + }, [enhanceConfigData]); + // 导航链接状态 const [navLinkForm, setNavLinkForm] = useState({ id: "", @@ -666,6 +693,40 @@ export function AdminSettingsClient() { } }; + // --- 变清晰API配置逻辑 --- + const handleSaveEnhanceConfig = async () => { + try { + if (!enhanceConfig.apiUrl.trim()) { + toast.error("请输入API地址"); + return; + } + + if (!enhanceConfig.apiKey.trim()) { + toast.error("请输入API密钥"); + return; + } + + const response = await fetch("/api/admin/settings", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + key: "enhance_api_config", + value: { + apiUrl: enhanceConfig.apiUrl.trim(), + apiKey: enhanceConfig.apiKey.trim(), + type: enhanceConfig.type, + scaleFactor: enhanceConfig.scaleFactor ? Number.parseInt(enhanceConfig.scaleFactor) : undefined, + }, + }), + }); + + if (!response.ok) throw new Error("保存失败"); + toast.success("变清晰API配置保存成功"); + } catch (error) { + toast.error("保存变清晰API配置失败"); + } + }; + // --- 导航链接逻辑 --- const resetNavLinkForm = () => { setNavLinkForm({ id: "", name: "", url: "", order: 0, isEnabled: true }); @@ -1018,7 +1079,7 @@ export function AdminSettingsClient() { - 抠图设置 + 本地AI设置 @@ -2901,8 +2962,9 @@ export function AdminSettingsClient() { - {/* 抠图设置 */} - + {/* 本地AI设置 */} + + {/* 抠图API配置 */} 抠图API配置 @@ -2950,6 +3012,94 @@ export function AdminSettingsClient() { + + {/* 变清晰API配置 */} + + + 变清晰API配置 + + 配置图片变清晰API,用于画图标注功能中的图片增强处理 + + + +
+ + setEnhanceConfig({ ...enhanceConfig, apiUrl: e.target.value })} + placeholder="https://techsz.aoscdn.com" + /> +
+ 请输入完整的API地址,例如: https://techsz.aoscdn.com +
+
+
+ + setEnhanceConfig({ ...enhanceConfig, apiKey: e.target.value })} + placeholder="请输入API密钥" + /> +
+ API密钥是必需的,请从服务提供商获取 +
+
+
+ + +
+ 选择图片类型:通用或人像(人像模式最多同时处理10个人) +
+
+
+ + +
+ 选择放大倍数:自动(根据图片尺寸智能选择)、不放大、2倍或4倍 +
+
+
+
API文档说明
+
+

• API地址应指向服务根地址,例如: https://techsz.aoscdn.com

+

• 系统会自动调用 /api/tasks/visual/scale 接口进行变清晰处理

+

• 支持的图片格式:JPG, JPEG, PNG, BMP, WEBP, TIFF等

+

• 图片大小:不超过20MB,分辨率最大4096x4096

+

• 返回的链接有效期为1小时,系统会自动下载并存储到S3

+
+
+ +
+
diff --git a/app/(chat)/gallery/page.tsx b/app/(chat)/gallery/page.tsx index ef637f4..53d5627 100644 --- a/app/(chat)/gallery/page.tsx +++ b/app/(chat)/gallery/page.tsx @@ -4,7 +4,7 @@ import { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent } from "@/components/ui/dialog"; -import { ArrowLeft, Download, ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, Edit, Scissors } from "lucide-react"; +import { ArrowLeft, Download, ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, Edit, Scissors, Sparkles } from "lucide-react"; import { Input } from "@/components/ui/input"; import Image from "next/image"; import { toast } from "sonner"; @@ -41,6 +41,7 @@ export default function GalleryPage() { const [dialogOpen, setDialogOpen] = useState(false); const [pageInput, setPageInput] = useState(""); const [processingImageId, setProcessingImageId] = useState(null); + const [enhancingImageId, setEnhancingImageId] = useState(null); const fetchImages = async (page: number) => { setLoading(true); @@ -232,12 +233,26 @@ export default function GalleryPage() { e.stopPropagation(); handleRemoveBackground(img, e); }} - disabled={processingImageId === img.id} + disabled={processingImageId === img.id || enhancingImageId === img.id} title="移除背景(抠图)" > {processingImageId === img.id ? "处理中" : "抠图"} + +