diff --git a/README.md b/README.md
index ee5d51c..0b66da1 100644
--- a/README.md
+++ b/README.md
@@ -164,6 +164,9 @@ Telegram交流群:[@CMLiussss](https://t.me/CMLiussss),**感谢[Alice Networ
# 注意事项
+### 开启在线编辑优选列表
+- 绑定名为`KV`的KV空间,即可在无`SUB`的前提下,在配置页实现在线编辑`ADD`与`ADDAPI`优选列表;
+
### **关于`KEY`与`UUID`:**
- 填入`KEY`变量后,将停用`UUID`变量,请确保**二者选其一使用**!
1. 填写`KEY`后,您的**永久订阅**地址为:`https://[YOUR-URL]/[YOUR-KEY]`;
diff --git a/明文源码.js b/明文源码.js
index af03cfb..5dce8ba 100644
--- a/明文源码.js
+++ b/明文源码.js
@@ -45,6 +45,7 @@ let userIDTime = "";
let proxyIPPool = [];
let path = '/?ed=2560';
let 动态UUID;
+let link = [];
export default {
async fetch(request, env, ctx) {
try {
@@ -123,7 +124,7 @@ export default {
FileName = env.SUBNAME || FileName;
subEmoji = env.SUBEMOJI || env.EMOJI || subEmoji;
if (subEmoji == '0') subEmoji = 'false';
-
+ if (env.LINK) link = await 整理(env.LINK) ;
sub = env.SUB || sub;
subConverter = env.SUBAPI || subConverter;
if (subConverter.includes("http://") ){
@@ -160,6 +161,9 @@ export default {
} else if (路径 == `/${fakeUserID}`) {
const fakeConfig = await 生成配置信息(userID, request.headers.get('Host'), sub, 'CF-Workers-SUB', RproxyIP, url, env);
return new Response(`${fakeConfig}`, { status: 200 });
+ } else if (路径 == `/${动态UUID}/add` || 路径 == `/${userID}/add`) {
+ const html = await KV(request, env);
+ return html;
} else if (路径 == `/${动态UUID}` || 路径 == `/${userID}`) {
await sendMessage(`#获取订阅 ${FileName}`, request.headers.get('CF-Connecting-IP'), `UA: ${UA}\n域名: ${url.hostname}\n入口: ${url.pathname + url.search}`);
const 维列斯Config = await 生成配置信息(userID, request.headers.get('Host'), sub, UA, RproxyIP, url, env);
@@ -173,10 +177,10 @@ export default {
let total = 24 * 1099511627776 ;
if (userAgent && userAgent.includes('mozilla')){
- return new Response(`${维列斯Config}`, {
+ return new Response(`
${维列斯Config}
`, {
status: 200,
headers: {
- "Content-Type": "text/plain;charset=utf-8",
+ "Content-Type": "text/html;charset=utf-8",
"Profile-Update-Interval": "6",
"Subscription-Userinfo": `upload=${pagesSum}; download=${workersSum}; total=${total}; expire=${expire}`,
}
@@ -730,7 +734,7 @@ async function remoteSocketToWS(remoteSocket, webSocket, 维列斯ResponseHeader
function base64ToArrayBuffer(base64Str) {
// 如果输入为空,直接返回空结果
if (!base64Str) {
- return { error: null };
+ return { earlyData: undefined, error: null };
}
try {
// Go 语言使用了 URL 安全的 Base64 变体(RFC 4648)
@@ -751,7 +755,7 @@ function base64ToArrayBuffer(base64Str) {
return { earlyData: arryBuffer.buffer, error: null };
} catch (error) {
// 如果在任何步骤中出现错误(如非法 Base64 字符),则返回错误
- return { error };
+ return { earlyData: undefined, error };
}
}
@@ -1193,21 +1197,8 @@ function 配置信息(UUID, 域名地址) {
传输层安全 = ['',false];
}
- const 威图瑞 = `${协议类型}://${用户ID}@${地址}:${端口}\u003f\u0065\u006e\u0063\u0072\u0079`+'p'+`${atob('dGlvbj0=') + 加密方式}\u0026\u0073\u0065\u0063\u0075\u0072\u0069\u0074\u0079\u003d${传输层安全[0]}&sni=${SNI}&fp=${指纹}&type=${传输层协议}&host=${伪装域名}&path=${encodeURIComponent(路径)}#${encodeURIComponent(别名)}`;
- const 猫猫猫 = `- type: ${协议类型}
- name: ${FileName}
- server: ${地址}
- port: ${端口}
- uuid: ${用户ID}
- network: ${传输层协议}
- tls: ${传输层安全[1]}
- udp: false
- sni: ${SNI}
- client-fingerprint: ${指纹}
- ws-opts:
- path: "${路径}"
- headers:
- host: ${伪装域名}`;
+ const 威图瑞 = `${协议类型}://${用户ID}@${地址}:${端口}\u003f\u0065\u006e\u0063\u0072\u0079`+'p'+`${atob('dGlvbj0=') + 加密方式}\u0026\u0073\u0065\u0063\u0075\u0072\u0069\u0074\u0079\u003d${传输层安全[0]}&sni=${SNI}&fp=${指纹}&type=${传输层协议}&host=${伪装域名}&path=${encodeURIComponent(路径)}#${encodeURIComponent(别名)}`;
+ const 猫猫猫 = `- {name: ${FileName}, server: ${地址}, port: ${端口}, type: ${协议类型}, uuid: ${用户ID}, tls: ${传输层安全[1]}, alpn: [h3], udp: false, sni: ${SNI}, tfo: false, skip-cert-verify: true, servername: ${伪装域名}, client-fingerprint: ${指纹}, network: ${传输层协议}, ws-opts: {path: "${路径}", headers: {${伪装域名}}}}`;
return [威图瑞,猫猫猫];
}
@@ -1228,46 +1219,64 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
}
const subs = await 整理(sub);
if (subs.length > 1) sub = subs[0];
-
- } else if ((addresses.length + addressesapi.length + addressesnotls.length + addressesnotlsapi.length + addressescsv.length) == 0){
- // 定义 Cloudflare IP 范围的 CIDR 列表
- let cfips = [
- '103.21.244.0/23',
- '104.16.0.0/13',
- '104.24.0.0/14',
- '172.64.0.0/14',
- '103.21.244.0/23',
- '104.16.0.0/14',
- '104.24.0.0/15',
- '141.101.64.0/19',
- '172.64.0.0/14',
- '188.114.96.0/21',
- '190.93.240.0/21',
- ];
-
- // 生成符合给定 CIDR 范围的随机 IP 地址
- function generateRandomIPFromCIDR(cidr) {
- const [base, mask] = cidr.split('/');
- const baseIP = base.split('.').map(Number);
- const subnetMask = 32 - parseInt(mask, 10);
- const maxHosts = Math.pow(2, subnetMask) - 1;
- const randomHost = Math.floor(Math.random() * maxHosts);
-
- const randomIP = baseIP.map((octet, index) => {
- if (index < 2) return octet;
- if (index === 2) return (octet & (255 << (subnetMask - 8))) + ((randomHost >> 8) & 255);
- return (octet & (255 << subnetMask)) + (randomHost & 255);
- });
-
- return randomIP.join('.');
+ } else {
+ if (env.KV){
+ const KV空间优选列表 = await env.KV.get('/ADD.txt');
+ if (KV空间优选列表) {
+ const KV空间优选列表数组 = await 整理(KV空间优选列表);
+ for (const item of KV空间优选列表数组) {
+ if (item.startsWith('https://')) {
+ addressesapi.push(item);
+ } else if (item.includes('://')) {
+ link.push(item);
+ } else {
+ addresses.push(item);
+ }
+ }
+ }
}
- addresses = addresses.concat('127.0.0.1:1234#CFnat');
- if (hostName.includes(".workers.dev")) {
- addressesnotls = addressesnotls.concat(cfips.map(cidr => generateRandomIPFromCIDR(cidr) + '#CF随机节点'));
- } else {
- addresses = addresses.concat(cfips.map(cidr => generateRandomIPFromCIDR(cidr) + '#CF随机节点'));
+
+ if ((addresses.length + addressesapi.length + addressesnotls.length + addressesnotlsapi.length + addressescsv.length) == 0){
+ // 定义 Cloudflare IP 范围的 CIDR 列表
+ let cfips = [
+ '103.21.244.0/23',
+ '104.16.0.0/13',
+ '104.24.0.0/14',
+ '172.64.0.0/14',
+ '103.21.244.0/23',
+ '104.16.0.0/14',
+ '104.24.0.0/15',
+ '141.101.64.0/19',
+ '172.64.0.0/14',
+ '188.114.96.0/21',
+ '190.93.240.0/21',
+ ];
+
+ // 生成符合给定 CIDR 范围的随机 IP 地址
+ function generateRandomIPFromCIDR(cidr) {
+ const [base, mask] = cidr.split('/');
+ const baseIP = base.split('.').map(Number);
+ const subnetMask = 32 - parseInt(mask, 10);
+ const maxHosts = Math.pow(2, subnetMask) - 1;
+ const randomHost = Math.floor(Math.random() * maxHosts);
+
+ const randomIP = baseIP.map((octet, index) => {
+ if (index < 2) return octet;
+ if (index === 2) return (octet & (255 << (subnetMask - 8))) + ((randomHost >> 8) & 255);
+ return (octet & (255 << subnetMask)) + (randomHost & 255);
+ });
+
+ return randomIP.join('.');
+ }
+ addresses = addresses.concat('127.0.0.1:1234#CFnat');
+ if (hostName.includes(".workers.dev")) {
+ addressesnotls = addressesnotls.concat(cfips.map(cidr => generateRandomIPFromCIDR(cidr) + '#CF随机节点'));
+ } else {
+ addresses = addresses.concat(cfips.map(cidr => generateRandomIPFromCIDR(cidr) + '#CF随机节点'));
+ }
}
}
+
const uuid = (_url.pathname == `/${动态UUID}`) ? 动态UUID : userID;
const userAgent = UA.toLowerCase();
const Config = 配置信息(userID , hostName);
@@ -1307,73 +1316,86 @@ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env
let socks5List = '';
if (go2Socks5s.length > 0 && enableSocks ) {
socks5List = `${decodeURIComponent('SOCKS5%EF%BC%88%E7%99%BD%E5%90%8D%E5%8D%95%EF%BC%89%3A%20')}`;
- if (go2Socks5s.includes(atob('YWxsIGlu'))||go2Socks5s.includes(atob('Kg=='))) socks5List += `${decodeURIComponent('%E6%89%80%E6%9C%89%E6%B5%81%E9%87%8F')}\n`;
- else socks5List += `\n ${go2Socks5s.join('\n ')}\n`;
+ if (go2Socks5s.includes(atob('YWxsIGlu'))||go2Socks5s.includes(atob('Kg=='))) socks5List += `${decodeURIComponent('%E6%89%80%E6%9C%89%E6%B5%81%E9%87%8F')}
`;
+ else socks5List += `
${go2Socks5s.join('
')}
`;
}
- let 订阅器 = '\n';
+ let 订阅器 = '
';
if (sub) {
- if (enableSocks) 订阅器 += `CFCDN(访问方式): Socks5\n ${newSocks5s.join('\n ')}\n${socks5List}`;
- else if (proxyIP && proxyIP != '') 订阅器 += `CFCDN(访问方式): ProxyIP\n ${proxyIPs.join('\n ')}\n`;
- else if (RproxyIP == 'true') 订阅器 += `CFCDN(访问方式): 自动获取ProxyIP\n`;
- else 订阅器 += `CFCDN(访问方式): 无法访问, 需要您设置 proxyIP/PROXYIP !!!\n`
- 订阅器 += `\nSUB(优选订阅生成器): ${sub}`;
+ if (enableSocks) 订阅器 += `CFCDN(访问方式): Socks5
${newSocks5s.join('
')}
${socks5List}`;
+ else if (proxyIP && proxyIP != '') 订阅器 += `CFCDN(访问方式): ProxyIP
${proxyIPs.join('
')}
`;
+ else if (RproxyIP == 'true') 订阅器 += `CFCDN(访问方式): 自动获取ProxyIP
`;
+ else 订阅器 += `CFCDN(访问方式): 无法访问, 需要您设置 proxyIP/PROXYIP !!!
`
+ 订阅器 += `
SUB(优选订阅生成器): ${sub}`;
} else {
- if (enableSocks) 订阅器 += `CFCDN(访问方式): Socks5\n ${newSocks5s.join('\n ')}\n${socks5List}`;
- else if (proxyIP && proxyIP != '') 订阅器 += `CFCDN(访问方式): ProxyIP\n ${proxyIPs.join('\n ')}\n`;
- else 订阅器 += `CFCDN(访问方式): 无法访问, 需要您设置 proxyIP/PROXYIP !!!\n`;
- 订阅器 += `\n您的订阅内容由 内置 addresses/ADD* 参数变量提供\n`;
- if (addresses.length > 0) 订阅器 += `ADD(TLS优选域名&IP): \n ${addresses.join('\n ')}\n`;
- if (addressesnotls.length > 0) 订阅器 += `ADDNOTLS(noTLS优选域名&IP): \n ${addressesnotls.join('\n ')}\n`;
- if (addressesapi.length > 0) 订阅器 += `ADDAPI(TLS优选域名&IP 的 API): \n ${addressesapi.join('\n ')}\n`;
- if (addressesnotlsapi.length > 0) 订阅器 += `ADDNOTLSAPI(noTLS优选域名&IP 的 API): \n ${addressesnotlsapi.join('\n ')}\n`;
- if (addressescsv.length > 0) 订阅器 += `ADDCSV(IPTest测速csv文件 限速 ${DLS} ): \n ${addressescsv.join('\n ')}\n`;
+ if (enableSocks) 订阅器 += `CFCDN(访问方式): Socks5
${newSocks5s.join('
')}
${socks5List}`;
+ else if (proxyIP && proxyIP != '') 订阅器 += `CFCDN(访问方式): ProxyIP
${proxyIPs.join('
')}
`;
+ else 订阅器 += `CFCDN(访问方式): 无法访问, 需要您设置 proxyIP/PROXYIP !!!
`;
+ let 判断是否绑定KV空间 = '';
+ if (env.KV) 判断是否绑定KV空间 = ` 编辑优选列表`;
+ 订阅器 += `
您的订阅内容由 内置 addresses/ADD* 参数变量提供${判断是否绑定KV空间}
`;
+ if (addresses.length > 0) 订阅器 += `ADD(TLS优选域名&IP):
${addresses.join('
')}
`;
+ if (addressesnotls.length > 0) 订阅器 += `ADDNOTLS(noTLS优选域名&IP):
${addressesnotls.join('
')}
`;
+ if (addressesapi.length > 0) 订阅器 += `ADDAPI(TLS优选域名&IP 的 API):
${addressesapi.join('
')}
`;
+ if (addressesnotlsapi.length > 0) 订阅器 += `ADDNOTLSAPI(noTLS优选域名&IP 的 API):
${addressesnotlsapi.join('
')}
`;
+ if (addressescsv.length > 0) 订阅器 += `ADDCSV(IPTest测速csv文件 限速 ${DLS} ):
${addressescsv.join('
')}
`;
}
if (动态UUID && _url.pathname !== `/${动态UUID}`) 订阅器 = '';
- else 订阅器 += `\nSUBAPI(订阅转换后端): ${subProtocol}://${subConverter}\nSUBCONFIG(订阅转换配置文件): ${subConfig}`;
- const 动态UUID信息 = (uuid != userID) ? `TOKEN: ${uuid}\nUUIDNow: ${userID}\nUUIDLow: ${userIDLow}\n${userIDTime}TIME(动态UUID有效时间): ${有效时间} 天\nUPTIME(动态UUID更新时间): ${更新时间} 时(北京时间)\n\n` : `${userIDTime}`;
- return `
-################################################################
-Subscribe / sub 订阅地址, 支持 Base64、clash-meta、sing-box 订阅格式
----------------------------------------------------------------
-快速自适应订阅地址:
-https://${proxyhost}${hostName}/${uuid}
-https://${proxyhost}${hostName}/${uuid}?sub
+ else 订阅器 += `
SUBAPI(订阅转换后端): ${subProtocol}://${subConverter}
SUBCONFIG(订阅转换配置文件): ${subConfig}`;
+ const 动态UUID信息 = (uuid != userID) ? `TOKEN: ${uuid}
UUIDNow: ${userID}
UUIDLow: ${userIDLow}
${userIDTime}TIME(动态UUID有效时间): ${有效时间} 天
UPTIME(动态UUID更新时间): ${更新时间} 时(北京时间)
` : `${userIDTime}`;
+ const 节点配置页 = `
+ ################################################################
+ Subscribe / sub 订阅地址, 支持 Base64、clash-meta、sing-box 订阅格式
+ ---------------------------------------------------------------
+ 自适应订阅地址:
+ https://${proxyhost}${hostName}/${uuid}
+ https://${proxyhost}${hostName}/${uuid}?sub
+
+ Base64订阅地址:
+ https://${proxyhost}${hostName}/${uuid}?b64
+ https://${proxyhost}${hostName}/${uuid}?base64
+
+ clash订阅地址:
+ https://${proxyhost}${hostName}/${uuid}?clash
+
+ singbox订阅地址:
+ https://${proxyhost}${hostName}/${uuid}?sb
+ https://${proxyhost}${hostName}/${uuid}?singbox
-Base64订阅地址:
-https://${proxyhost}${hostName}/${uuid}?b64
-https://${proxyhost}${hostName}/${uuid}?base64
-
-clash订阅地址:
-https://${proxyhost}${hostName}/${uuid}?clash
-
-singbox订阅地址:
-https://${proxyhost}${hostName}/${uuid}?sb
-https://${proxyhost}${hostName}/${uuid}?singbox
----------------------------------------------------------------
-################################################################
-${FileName} 配置信息
----------------------------------------------------------------
-${动态UUID信息}HOST: ${hostName}
-UUID: ${userID}
-FKID: ${fakeUserID}
-UA: ${UA}
-${订阅器}
----------------------------------------------------------------
-################################################################
-v2ray
----------------------------------------------------------------
-${v2ray}
----------------------------------------------------------------
-################################################################
-clash-meta
----------------------------------------------------------------
-${clash}
----------------------------------------------------------------
-################################################################
-${decodeURIComponent(atob('dGVsZWdyYW0lMjAlRTQlQkElQTQlRTYlQjUlODElRTclQkUlQTQlMjAlRTYlOEElODAlRTYlOUMlQUYlRTUlQTQlQTclRTQlQkQlQUMlN0UlRTUlOUMlQTglRTclQkElQkYlRTUlOEYlOTElRTclODklOEMhCmh0dHBzJTNBJTJGJTJGdC5tZSUyRkNNTGl1c3NzcwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KZ2l0aHViJTIwJUU5JUExJUI5JUU3JTlCJUFFJUU1JTlDJUIwJUU1JTlEJTgwJTIwU3RhciFTdGFyIVN0YXIhISEKaHR0cHMlM0ElMkYlMkZnaXRodWIuY29tJTJGY21saXUlMkZlZGdldHVubmVsCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQolMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjM='))}
-`;
+
+ ---------------------------------------------------------------
+ ################################################################
+ ${FileName} 配置信息
+ ---------------------------------------------------------------
+ ${动态UUID信息}HOST: ${hostName}
+ UUID: ${userID}
+ FKID: ${fakeUserID}
+ UA: ${UA}
+ ${订阅器}
+ ---------------------------------------------------------------
+ ################################################################
+ v2ray
+ ---------------------------------------------------------------
+ ${v2ray}
+ ---------------------------------------------------------------
+ ################################################################
+ clash-meta
+ ---------------------------------------------------------------
+ ${clash}
+ ---------------------------------------------------------------
+ ################################################################
+ ${decodeURIComponent(atob('dGVsZWdyYW0lMjAlRTQlQkElQTQlRTYlQjUlODElRTclQkUlQTQlMjAlRTYlOEElODAlRTYlOUMlQUYlRTUlQTQlQTclRTQlQkQlQUMlN0UlRTUlOUMlQTglRTclQkElQkYlRTUlOEYlOTElRTclODklOEMhJTNDYnIlM0UKJTNDYSUyMGhyZWYlM0QlMjdodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlMjclM0VodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlM0MlMkZhJTNFJTNDYnIlM0UKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJTNDYnIlM0UKZ2l0aHViJTIwJUU5JUExJUI5JUU3JTlCJUFFJUU1JTlDJUIwJUU1JTlEJTgwJTIwU3RhciFTdGFyIVN0YXIhISElM0NiciUzRQolM0NhJTIwaHJlZiUzRCUyN2h0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRmNtbGl1JTJGZWRnZXR1bm5lbCUyNyUzRWh0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRmNtbGl1JTJGZWRnZXR1bm5lbCUzQyUyRmElM0UlM0NiciUzRQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0lM0NiciUzRQolMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjM='))}
+ `;
+ return 节点配置页;
} else {
if (typeof fetch != 'function') {
return 'Error: fetch is not available in this environment.';
@@ -1749,6 +1771,7 @@ function 生成本地订阅(host,UUID,noTLS,newAddressesapi,newAddressescsv,newA
let base64Response = responseBody; // 重新进行 Base64 编码
if(noTLS == 'true') base64Response += `\n${notlsresponseBody}`;
+ if (link.length > 0) base64Response += '\n' + link.join('\n');
return btoa(base64Response);
}
@@ -1832,4 +1855,165 @@ function 生成动态UUID(密钥) {
const 到期时间字符串 = `到期时间(UTC): ${到期时间UTC.toISOString().slice(0, 19).replace('T', ' ')} (UTC+8): ${结束时间.toISOString().slice(0, 19).replace('T', ' ')}\n`;
return Promise.all([当前UUIDPromise, 上一个UUIDPromise, 到期时间字符串]);
+}
+
+async function KV(request, env) {
+ try {
+ // POST请求处理
+ if (request.method === "POST") {
+ if (!env.KV) return new Response("未绑定KV空间", { status: 400 });
+ try {
+ const content = await request.text();
+ await env.KV.put('/ADD.txt', content);
+ return new Response("保存成功");
+ } catch (error) {
+ console.error('保存KV时发生错误:', error);
+ return new Response("保存失败: " + error.message, { status: 500 });
+ }
+ }
+
+ // GET请求部分
+ let content = '';
+ let hasKV = !!env.KV;
+
+ if (hasKV) {
+ try {
+ content = await env.KV.get('/ADD.txt') || '';
+ } catch (error) {
+ console.error('读取KV时发生错误:', error);
+ content = '读取数据时发生错误: ' + error.message;
+ }
+ }
+
+ const html = `
+
+
+
+ KV编辑器
+
+
+
+
+
+
+ ${hasKV ? `
+
+
+
+
+
+
+ ` : '
未绑定KV空间
'}
+
+
+
+
+
+ `;
+
+ return new Response(html, {
+ headers: { "Content-Type": "text/html;charset=utf-8" }
+ });
+ } catch (error) {
+ console.error('处理请求时发生错误:', error);
+ return new Response("服务器错误: " + error.message, {
+ status: 500,
+ headers: { "Content-Type": "text/plain;charset=utf-8" }
+ });
+ }
}
\ No newline at end of file