music 兼容cloudflarer
This commit is contained in:
+55
-11
@@ -7,6 +7,9 @@ import { OpenListClient } from '@/lib/openlist.client';
|
|||||||
|
|
||||||
export const runtime = 'nodejs';
|
export const runtime = 'nodejs';
|
||||||
|
|
||||||
|
// 检测是否为 Cloudflare 环境
|
||||||
|
const isCloudflare = process.env.CF_PAGES === '1' || process.env.BUILD_TARGET === 'cloudflare';
|
||||||
|
|
||||||
// 服务器端内存缓存
|
// 服务器端内存缓存
|
||||||
const serverCache = {
|
const serverCache = {
|
||||||
methodConfigs: new Map<string, { data: any; timestamp: number }>(),
|
methodConfigs: new Map<string, { data: any; timestamp: number }>(),
|
||||||
@@ -249,11 +252,45 @@ async function executeMethod(
|
|||||||
const expressionRegex = /\{\{(.+?)\}\}/g;
|
const expressionRegex = /\{\{(.+?)\}\}/g;
|
||||||
return value.replace(expressionRegex, (match, expression) => {
|
return value.replace(expressionRegex, (match, expression) => {
|
||||||
try {
|
try {
|
||||||
// 创建一个函数来执行表达式,传入所有变量作为参数
|
// 在 Cloudflare 环境下,使用简单的表达式替换
|
||||||
// eslint-disable-next-line no-new-func
|
if (isCloudflare) {
|
||||||
const func = new Function(...Object.keys(evalContext), `return ${expression}`);
|
const expr = expression.trim();
|
||||||
const result = func(...Object.values(evalContext));
|
|
||||||
return String(result);
|
// 检查是否是单个变量(没有运算符)
|
||||||
|
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) {
|
} catch (err) {
|
||||||
console.error(`[executeMethod] 执行表达式失败: ${expression}`, err);
|
console.error(`[executeMethod] 执行表达式失败: ${expression}`, err);
|
||||||
return '0'; // 默认值
|
return '0'; // 默认值
|
||||||
@@ -312,12 +349,19 @@ async function executeMethod(
|
|||||||
|
|
||||||
// 5. 执行 transform 函数(如果有)
|
// 5. 执行 transform 函数(如果有)
|
||||||
if (config.transform) {
|
if (config.transform) {
|
||||||
try {
|
// 在 Cloudflare 环境下,将 transform 函数返回给前端执行
|
||||||
// eslint-disable-next-line no-eval
|
if (isCloudflare) {
|
||||||
const transformFn = eval(`(${config.transform})`);
|
// 将 transform 函数字符串附加到响应数据中
|
||||||
data = transformFn(data);
|
data.__transform = config.transform;
|
||||||
} catch (err) {
|
} else {
|
||||||
console.error('[executeMethod] Transform 函数执行失败:', err);
|
// 在 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) {
|
if (data.code === 0 && data.data?.data && data.data.data.length > 0) {
|
||||||
const songData = data.data.data[0];
|
const songData = data.data.data[0];
|
||||||
@@ -357,6 +359,23 @@ export default function MusicPage() {
|
|||||||
}
|
}
|
||||||
}, [playRecords, pendingSongToPlay]);
|
}, [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) => {
|
const loadPlaylists = async (source: string) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -364,7 +383,9 @@ export default function MusicPage() {
|
|||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`/api/music?action=toplists&platform=${source}`
|
`/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 : []);
|
setPlaylists(Array.isArray(data) ? data : []);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -382,7 +403,9 @@ export default function MusicPage() {
|
|||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`/api/music?action=toplist&platform=${currentSource}&id=${playlistId}`
|
`/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 : []);
|
setSongs(Array.isArray(data) ? data : []);
|
||||||
setCurrentPlaylistTitle(playlistName);
|
setCurrentPlaylistTitle(playlistName);
|
||||||
@@ -404,7 +427,9 @@ export default function MusicPage() {
|
|||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`/api/music?action=search&platform=${currentSource}&keyword=${encodeURIComponent(searchKeyword)}&page=1&pageSize=20`
|
`/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 : []);
|
setSongs(Array.isArray(data) ? data : []);
|
||||||
setCurrentPlaylistTitle(`搜索: ${searchKeyword}`);
|
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: [...] } }
|
// TuneHub 返回格式: { code: 0, data: { data: [...] } }
|
||||||
if (data.code === 0 && data.data?.data && data.data.data.length > 0) {
|
if (data.code === 0 && data.data?.data && data.data.data.length > 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user