music 兼容cloudflarer
This commit is contained in:
+55
-11
@@ -7,6 +7,9 @@ import { OpenListClient } from '@/lib/openlist.client';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
// 检测是否为 Cloudflare 环境
|
||||
const isCloudflare = process.env.CF_PAGES === '1' || process.env.BUILD_TARGET === 'cloudflare';
|
||||
|
||||
// 服务器端内存缓存
|
||||
const serverCache = {
|
||||
methodConfigs: new Map<string, { data: any; timestamp: number }>(),
|
||||
@@ -249,11 +252,45 @@ async function executeMethod(
|
||||
const expressionRegex = /\{\{(.+?)\}\}/g;
|
||||
return value.replace(expressionRegex, (match, expression) => {
|
||||
try {
|
||||
// 创建一个函数来执行表达式,传入所有变量作为参数
|
||||
// eslint-disable-next-line no-new-func
|
||||
const func = new Function(...Object.keys(evalContext), `return ${expression}`);
|
||||
const result = func(...Object.values(evalContext));
|
||||
return String(result);
|
||||
// 在 Cloudflare 环境下,使用简单的表达式替换
|
||||
if (isCloudflare) {
|
||||
const expr = expression.trim();
|
||||
|
||||
// 检查是否是单个变量(没有运算符)
|
||||
if (evalContext.hasOwnProperty(expr)) {
|
||||
// 直接返回变量值
|
||||
return String(evalContext[expr]);
|
||||
}
|
||||
|
||||
// 处理包含运算的表达式(如 page - 1)
|
||||
let result: any = expr;
|
||||
|
||||
// 替换变量为其值
|
||||
for (const [key, val] of Object.entries(evalContext)) {
|
||||
const regex = new RegExp(`\\b${key}\\b`, 'g');
|
||||
// 对于数字直接替换,对于字符串需要加引号以便 eval
|
||||
const replacement = typeof val === 'number' ? String(val) : `"${String(val).replace(/"/g, '\\"')}"`;
|
||||
result = result.replace(regex, replacement);
|
||||
}
|
||||
|
||||
// 尝试计算表达式
|
||||
try {
|
||||
// eslint-disable-next-line no-eval
|
||||
result = eval(result);
|
||||
} catch (err) {
|
||||
console.error(`[executeMethod] Cloudflare 环境执行表达式失败: ${expr}`, err);
|
||||
// 如果计算失败,尝试直接返回替换后的结果(去掉可能的引号)
|
||||
result = result.replace(/^["']|["']$/g, '');
|
||||
}
|
||||
|
||||
return String(result);
|
||||
} else {
|
||||
// 在 Node.js 环境下,使用 Function 构造器
|
||||
// eslint-disable-next-line no-new-func
|
||||
const func = new Function(...Object.keys(evalContext), `return ${expression}`);
|
||||
const result = func(...Object.values(evalContext));
|
||||
return String(result);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`[executeMethod] 执行表达式失败: ${expression}`, err);
|
||||
return '0'; // 默认值
|
||||
@@ -312,12 +349,19 @@ async function executeMethod(
|
||||
|
||||
// 5. 执行 transform 函数(如果有)
|
||||
if (config.transform) {
|
||||
try {
|
||||
// eslint-disable-next-line no-eval
|
||||
const transformFn = eval(`(${config.transform})`);
|
||||
data = transformFn(data);
|
||||
} catch (err) {
|
||||
console.error('[executeMethod] Transform 函数执行失败:', err);
|
||||
// 在 Cloudflare 环境下,将 transform 函数返回给前端执行
|
||||
if (isCloudflare) {
|
||||
// 将 transform 函数字符串附加到响应数据中
|
||||
data.__transform = config.transform;
|
||||
} else {
|
||||
// 在 Node.js 环境下,直接执行 transform
|
||||
try {
|
||||
// eslint-disable-next-line no-eval
|
||||
const transformFn = eval(`(${config.transform})`);
|
||||
data = transformFn(data);
|
||||
} catch (err) {
|
||||
console.error('[executeMethod] Transform 函数执行失败:', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-5
@@ -267,7 +267,9 @@ export default function MusicPage() {
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await parseResponse.json();
|
||||
let data = await parseResponse.json();
|
||||
// 执行前端 transform(如果有)
|
||||
data = executeTransform(data);
|
||||
|
||||
if (data.code === 0 && data.data?.data && data.data.data.length > 0) {
|
||||
const songData = data.data.data[0];
|
||||
@@ -357,6 +359,23 @@ export default function MusicPage() {
|
||||
}
|
||||
}, [playRecords, pendingSongToPlay]);
|
||||
|
||||
// 执行前端 transform(用于 Cloudflare 环境)
|
||||
const executeTransform = (data: any) => {
|
||||
if (data && typeof data === 'object' && data.__transform) {
|
||||
try {
|
||||
// eslint-disable-next-line no-eval
|
||||
const transformFn = eval(`(${data.__transform})`);
|
||||
delete data.__transform; // 删除 transform 字段
|
||||
return transformFn(data);
|
||||
} catch (err) {
|
||||
console.error('[Frontend] Transform 函数执行失败:', err);
|
||||
delete data.__transform;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
// 加载排行榜列表
|
||||
const loadPlaylists = async (source: string) => {
|
||||
setLoading(true);
|
||||
@@ -364,7 +383,9 @@ export default function MusicPage() {
|
||||
const response = await fetch(
|
||||
`/api/music?action=toplists&platform=${source}`
|
||||
);
|
||||
const data = await response.json();
|
||||
let data = await response.json();
|
||||
// 执行前端 transform(如果有)
|
||||
data = executeTransform(data);
|
||||
// 确保返回的是数组
|
||||
setPlaylists(Array.isArray(data) ? data : []);
|
||||
} catch (error) {
|
||||
@@ -382,7 +403,9 @@ export default function MusicPage() {
|
||||
const response = await fetch(
|
||||
`/api/music?action=toplist&platform=${currentSource}&id=${playlistId}`
|
||||
);
|
||||
const data = await response.json();
|
||||
let data = await response.json();
|
||||
// 执行前端 transform(如果有)
|
||||
data = executeTransform(data);
|
||||
// 确保返回的是数组
|
||||
setSongs(Array.isArray(data) ? data : []);
|
||||
setCurrentPlaylistTitle(playlistName);
|
||||
@@ -404,7 +427,9 @@ export default function MusicPage() {
|
||||
const response = await fetch(
|
||||
`/api/music?action=search&platform=${currentSource}&keyword=${encodeURIComponent(searchKeyword)}&page=1&pageSize=20`
|
||||
);
|
||||
const data = await response.json();
|
||||
let data = await response.json();
|
||||
// 执行前端 transform(如果有)
|
||||
data = executeTransform(data);
|
||||
// 确保返回的是数组
|
||||
setSongs(Array.isArray(data) ? data : []);
|
||||
setCurrentPlaylistTitle(`搜索: ${searchKeyword}`);
|
||||
@@ -743,7 +768,9 @@ export default function MusicPage() {
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
let data = await response.json();
|
||||
// 执行前端 transform(如果有)
|
||||
data = executeTransform(data);
|
||||
|
||||
// TuneHub 返回格式: { code: 0, data: { data: [...] } }
|
||||
if (data.code === 0 && data.data?.data && data.data.data.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user