1403 lines
31 KiB
Markdown
1403 lines
31 KiB
Markdown
# Cloudflare Worker 部署与使用指南
|
||
|
||
## 📦 文件说明
|
||
|
||
本工具只需要 **2 个文件**:
|
||
|
||
1. **cf_worker_v2ray_converter.js** (~88KB) - Worker 主文件
|
||
- 包含所有功能代码和完整的 HTML/CSS/JavaScript 界面
|
||
- **这是唯一需要部署到 Cloudflare 的文件**
|
||
|
||
2. **DEPLOYMENT_GUIDE.md** - 本文件,部署和使用指南
|
||
|
||
---
|
||
|
||
## 🎯 功能说明
|
||
|
||
### v4.1 核心功能 ⭐ 最新版本
|
||
|
||
#### 📡 订阅管理中心(需要配置 KV)
|
||
|
||
全新的订阅管理界面,专注于订阅的长期管理:
|
||
|
||
- ✅ **左右分栏布局**:左侧订阅列表,右侧详情操作
|
||
- ✅ **订阅分类管理**:
|
||
- **正式订阅**:支持 7天、1个月、3个月、1年、3年、长期(默认1年)
|
||
- **临时订阅**:限定1天/3天/7天有效期,到期自动删除
|
||
- ✅ **智能类型识别**:自动检测 Clash 或 V2Ray 格式
|
||
- ✅ **双向格式转换**:Clash ⇄ V2Ray 任意转换
|
||
- ✅ **短链生命周期管理**:续期、换新链接、删除
|
||
- ✅ **状态标记**:快过期(30天内)和已过期订阅有明显标记
|
||
- ✅ **自定义对话框**:美观的模态确认框替代浏览器默认弹窗
|
||
|
||
---
|
||
|
||
## 🚀 快速部署(5分钟)
|
||
|
||
### 方式 1: 通过 Cloudflare Dashboard(推荐新手)
|
||
|
||
#### 步骤 1:登录 Cloudflare
|
||
|
||
访问 <https://dash.cloudflare.com/> 并登录(没有账号需先注册)
|
||
|
||
#### 步骤 2:创建 Worker
|
||
|
||
1. 点击左侧菜单 **Workers & Pages**
|
||
2. 点击 **Create application** → **Create Worker**
|
||
3. 输入名称(如:`subscription-manager`)
|
||
- 这将成为你的访问域名:`subscription-manager.你的账号.workers.dev`
|
||
4. 点击 **Deploy**
|
||
|
||
#### 步骤 3:部署代码
|
||
|
||
1. 点击 **Quick edit** 打开代码编辑器
|
||
2. **删除**编辑器中的所有默认代码
|
||
3. 打开本地的 `cf_worker_v2ray_converter.js`
|
||
4. **全选复制**所有内容(Ctrl+A / Cmd+A,然后 Ctrl+C / Cmd+C)
|
||
- ⚠️ 重要:必须复制全部 ~88KB 内容
|
||
5. **粘贴**到编辑器(Ctrl+V / Cmd+V)
|
||
6. 点击右上角 **Save and deploy**
|
||
|
||
#### 步骤 4:验证部署
|
||
|
||
1. 访问 `https://你的worker名称.你的账号.workers.dev/`
|
||
2. 应该看到紫色渐变背景的「📡 订阅管理中心」页面
|
||
3. 提示需要配置 KV 命名空间
|
||
4. 继续下一步配置 KV
|
||
|
||
✅ **基础部署完成!**
|
||
|
||
---
|
||
|
||
### 方式 2: 使用 Wrangler CLI(推荐开发者)
|
||
|
||
```bash
|
||
# 1. 安装 wrangler
|
||
npm install -g wrangler
|
||
|
||
# 2. 登录
|
||
wrangler login
|
||
|
||
# 3. 创建项目
|
||
mkdir subscription-manager && cd subscription-manager
|
||
wrangler init
|
||
|
||
# 4. 复制代码到 src/index.js
|
||
cp /path/to/cf_worker_v2ray_converter.js src/index.js
|
||
|
||
# 5. 部署
|
||
wrangler deploy
|
||
|
||
# 6. 查看日志(可选)
|
||
wrangler tail
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 必需配置:启用订阅管理
|
||
|
||
### 为什么需要配置 KV?
|
||
|
||
订阅管理功能依赖 Cloudflare KV 存储数据:
|
||
|
||
**不配置 KV:**
|
||
|
||
- ✅ 快速转换可用
|
||
- ❌ 订阅管理不可用
|
||
- ❌ 短链接不可用
|
||
|
||
**配置 KV:**
|
||
|
||
- ✅ 全部功能可用
|
||
- ✅ 可保存多个订阅
|
||
- ✅ 数据持久化
|
||
|
||
**强烈建议配置 KV!** 以下是详细步骤:
|
||
|
||
---
|
||
|
||
### 第一步:创建 KV 命名空间
|
||
|
||
#### 通过 Dashboard 创建
|
||
|
||
1. 在 Cloudflare Dashboard 中,点击 **Workers & Pages**
|
||
2. 点击顶部的 **KV** 标签
|
||
3. 点击 **Create a namespace**
|
||
4. 输入名称:`SUBSCRIPTION_STORE`
|
||
5. 点击 **Add**
|
||
|
||
#### 通过 CLI 创建(可选)
|
||
|
||
```bash
|
||
wrangler kv:namespace create "SUBSCRIPTION_STORE"
|
||
# 记录输出的 namespace id
|
||
```
|
||
|
||
---
|
||
|
||
### 第二步:绑定 KV 到 Worker
|
||
|
||
#### 通过 Dashboard 绑定
|
||
|
||
1. 进入你的 Worker 页面
|
||
2. 点击 **Settings** 标签
|
||
3. 选择左侧的 **Variables**
|
||
4. 滚动到 **KV Namespace Bindings** 部分
|
||
5. 点击 **Add binding**
|
||
6. 填写:
|
||
- **Variable name**: `SUBSCRIPTION_KV` ⚠️ **必须用这个名字**
|
||
- **KV namespace**: 选择 `SUBSCRIPTION_STORE`
|
||
7. 点击 **Save and deploy**
|
||
|
||
#### 通过 Wrangler 绑定(可选)
|
||
|
||
在 `wrangler.toml` 中添加:
|
||
|
||
```toml
|
||
[[kv_namespaces]]
|
||
binding = "SUBSCRIPTION_KV"
|
||
id = "your_namespace_id"
|
||
```
|
||
|
||
重新部署:
|
||
|
||
```bash
|
||
wrangler deploy
|
||
```
|
||
|
||
---
|
||
|
||
### 第三步:验证配置
|
||
|
||
1. 访问你的 Worker URL
|
||
2. 切换到「订阅管理」标签
|
||
3. 如果看到「+ 添加新订阅」按钮
|
||
4. 说明配置成功!
|
||
|
||
**如果显示"KV 未配置":**
|
||
|
||
- 检查变量名是否为 `SUBSCRIPTION_KV`
|
||
- 检查是否点击了 Save and deploy
|
||
- 强制刷新页面(Ctrl+Shift+R)
|
||
|
||
---
|
||
|
||
## 💾 订阅数据存储机制
|
||
|
||
### 存储架构概览
|
||
|
||
本工具使用 Cloudflare KV 的**三层存储结构**来管理订阅数据:
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────┐
|
||
│ Cloudflare KV Storage │
|
||
├─────────────────────────────────────────────────┤
|
||
│ │
|
||
│ 1️⃣ 订阅配置存储 │
|
||
│ Key: sub:{subscriptionId} │
|
||
│ Value: {...订阅详细信息...} │
|
||
│ 生命周期: 永久 │
|
||
│ │
|
||
│ 2️⃣ 短链接映射存储 │
|
||
│ Key: {shortId} │
|
||
│ Value: clashUrl │
|
||
│ 生命周期: 7-365天(可配置) │
|
||
│ │
|
||
│ 3️⃣ 订阅列表索引 │
|
||
│ Key: subscriptions:list │
|
||
│ Value: [id1, id2, id3, ...] │
|
||
│ 生命周期: 永久 │
|
||
│ │
|
||
└─────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
### 详细存储说明
|
||
|
||
#### 1️⃣ 订阅配置存储
|
||
|
||
**键格式**: `sub:{subscriptionId}`
|
||
**值类型**: JSON 对象
|
||
**生命周期**: 永久(手动删除才会消失)
|
||
|
||
**存储内容**:
|
||
|
||
```json
|
||
{
|
||
"id": "abc12345", // 订阅唯一ID(8位随机字符)
|
||
"name": "我的订阅", // 用户设置的订阅名称
|
||
"clashUrl": "https://...", // 原始订阅链接(Clash或V2Ray)
|
||
"subscriptionType": "clash", // 订阅源类型:clash/v2ray
|
||
"subscriptionMode": "permanent", // 订阅分类:permanent/temporary
|
||
"outputType": "v2ray", // 输出类型:auto/clash/v2ray
|
||
"shortIds": {}, // 短链ID对象(按需生成)
|
||
"shortIdsExpiry": {}, // 短链过期时间对象
|
||
"createdAt": 1703001234567, // 创建时间(Unix时间戳)
|
||
"expiresAt": 1703606034567, // 订阅过期时间(null表示无限期)
|
||
"expiration": "7d", // 有效期配置(如:7d, 30d, 3m, 1y, unlimited)
|
||
"updatedAt": 1703001234567 // 最后更新时间
|
||
}
|
||
```
|
||
|
||
**实际例子**:
|
||
|
||
```json
|
||
Key: sub:aB7cD9eF
|
||
Value: {
|
||
"id": "aB7cD9eF",
|
||
"name": "公司网络",
|
||
"clashUrl": "https://...",
|
||
"subscriptionType": "clash",
|
||
"subscriptionMode": "permanent",
|
||
"outputType": "v2ray",
|
||
"shortIds": {},
|
||
"shortIdsExpiry": {},
|
||
"createdAt": 1734672000000,
|
||
"expiresAt": 1737264000000,
|
||
"expiration": "30d",
|
||
"updatedAt": 1734672000000
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### 2️⃣ 短链接映射存储
|
||
|
||
**键格式**: `{shortId}`(直接使用短ID)
|
||
**值类型**: JSON 对象(包含 url、type、subscriptionId、outputType)
|
||
**生命周期**: 有过期时间(TTL机制)
|
||
|
||
**存储内容**:
|
||
|
||
```json
|
||
Key: xyz98765
|
||
Value: {
|
||
"url": "https://example.com/clash-subscription",
|
||
"type": "clash",
|
||
"subscriptionId": "abc12345",
|
||
"outputType": "v2ray"
|
||
}
|
||
TTL: 604800 秒(7天)
|
||
```
|
||
|
||
**TTL 机制**:
|
||
|
||
- 创建时设置过期时间(expirationTtl)
|
||
- 到期后 KV 自动删除
|
||
- 订阅配置仍保留(可续期或换新链接)
|
||
|
||
**实际例子**:
|
||
|
||
```json
|
||
Key: x3Y8z2W
|
||
Value: {
|
||
"url": "https://sub.example.com/api/v1/client/subscribe?token=abc123",
|
||
"type": "clash",
|
||
"subscriptionId": "aB7cD9eF",
|
||
"outputType": "v2ray"
|
||
}
|
||
TTL: 2592000 秒(30天)
|
||
```
|
||
|
||
---
|
||
|
||
#### 3️⃣ 订阅列表索引
|
||
|
||
**键格式**: `subscriptions:list`(固定键名)
|
||
**值类型**: JSON 数组
|
||
**生命周期**: 永久
|
||
|
||
**存储内容**:
|
||
|
||
```json
|
||
["aB7cD9eF", "gH4iJ6kL", "mN1oP8qR"]
|
||
```
|
||
|
||
**作用**:
|
||
|
||
- 快速获取所有订阅ID
|
||
- 避免遍历整个 KV 空间
|
||
- 支持高效的列表查询
|
||
|
||
---
|
||
|
||
### 数据操作流程
|
||
|
||
#### 📝 创建订阅
|
||
|
||
```
|
||
用户输入 → 生成ID → 写入3个地方
|
||
```
|
||
|
||
详细步骤:
|
||
|
||
1. 用户提交:名称、Clash URL、有效期
|
||
2. 生成 `subscriptionId`(8位随机字符)
|
||
3. 生成 `shortId`(8位随机字符)
|
||
4. **写入操作**:
|
||
|
||
```javascript
|
||
// ① 创建短链数据(按需生成,不在创建时预先生成)
|
||
const shortLinkData = {
|
||
url: clashUrl,
|
||
type: subscriptionType,
|
||
subscriptionId: subscriptionId,
|
||
outputType: outputType
|
||
}
|
||
|
||
// ② 写入订阅配置
|
||
await KV.put(`sub:${subscriptionId}`, JSON.stringify(subscription))
|
||
|
||
// ③ 更新订阅列表
|
||
const list = await getList()
|
||
list.push(subscriptionId)
|
||
await KV.put('subscriptions:list', JSON.stringify(list))
|
||
```
|
||
|
||
---
|
||
|
||
#### 📖 获取订阅列表
|
||
|
||
```
|
||
读取索引 → 遍历读取 → 检查状态 → 返回列表
|
||
```
|
||
|
||
详细步骤:
|
||
|
||
1. 读取 `subscriptions:list` 获取所有ID
|
||
2. 循环读取每个 `sub:{id}`
|
||
3. 检查 `expiresAt` 判断是否过期
|
||
4. 组装并返回完整列表
|
||
|
||
**性能**:
|
||
|
||
- 假设有 10 个订阅
|
||
- 需要 11 次 KV 读取(1次索引 + 10次配置)
|
||
- 免费版每天 100K 读取,完全够用
|
||
|
||
---
|
||
|
||
#### 🔄 续期短链
|
||
|
||
```
|
||
读取配置 → 更新TTL → 更新配置
|
||
```
|
||
|
||
详细步骤:
|
||
|
||
1. 读取 `sub:{id}` 获取 shortIds 和订阅信息
|
||
2. **重新写入短链**(更新 TTL):
|
||
|
||
```javascript
|
||
const shortLinkData = {
|
||
url: subscription.clashUrl,
|
||
type: subscription.subscriptionType,
|
||
subscriptionId: id,
|
||
outputType: subscription.outputType
|
||
}
|
||
await KV.put(shortId, JSON.stringify(shortLinkData), {
|
||
expirationTtl: newDays * 86400
|
||
})
|
||
```
|
||
|
||
3. **更新订阅配置**:
|
||
|
||
```javascript
|
||
subscription.shortIdsExpiry[type] = Date.now() + newTTL * 1000
|
||
subscription.updatedAt = Date.now()
|
||
await KV.put(`sub:${id}`, JSON.stringify(subscription))
|
||
```
|
||
|
||
**优势**:
|
||
|
||
- 短链接URL不变
|
||
- v2rayN客户端无需重新配置
|
||
- 只需2次KV操作
|
||
|
||
---
|
||
|
||
#### 🔁 换新链接
|
||
|
||
```
|
||
删除旧链 → 生成新ID → 写入新链 → 更新配置
|
||
```
|
||
|
||
详细步骤:
|
||
|
||
1. 读取订阅配置,获取旧的 shortIds
|
||
2. **删除旧短链**:
|
||
|
||
```javascript
|
||
if (subscription.shortIds[type]) {
|
||
await KV.delete(subscription.shortIds[type])
|
||
}
|
||
```
|
||
|
||
3. 生成新的 shortId
|
||
4. **写入新短链**:
|
||
|
||
```javascript
|
||
const shortLinkData = {
|
||
url: subscription.clashUrl,
|
||
type: subscription.subscriptionType,
|
||
subscriptionId: id,
|
||
outputType: subscription.outputType
|
||
}
|
||
await KV.put(newShortId, JSON.stringify(shortLinkData), {
|
||
expirationTtl: days * 86400
|
||
})
|
||
```
|
||
|
||
5. **更新订阅配置**:
|
||
|
||
```javascript
|
||
subscription.shortIds[type] = newShortId
|
||
subscription.shortIdsExpiry[type] = Date.now() + newTTL * 1000
|
||
subscription.updatedAt = Date.now()
|
||
await KV.put(`sub:${id}`, JSON.stringify(subscription))
|
||
```
|
||
|
||
**注意**:
|
||
|
||
- 旧短链立即失效
|
||
- 需要在v2rayN中更新订阅链接
|
||
- 用于应对链接泄露的情况
|
||
|
||
---
|
||
|
||
#### 🗑️ 删除订阅
|
||
|
||
```
|
||
删除短链 → 删除配置 → 更新索引
|
||
```
|
||
|
||
详细步骤:
|
||
|
||
1. 读取配置获取 shortIds 对象
|
||
2. **删除所有短链映射**:
|
||
|
||
```javascript
|
||
for (const type in subscription.shortIds) {
|
||
await KV.delete(subscription.shortIds[type])
|
||
}
|
||
```
|
||
|
||
3. **删除订阅配置**:`await KV.delete(`sub:${id}`)`
|
||
4. **更新订阅列表**:
|
||
|
||
```javascript
|
||
const list = await getList()
|
||
const newList = list.filter(x => x !== id)
|
||
await KV.put('subscriptions:list', JSON.stringify(newList))
|
||
```
|
||
|
||
---
|
||
|
||
### 存储容量和限制
|
||
|
||
#### Cloudflare KV 免费版配额
|
||
|
||
| 指标 | 限制 | 说明 |
|
||
|------|------|------|
|
||
| 存储空间 | 1 GB | 可存储约100万个订阅 |
|
||
| 读取操作 | 100,000 次/天 | 获取订阅、访问短链 |
|
||
| 写入操作 | 1,000 次/天 | 创建、更新、删除订阅 |
|
||
| 删除操作 | 1,000 次/天 | 包含在写入配额中 |
|
||
| 列表操作 | 1,000 次/天 | 遍历键名 |
|
||
|
||
#### 操作消耗计算
|
||
|
||
**创建1个订阅**:
|
||
|
||
- 2次写入(配置 + 索引)
|
||
- 消耗配额:2/1000
|
||
- 注:短链按需生成,不在创建时预先生成
|
||
|
||
**获取订阅列表**(假设10个订阅):
|
||
|
||
- 11次读取(1次索引 + 10次配置)
|
||
- 消耗配额:11/100000
|
||
|
||
**续期1个订阅**:
|
||
|
||
- 1次读取 + 2次写入
|
||
- 消耗配额:1/100000 + 2/1000
|
||
|
||
**换新链接**:
|
||
|
||
- 1次读取 + 1次删除 + 2次写入
|
||
- 消耗配额:1/100000 + 3/1000
|
||
|
||
---
|
||
|
||
#### 实际使用场景
|
||
|
||
**个人使用(推荐)**:
|
||
|
||
```
|
||
订阅数量:10-50 个
|
||
短链有效期:30-90 天
|
||
每天操作:
|
||
- 查看列表 5 次 → 55 次读取
|
||
- 访问短链 50 次 → 50 次读取
|
||
- 创建订阅 1 次 → 2 次写入
|
||
- 续期订阅 1 次 → 2 次写入
|
||
|
||
总消耗:
|
||
- 读取:105 / 100,000 = 0.1%
|
||
- 写入:4 / 1,000 = 0.4%
|
||
|
||
结论:完全在免费额度内 ✅
|
||
```
|
||
|
||
**小团队使用**:
|
||
|
||
```
|
||
订阅数量:100-200 个
|
||
短链有效期:60-180 天
|
||
每天操作:
|
||
- 查看列表 20 次 → 4,020 次读取
|
||
- 访问短链 500 次 → 500 次读取
|
||
- 创建订阅 5 次 → 10 次写入
|
||
- 续期订阅 5 次 → 10 次写入
|
||
|
||
总消耗:
|
||
- 读取:4,520 / 100,000 = 4.5%
|
||
- 写入:20 / 1,000 = 2.0%
|
||
|
||
结论:免费额度足够 ✅
|
||
```
|
||
|
||
**高频使用(需付费)**:
|
||
|
||
```
|
||
- 写入 > 1,000 次/天
|
||
- 读取 > 100,000 次/天
|
||
建议:升级到付费版
|
||
```
|
||
|
||
---
|
||
|
||
### 数据持久性
|
||
|
||
#### 永久保存的数据
|
||
|
||
- ✅ 订阅配置(`sub:{id}`)
|
||
- ✅ 订阅列表索引(`subscriptions:list`)
|
||
- ✅ 不会因为 Worker 重新部署而丢失
|
||
|
||
#### 有生命周期的数据
|
||
|
||
- ⏰ 短链接(`{shortId}`)
|
||
- ⏰ 创建时设置 TTL
|
||
- ⏰ 到期自动删除
|
||
- ⏰ 但可以续期或换新
|
||
|
||
#### 数据丢失风险
|
||
|
||
- ❌ 删除 KV 命名空间 → 所有数据丢失
|
||
- ❌ 解绑 KV → 无法访问数据
|
||
- ✅ Worker 重新部署 → 数据不受影响
|
||
- ✅ 修改代码 → 数据不受影响
|
||
|
||
---
|
||
|
||
### 数据安全性
|
||
|
||
#### 1. 数据隔离
|
||
|
||
- 每个 Worker 绑定独立的 KV 命名空间
|
||
- 其他人无法访问你的 KV 数据
|
||
- Cloudflare 账号权限控制
|
||
|
||
#### 2. 访问控制
|
||
|
||
- 订阅管理功能在前端,无内置权限控制
|
||
- **建议**:不要公开分享 Worker URL
|
||
- **可选**:配置 `ADMIN_TOKEN` 环境变量启用管理员页面
|
||
|
||
配置管理员 Token:
|
||
|
||
```
|
||
Worker Settings → Variables → Environment Variables
|
||
Name: ADMIN_TOKEN
|
||
Value: your-secret-token
|
||
```
|
||
|
||
访问管理页面:
|
||
|
||
```
|
||
https://your-worker.workers.dev/admin?token=your-secret-token
|
||
```
|
||
|
||
#### 3. 数据备份
|
||
|
||
- KV 数据由 Cloudflare 自动备份
|
||
- **建议**:定期导出重要订阅的 Clash URL
|
||
- 可通过 API 或管理页面查看所有订阅
|
||
|
||
#### 4. 隐私保护
|
||
|
||
- Clash URL 存储在 KV 中(加密存储)
|
||
- 短链接隐藏了原始 URL
|
||
- **建议**:使用短链接分享,不要直接分享 Clash URL
|
||
|
||
---
|
||
|
||
## 📱 使用指南
|
||
|
||
### 场景 1:快速转换(临时使用)
|
||
|
||
**适合**:偶尔需要转换、不想保存
|
||
|
||
**步骤**:
|
||
|
||
1. 访问 Worker URL
|
||
2. 在「快速转换」标签
|
||
3. 粘贴 Clash 订阅链接
|
||
4. 点击「生成在线链接」或「下载订阅」
|
||
5. 使用生成的链接或文件
|
||
|
||
---
|
||
|
||
### 场景 2:保存订阅(长期管理)⭐ 推荐
|
||
|
||
**适合**:经常使用、需要管理多个订阅
|
||
|
||
#### 首次添加订阅
|
||
|
||
1. 切换到「订阅管理」标签
|
||
2. 点击「+ 添加新订阅」
|
||
3. 填写信息:
|
||
|
||
```
|
||
订阅名称:公司网络
|
||
Clash 订阅链接:https://...
|
||
短链有效期:30 天
|
||
```
|
||
|
||
4. 点击「保存」
|
||
|
||
#### 使用订阅
|
||
|
||
1. 找到订阅卡片
|
||
2. 点击「复制链接」
|
||
3. 在 v2rayN 中:
|
||
|
||
```
|
||
订阅 → 订阅设置
|
||
添加订阅地址
|
||
粘贴链接 → 确定
|
||
更新订阅
|
||
```
|
||
|
||
#### 管理订阅
|
||
|
||
- **续期**:短链快过期 → 点击「续期」→ 设置天数
|
||
- 优点:链接不变,客户端无需更新
|
||
|
||
- **换新链接**:担心链接泄露 → 点击「换新链接」→ 设置天数
|
||
- 注意:旧链接失效,需要更新客户端
|
||
|
||
- **编辑**:Clash URL 变了 → 点击「编辑」→ 修改并保存
|
||
|
||
- **删除**:不再需要 → 点击「删除」→ 确认
|
||
|
||
---
|
||
|
||
### 场景 3:管理多个订阅
|
||
|
||
**适合**:多个机场、多个环境
|
||
|
||
**示例**:
|
||
|
||
```
|
||
订阅列表:
|
||
├─ 机场A - 美国节点(30天)
|
||
├─ 机场B - 香港节点(60天)
|
||
├─ 公司专线(90天)
|
||
└─ 备用订阅(7天)
|
||
```
|
||
|
||
**操作**:
|
||
|
||
1. 分别添加所有订阅
|
||
2. 设置不同的名称和有效期
|
||
3. 在 v2rayN 中添加多个订阅源
|
||
4. 定期检查过期状态
|
||
5. 需要时单独续期或换链接
|
||
|
||
---
|
||
|
||
## 🔌 API 接口说明
|
||
|
||
### 基础接口
|
||
|
||
#### 1. 网页界面
|
||
|
||
```http
|
||
GET /
|
||
```
|
||
|
||
返回 HTML 页面
|
||
|
||
#### 2. 快速转换(POST)
|
||
|
||
```http
|
||
POST /convert
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"clashUrl": "https://..."
|
||
}
|
||
```
|
||
|
||
返回 Base64 编码的 v2rayN 订阅
|
||
|
||
#### 3. 快速转换(GET)
|
||
|
||
```http
|
||
GET /convert?url=https://...
|
||
```
|
||
|
||
直接返回订阅内容,用于在线订阅
|
||
|
||
#### 4. 生成短链
|
||
|
||
```http
|
||
POST /shorten
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"clashUrl": "https://..."
|
||
}
|
||
```
|
||
|
||
#### 5. 访问短链
|
||
|
||
```http
|
||
GET /s/{shortId}
|
||
```
|
||
|
||
---
|
||
|
||
### 订阅管理 API
|
||
|
||
#### 创建订阅
|
||
|
||
```http
|
||
POST /api/subscriptions
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "我的订阅",
|
||
"clashUrl": "https://...",
|
||
"expirationDays": 30
|
||
}
|
||
```
|
||
|
||
#### 获取所有订阅
|
||
|
||
```http
|
||
GET /api/subscriptions
|
||
```
|
||
|
||
#### 获取单个订阅
|
||
|
||
```http
|
||
GET /api/subscriptions/{id}
|
||
```
|
||
|
||
#### 更新订阅
|
||
|
||
```http
|
||
PUT /api/subscriptions/{id}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "新名称",
|
||
"clashUrl": "https://..."
|
||
}
|
||
```
|
||
|
||
#### 删除订阅
|
||
|
||
```http
|
||
DELETE /api/subscriptions/{id}
|
||
```
|
||
|
||
#### 续期短链
|
||
|
||
```http
|
||
POST /api/subscriptions/{id}/renew
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"days": 30
|
||
}
|
||
```
|
||
|
||
#### 换新链接
|
||
|
||
```http
|
||
POST /api/subscriptions/{id}/regenerate
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"days": 30
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## ❓ 常见问题
|
||
|
||
### Q1: 必须配置 KV 吗?
|
||
|
||
**答**:不是必须,但强烈建议
|
||
|
||
- 不配置:只能用快速转换
|
||
- 配置后:完整功能,可保存订阅
|
||
|
||
### Q2: 免费版够用吗?
|
||
|
||
**答**:个人使用完全够用
|
||
|
||
- 存储:1GB(数万个订阅)
|
||
- 读取:10万次/天
|
||
- 写入:1000次/天
|
||
|
||
### Q3: 订阅会丢失吗?
|
||
|
||
**答**:不会
|
||
|
||
- 订阅配置永久保存
|
||
- 短链接有过期时间
|
||
- Worker 重新部署不影响数据
|
||
|
||
### Q4: 短链过期了怎么办?
|
||
|
||
**答**:两种方式
|
||
|
||
1. **续期**:延长有效期,链接不变
|
||
2. **换新链接**:生成新链接,旧链失效
|
||
|
||
推荐续期,无需更新客户端。
|
||
|
||
### Q5: 如何备份数据?
|
||
|
||
**答**:建议
|
||
|
||
1. 定期导出订阅列表(API 或页面)
|
||
2. 保存重要的 Clash URL
|
||
3. KV 数据 Cloudflare 自动备份
|
||
|
||
### Q6: 支持多少个订阅?
|
||
|
||
**答**:理论上无限
|
||
|
||
- 免费版存储 1GB
|
||
- 每个订阅约 1KB
|
||
- 可存储约 100 万个
|
||
|
||
实际建议:10-100个
|
||
|
||
### Q7: 如何查看日志?
|
||
|
||
**答**:使用 wrangler
|
||
|
||
```bash
|
||
wrangler tail
|
||
```
|
||
|
||
### Q8: 可以自定义域名吗?
|
||
|
||
**答**:可以
|
||
|
||
在 Worker 设置中添加自定义域名
|
||
|
||
### Q9: 数据安全吗?
|
||
|
||
**答**:安全
|
||
|
||
- KV 数据加密存储
|
||
- 账号权限隔离
|
||
- 建议不公开分享 Worker URL
|
||
|
||
### Q10: 转换失败怎么办?
|
||
|
||
**答**:检查
|
||
|
||
1. Clash URL 是否有效
|
||
2. 浏览器控制台错误
|
||
3. Worker 日志
|
||
|
||
---
|
||
|
||
## 🔄 更新日志
|
||
|
||
### v3.1 (2024-12-20) 🆕
|
||
|
||
**订阅类型支持**:
|
||
|
||
- ✨ 自动识别订阅类型(Clash / V2Ray)
|
||
- ✨ 双向转换:Clash ⇄ V2Ray
|
||
- ✨ 自定义输出类型(保存时选择)
|
||
- ✨ 短链支持类型参数 `?type=clash` 或 `?type=v2ray`
|
||
|
||
**灵活的有效期管理**:
|
||
|
||
- ✨ 支持多种时间单位:天(d)、月(m)、年(y)
|
||
- ✨ 支持无限期订阅
|
||
- ✨ 示例:`7d`(7天)、`3m`(3个月)、`1y`(1年)、`unlimited`(无限期)
|
||
|
||
**UI 改进**:
|
||
|
||
- ✨ 订阅卡片显示类型标签(Clash/V2Ray)
|
||
- ✨ 显示输出类型和转换方向
|
||
- ✨ 续期/换链接使用模态框界面(替代 prompt)
|
||
- ✨ 时间单位下拉选择(更友好)
|
||
|
||
**数据结构升级**:
|
||
|
||
- 📝 订阅对象新增 `subscriptionType` 和 `outputType` 字段
|
||
- 📝 短链存储改为 JSON 对象(包含类型信息)
|
||
- 📝 过期时间格式改为字符串(如 `7d`)
|
||
|
||
### v4.1 (2025-01)
|
||
|
||
**有效期选项简化**:
|
||
|
||
- ✨ 正式订阅有效期简化为:7天、1个月、3个月、1年、3年、长期
|
||
- ✨ 默认选择1年(更适合长期使用场景)
|
||
- ✨ 移除过于细分的有效期选项
|
||
|
||
**状态标记增强**:
|
||
|
||
- ✨ 快过期订阅(30天内到期)显示「快过期」橙色标记
|
||
- ✨ 已过期订阅显示「已过期」红色标记
|
||
- ✨ 便于用户及时续期或清理
|
||
|
||
**UI/UX 改进**:
|
||
|
||
- ✨ 自定义对话框替代浏览器默认 alert/confirm 弹窗
|
||
- ✨ 统一的模态框风格,更美观
|
||
- ✨ 清空订阅列表功能完善
|
||
|
||
**代码优化**:
|
||
|
||
- 📝 移除本地 KV 模拟代码(Wrangler 自带模拟)
|
||
- 📝 优化 API 路由顺序
|
||
- 📝 简化 clearAllSubscriptions 函数
|
||
|
||
### v3.0 (2024-12-20)
|
||
|
||
- ✨ 多订阅管理
|
||
- ✨ 短链生命周期管理
|
||
- ✨ 双标签界面
|
||
- ✨ 12个新API端点
|
||
|
||
### v2.0 (2025-12-19)
|
||
|
||
- ✨ 在线链接生成
|
||
- ✨ KV 短链接支持
|
||
|
||
### v1.0 (2025-12-19)
|
||
|
||
- 🎉 初始版本
|
||
- ✅ 基础转换功能
|
||
|
||
---
|
||
|
||
## 📞 技术支持
|
||
|
||
遇到问题?
|
||
|
||
1. 查看本文档的常见问题
|
||
2. 检查浏览器控制台
|
||
3. 查看 Worker 日志
|
||
|
||
**当前版本**: v3.1
|
||
**更新时间**: 2024-12-20
|
||
|
||
---
|
||
|
||
## 🆕 v3.1 新功能详细说明
|
||
|
||
### 1. 订阅类型自动识别
|
||
|
||
**功能说明**:
|
||
添加订阅时,系统会自动检测订阅链接的类型:
|
||
|
||
- Clash 格式:YAML 配置文件
|
||
- V2Ray 格式:Base64 编码的节点列表
|
||
|
||
**识别逻辑**:
|
||
|
||
1. 尝试下载订阅内容
|
||
2. 检查是否包含 "proxies:" → Clash
|
||
3. 尝试 Base64 解码 → V2Ray
|
||
4. 检查是否包含 vmess:// 等协议 → V2Ray
|
||
|
||
**使用场景**:
|
||
|
||
- 无需手动选择类型
|
||
- 支持混合使用多种订阅源
|
||
- 自动标记订阅类型
|
||
|
||
### 2. 双向转换功能
|
||
|
||
**支持的转换方向**:
|
||
|
||
- ✅ Clash → V2Ray(原有功能)
|
||
- ✅ V2Ray → Clash(新增功能)
|
||
- ✅ Clash → Clash(直接透传)
|
||
- ✅ V2Ray → V2Ray(直接透传)
|
||
|
||
**短链动态转换**:
|
||
|
||
```
|
||
短链:https://worker.com/s/abc123
|
||
- 默认:https://worker.com/s/abc123(使用配置的输出类型)
|
||
- Clash:https://worker.com/s/abc123?type=clash
|
||
- V2Ray:https://worker.com/s/abc123?type=v2ray
|
||
```
|
||
|
||
### 3. 灵活的有效期设置
|
||
|
||
**支持的格式**:
|
||
|
||
| 格式 | 说明 | 实际时长 |
|
||
|------|------|---------|
|
||
| `7` 或 `7d` | 7天 | 604,800 秒 |
|
||
| `30d` | 30天 | 2,592,000 秒 |
|
||
| `3m` | 3个月 | ~7,776,000 秒 |
|
||
| `1y` | 1年 | ~31,536,000 秒 |
|
||
| `unlimited` | 无限期 | 永不过期 |
|
||
|
||
### 4. API 变更说明
|
||
|
||
**创建订阅 API**:
|
||
|
||
```http
|
||
POST /api/subscriptions
|
||
{
|
||
"name": "订阅名",
|
||
"clashUrl": "https://...", // 支持 Clash 或 V2Ray
|
||
"expiration": "7d", // 支持 d/m/y/unlimited
|
||
"outputType": "auto" // auto/v2ray/clash
|
||
}
|
||
```
|
||
|
||
**续期/换链接 API**:
|
||
|
||
```http
|
||
POST /api/subscriptions/{id}/renew
|
||
POST /api/subscriptions/{id}/regenerate
|
||
{
|
||
"expiration": "7d", // 支持 d/m/y/unlimited
|
||
"outputType": "v2ray" // 可选:更改输出类型
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📝 v4.0 新特性详解
|
||
|
||
### 1. 全新的左右分栏界面
|
||
|
||
**界面结构**:
|
||
|
||
```
|
||
┌─────────────────────────────────────────────┐
|
||
│ 📡 订阅管理中心 │
|
||
├─────────────┬───────────────────────────────┤
|
||
│ 订阅列表 │ 订阅详情 │
|
||
│ [+新建] │ │
|
||
│ │ 订阅名称 [正式] [V2Ray] │
|
||
│ > 我的订阅 │ ─────────────────────── │
|
||
│ 机场A │ 原始链接: https://... │
|
||
│ 测试订阅 │ 输出类型: V2Ray │
|
||
│ │ 创建时间: 2025-01-01 │
|
||
│ │ 有效期: 2025-02-01 │
|
||
│ │ │
|
||
│ │ 短链接: https://... │
|
||
│ │ [复制] ✅ 正常使用中 │
|
||
│ │ │
|
||
│ │ [编辑] [续期] [换链接] [删除] │
|
||
└─────────────┴───────────────────────────────┘
|
||
```
|
||
|
||
**交互流程**:
|
||
|
||
1. 左侧列表点击订阅 → 右侧显示详情
|
||
2. 点击「新建」→ 弹出添加表单
|
||
3. 点击「编辑」→ 弹出编辑表单
|
||
4. 点击「续期」→ 弹出续期表单
|
||
5. 点击「换链接」→ 弹出换链接表单
|
||
|
||
### 2. 订阅分类:正式 vs 临时
|
||
|
||
#### 正式订阅(Permanent)
|
||
|
||
**特点**:
|
||
|
||
- ✅ 完整的功能和灵活性
|
||
- ✅ 支持全部有效期选项:1天-无限期
|
||
- ✅ 支持所有单位:天(d)、月(m)、年(y)、无限期
|
||
- ✅ 适合长期使用的订阅
|
||
|
||
**使用场景**:
|
||
|
||
- 主力机场订阅
|
||
- 公司专线
|
||
- 长期测试环境
|
||
- 需要永久保存的配置
|
||
|
||
#### 临时订阅(Temporary)
|
||
|
||
**特点**:
|
||
|
||
- ⚡ 限制有效期:只能选择 1天/3天/7天
|
||
- ⚡ 到期自动删除:短链过期后订阅配置也会被清理
|
||
- ⚡ 适合短期临时使用
|
||
|
||
**使用场景**:
|
||
|
||
- 临时测试链接
|
||
- 短期分享给朋友
|
||
- 一次性测试任务
|
||
- 避免数据积累
|
||
|
||
**对比表格**:
|
||
|
||
| 特性 | 正式订阅 | 临时订阅 |
|
||
|------|---------|---------|
|
||
| 有效期选项 | 1天-无限期 | 仅1天/3天/7天 |
|
||
| 自动删除 | ❌ 不删除 | ✅ 过期自动删除 |
|
||
| 续期 | ✅ 支持任意期限 | ✅ 仅支持1/3/7天 |
|
||
| 换链接 | ✅ 支持任意期限 | ✅ 仅支持1/3/7天 |
|
||
| 用途 | 长期使用 | 短期临时 |
|
||
|
||
### 3. 智能类型识别与双向转换
|
||
|
||
**自动识别逻辑**:
|
||
|
||
```javascript
|
||
// 添加订阅时自动检测
|
||
const url = "https://example.com/subscription"
|
||
// 系统会自动判断:
|
||
// - Clash: 包含 proxies, proxy-groups, rules 等字段
|
||
// - V2Ray: base64 编码的 vmess:// 或 vless:// 链接列表
|
||
```
|
||
|
||
**转换支持**:
|
||
|
||
| 原始类型 | 目标类型 | 操作 | 说明 |
|
||
|---------|---------|------|------|
|
||
| Clash | V2Ray | ✅ 转换 | 提取节点转为 V2Ray 格式 |
|
||
| V2Ray | Clash | ✅ 转换 | 解析节点生成 Clash 配置 |
|
||
| Clash | Clash | ⏩ 直传 | 不做转换,直接返回 |
|
||
| V2Ray | V2Ray | ⏩ 直传 | 不做转换,直接返回 |
|
||
|
||
**短链动态切换**:
|
||
|
||
```
|
||
短链地址:https://worker.com/s/abc123
|
||
|
||
可选参数:
|
||
- 默认(自动):https://worker.com/s/abc123
|
||
- 强制 Clash:https://worker.com/s/abc123?type=clash
|
||
- 强制 V2Ray:https://worker.com/s/abc123?type=v2ray
|
||
```
|
||
|
||
### 4. 多单位有效期系统
|
||
|
||
**支持的格式**:
|
||
|
||
| 输入格式 | 说明 | 实际时长(秒) |
|
||
|---------|------|---------------|
|
||
| `7` 或 `7d` | 7天 | 604,800 |
|
||
| `30d` | 30天 | 2,592,000 |
|
||
| `3m` | 3个月 | ~7,776,000 |
|
||
| `6m` | 6个月 | ~15,552,000 |
|
||
| `1y` | 1年 | ~31,536,000 |
|
||
| `unlimited` | 无限期 | null(永不过期) |
|
||
|
||
**解析规则**:
|
||
|
||
```javascript
|
||
// parseExpiration() 函数
|
||
"7d" → 7 * 86400 = 604800 秒
|
||
"3m" → 3 * 30 * 86400 = 7776000 秒
|
||
"1y" → 1 * 365 * 86400 = 31536000 秒
|
||
"unlimited" → null(不设置TTL)
|
||
```
|
||
|
||
**临时订阅限制**:
|
||
|
||
```javascript
|
||
// 临时订阅只接受以下值:
|
||
✅ "1d" - 1天
|
||
✅ "3d" - 3天
|
||
✅ "7d" - 7天
|
||
❌ "30d", "1m", "1y", "unlimited" - 不允许
|
||
```
|
||
|
||
### 5. API 完整说明
|
||
|
||
#### 创建订阅(新增 subscriptionMode)
|
||
|
||
```http
|
||
POST /api/subscriptions
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "订阅名称",
|
||
"clashUrl": "https://...", // 支持 Clash 或 V2Ray
|
||
"subscriptionMode": "permanent", // 新增:permanent/temporary
|
||
"expiration": "7d", // d/m/y/unlimited
|
||
"outputType": "auto" // auto/v2ray/clash
|
||
}
|
||
```
|
||
|
||
**Response**:
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"subscription": {
|
||
"id": "abc123xy",
|
||
"name": "我的订阅",
|
||
"clashUrl": "https://...",
|
||
"subscriptionType": "clash", // 自动识别的类型
|
||
"subscriptionMode": "permanent", // 订阅分类
|
||
"outputType": "v2ray",
|
||
"shortIds": {}, // 短链ID对象(按需生成)
|
||
"shortIdsExpiry": {}, // 短链过期时间对象
|
||
"createdAt": 1704067200000,
|
||
"expiresAt": 1704672000000,
|
||
"expiration": "7d",
|
||
"updatedAt": 1704067200000,
|
||
"isExpired": false
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 续期订阅(支持临时订阅限制)
|
||
|
||
```http
|
||
POST /api/subscriptions/{id}/renew
|
||
|
||
{
|
||
"expiration": "7d", // 临时订阅只能 1d/3d/7d
|
||
"outputType": "clash" // 可选:更改输出类型
|
||
}
|
||
```
|
||
|
||
#### 换新链接(支持临时订阅限制)
|
||
|
||
```http
|
||
POST /api/subscriptions/{id}/regenerate
|
||
|
||
{
|
||
"expiration": "30d", // 临时订阅只能 1d/3d/7d
|
||
"outputType": "v2ray" // 可选:更改输出类型
|
||
}
|
||
```
|
||
|
||
**临时订阅限制示例**:
|
||
|
||
```javascript
|
||
// 如果是临时订阅 + 传入不合法的期限
|
||
{
|
||
"subscriptionMode": "temporary",
|
||
"expiration": "30d" // ❌ 不允许
|
||
}
|
||
// 服务器会自动调整为默认值 "3d"
|
||
```
|
||
|
||
### 6. 临时订阅自动清理机制
|
||
|
||
**工作原理**:
|
||
|
||
1. 临时订阅的短链设置 KV TTL(Time To Live)
|
||
2. 到期后 Cloudflare 自动删除短链 KV 记录
|
||
3. 用户访问订阅列表时,检测到短链已失效
|
||
4. **未来增强**:可以添加定时任务删除过期的订阅配置记录
|
||
|
||
**当前状态**:
|
||
|
||
```javascript
|
||
// 短链过期后自动删除(由 KV TTL 机制保证)
|
||
const shortLinkData = {
|
||
url: subscription.clashUrl,
|
||
type: subscription.subscriptionType,
|
||
subscriptionId: id,
|
||
outputType: subscription.outputType
|
||
}
|
||
await KV.put(shortId, JSON.stringify(shortLinkData), {
|
||
expirationTtl: days * 86400 // 自动过期
|
||
})
|
||
|
||
// 订阅配置需要手动删除(访问时检测)
|
||
// TODO: 未来可添加 Cron Trigger 定期清理
|
||
```
|
||
|
||
---
|
||
|
||
## 🆕 版本历史
|
||
|
||
### v4.0(2024-12-20)⭐ 当前版本
|
||
|
||
**主要更新**:
|
||
|
||
- 🎨 全新左右分栏 UI 设计
|
||
- 📂 订阅分类:正式订阅 vs 临时订阅
|
||
- ⏱️ 临时订阅自动过期删除
|
||
- 🔧 临时订阅有效期限制(1/3/7天)
|
||
- 🏷️ 订阅列表显示分类标签
|
||
- 🎯 简化用户操作流程
|
||
- 📡 工具更名为「订阅管理中心」
|
||
|
||
### v3.1(2024-12-20)
|
||
|
||
**主要更新**:
|
||
|
||
- ✨ 智能订阅类型识别(Clash/V2Ray)
|
||
- 🔄 双向格式转换(Clash ⇄ V2Ray)
|
||
- 📅 灵活有效期单位(天/月/年/无限期)
|
||
- 🏷️ 订阅类型标签显示
|
||
- 🎨 改进的 UI 反馈
|
||
|
||
### v3.0(2024-11-XX)
|
||
|
||
**主要更新**:
|
||
|
||
- 📋 多订阅管理功能
|
||
- 🔗 短链生命周期管理
|
||
- 💾 KV 存储集成
|
||
- 📊 订阅列表视图
|
||
- ⚙️ 编辑/续期/换链接功能
|
||
|
||
### v2.0(2024-10-XX)
|
||
|
||
**主要更新**:
|
||
|
||
- 🌐 Web UI 界面
|
||
- ⚡ 快速转换模式
|
||
- 📥 直接下载功能
|
||
|
||
### v1.0(2024-09-XX)
|
||
|
||
**初始版本**:
|
||
|
||
- 🔧 基础 Clash → V2Ray 转换
|
||
- 📝 命令行工具
|
||
|
||
---
|
||
|
||
**当前版本**: v4.0
|
||
**更新时间**: 2024-12-20
|