🔧 Worker 更新代码
把下面代码贴到 Cloudflare Workers 编辑器,点 Deploy。
// ================================================================
// School Panda 统一云同步 Worker
// 同时支持:课时系统 + 课程表系统
// 绑定 KV: SP_KV,环境变量: SYNC_KEY
//
// 数据 key:
// 课时系统 → school_panda_data (原有,不变)
// 课程表 → school_panda_timetable_data (新增)
// ================================================================
const ALLOWED_KEYS = ["school_panda_data", "school_panda_timetable_data"];
export default {
async fetch(request, env) {
const cors = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, X-Sync-Key, X-Device-Id, X-Data-Key",
"Access-Control-Max-Age": "86400",
};
if (request.method === "OPTIONS") {
return new Response(null, { headers: cors });
}
// 密钥验证
const key = request.headers.get("X-Sync-Key");
if (!key || key !== env.SYNC_KEY) {
return new Response(JSON.stringify({ error: "unauthorized" }), {
status: 401,
headers: { ...cors, "Content-Type": "application/json" },
});
}
// 读取 dataKey(由客户端指定,默认兼容课时系统)
const url = new URL(request.url);
const dataKey = request.headers.get("X-Data-Key")
|| url.searchParams.get("dataKey")
|| "school_panda_data";
// 安全白名单,防止乱写 KV
if (!ALLOWED_KEYS.includes(dataKey)) {
return new Response(JSON.stringify({ error: "invalid dataKey" }), {
status: 400,
headers: { ...cors, "Content-Type": "application/json" },
});
}
try {
if (request.method === "GET") {
const stored = await env.SP_KV.get(dataKey, "json");
return new Response(JSON.stringify(stored || { data: null, modified: 0 }), {
headers: { ...cors, "Content-Type": "application/json" },
});
}
if (request.method === "POST") {
const body = await request.json();
if (!body || !body.data) {
return new Response(JSON.stringify({ error: "invalid body" }), {
status: 400,
headers: { ...cors, "Content-Type": "application/json" },
});
}
const payload = {
data: body.data,
modified: body.modified || Date.now(),
device: body.device || "unknown",
updatedAt: Date.now(),
};
await env.SP_KV.put(dataKey, JSON.stringify(payload));
return new Response(JSON.stringify({ ok: true, modified: payload.modified }), {
headers: { ...cors, "Content-Type": "application/json" },
});
}
return new Response(JSON.stringify({ error: "method not allowed" }), {
status: 405,
headers: { ...cors, "Content-Type": "application/json" },
});
} catch (e) {
return new Response(JSON.stringify({ error: e.message }), {
status: 500,
headers: { ...cors, "Content-Type": "application/json" },
});
}
},
};
✅ 已复制!