From 5b86a1c84a506a24b58c976c7e1a1a4956a79fd9 Mon Sep 17 00:00:00 2001 From: hzm <934585316@qq.com> Date: Sat, 7 Mar 2026 19:25:55 +0800 Subject: [PATCH] =?UTF-8?q?Revert=20"feat:=20=E4=B8=BA=E5=87=8F=E5=B0=91?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E7=AB=AF=E5=87=BA=E5=8F=A3=E6=B5=81=E9=87=8F?= =?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=A2=9E=E8=BE=B9=E7=BC=98=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E6=95=B0=E6=8D=AE=E5=BA=93=E8=A1=A8=E7=8A=B6?= =?UTF-8?q?=E6=80=81"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit f20b852e98885a45e486e8a0970052f687cf853d. --- README.md | 32 -------- app/page.jsx | 31 +++----- doc/edgeFunctions/check-data.ts | 125 -------------------------------- 3 files changed, 10 insertions(+), 178 deletions(-) delete mode 100644 doc/edgeFunctions/check-data.ts diff --git a/README.md b/README.md index aae5ff1..a588b43 100644 --- a/README.md +++ b/README.md @@ -81,38 +81,6 @@ 5. 目前项目用到的 sql 语句,查看项目 supabase.sql 文件。 -### Supabase Edge Functions 配置说明 - -本项目使用 Supabase Edge Functions 来检查用户配置状态。需要部署以下边缘函数: - -#### 1. 边缘函数文件位置 -边缘函数代码位于 `doc/edgeFunctions/*` - -#### 2. 部署步骤 - -1. **新建边缘函数代码**: -位置在 Supabase控制台 → Edge Functions - -2. **复制边缘函数代码**: - 将 `doc/edgeFunctions/*` 复制到 `supabase/functions/*`。复制成功后即可点击部署 - -#### 3. 边缘函数说明 - -**check-data** - 检查用户配置状态 -- **功能**:检查用户在 `user_configs` 表中的配置状态 -- **认证**:需要用户 JWT token -- **返回状态**: - - `not_found`:用户配置记录不存在 - - `empty`:用户配置记录存在但数据为空 - - `found`:用户配置记录存在且有有效数据 - -#### 4. 环境变量要求 - -边缘函数需要以下 Supabase 环境变量(自动注入,无需手动配置): -- `SUPABASE_URL`:Supabase 项目 URL -- `SUPABASE_ANON_KEY`:Supabase 匿名公钥 -- `SUPABASE_SERVICE_ROLE_KEY`:Supabase Service Role Key(用于绕过 RLS 查询) - 更多 Supabase 相关内容查阅官方文档。 ### 构建与部署 diff --git a/app/page.jsx b/app/page.jsx index 946991f..4718276 100644 --- a/app/page.jsx +++ b/app/page.jsx @@ -3179,13 +3179,13 @@ export default function HomePage() { const fetchCloudConfig = async (userId, checkConflict = false) => { if (!userId) return; try { - const { data: checkResult, error: checkError } = await supabase.functions.invoke(`check-data?userId=${userId}`, { - method: 'GET', - }); - - if (checkError) throw checkError; - - if (checkResult.status === 'not_found') { + const { data, error } = await supabase + .from('user_configs') + .select('id, data, updated_at') + .eq('user_id', userId) + .maybeSingle(); + if (error) throw error; + if (!data?.id) { const { error: insertError } = await supabase .from('user_configs') .insert({ user_id: userId }); @@ -3193,30 +3193,19 @@ export default function HomePage() { setCloudConfigModal({ open: true, userId, type: 'empty' }); return; } - - if (checkResult.status === 'empty') { - setCloudConfigModal({ open: true, userId, type: 'empty' }); - return; - } - - const { data, error } = await supabase - .from('user_configs') - .select('id, data, updated_at') - .eq('user_id', userId) - .single(); - - if (error) throw error; - if (data?.data && isPlainObject(data.data) && Object.keys(data.data).length > 0) { const localPayload = collectLocalPayload(); const localComparable = getComparablePayload(localPayload); const cloudComparable = getComparablePayload(data.data); if (localComparable !== cloudComparable) { + // 如果数据不一致 if (checkConflict) { + // 只有明确要求检查冲突时才提示(例如刚登录时) setCloudConfigModal({ open: true, userId, type: 'conflict', cloudData: data.data }); return; } + // 否则直接覆盖本地(例如已登录状态下的刷新) await applyCloudConfig(data.data, data.updated_at); return; } diff --git a/doc/edgeFunctions/check-data.ts b/doc/edgeFunctions/check-data.ts deleted file mode 100644 index 8afed8a..0000000 --- a/doc/edgeFunctions/check-data.ts +++ /dev/null @@ -1,125 +0,0 @@ -/** - * 检测用户配置是否存在 - */ -// supabase/functions/check-data/index.ts - -import { serve } from "https://deno.land/std@0.168.0/http/server.ts"; -import { createClient } from "https://esm.sh/@supabase/supabase-js@2"; - -const corsHeaders = { - "Access-Control-Allow-Origin": "*", - "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type", -}; - -serve(async (req: Request) => { - if (req.method === "OPTIONS") { - return new Response("ok", { headers: corsHeaders }); - } - - if (req.method !== "GET") { - return new Response( - JSON.stringify({ error: "Method not allowed" }), - { status: 405, headers: { ...corsHeaders, "Content-Type": "application/json" } } - ); - } - - try { - const authHeader = req.headers.get("Authorization"); - if (!authHeader) { - return new Response( - JSON.stringify({ error: "Missing authorization header" }), - { status: 401, headers: { ...corsHeaders, "Content-Type": "application/json" } } - ); - } - - const supabaseUrl = Deno.env.get("SUPABASE_URL") ?? ""; - const supabaseAnonKey = Deno.env.get("SUPABASE_ANON_KEY") ?? ""; - const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""; - - const supabaseClient = createClient(supabaseUrl, supabaseAnonKey, { - global: { - headers: { Authorization: authHeader }, - }, - }); - - const { data: { user }, error: userError } = await supabaseClient.auth.getUser(); - - if (userError || !user) { - return new Response( - JSON.stringify({ error: "Invalid JWT", exists: false, status: "error" }), - { status: 401, headers: { ...corsHeaders, "Content-Type": "application/json" } } - ); - } - - const url = new URL(req.url); - const userId = url.searchParams.get("userId"); - - if (!userId) { - return new Response( - JSON.stringify({ error: "Missing 'userId' parameter" }), - { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } } - ); - } - - if (user.id !== userId) { - return new Response( - JSON.stringify({ error: "Unauthorized: User ID mismatch" }), - { status: 403, headers: { ...corsHeaders, "Content-Type": "application/json" } } - ); - } - - const supabaseAdmin = createClient(supabaseUrl, supabaseServiceKey); - - const { data, error } = await supabaseAdmin - .from("user_configs") - .select("data") - .eq("user_id", userId) - .single(); - - if (error && error.code === "PGRST116") { - return new Response( - JSON.stringify({ - exists: false, - status: "not_found", - }), - { status: 200, headers: { ...corsHeaders, "Content-Type": "application/json" } } - ); - } - - if (error) { - throw error; - } - - const jsonData = data?.data; - - const hasValidData = - jsonData !== null && - typeof jsonData === "object" && - Object.keys(jsonData).length > 0; - - if (hasValidData) { - return new Response( - JSON.stringify({ - exists: true, - status: "found", - }), - { status: 200, headers: { ...corsHeaders, "Content-Type": "application/json" } } - ); - } else { - return new Response( - JSON.stringify({ - exists: false, - status: "empty", - }), - { status: 200, headers: { ...corsHeaders, "Content-Type": "application/json" } } - ); - } - - } catch (err) { - console.error("Error:", err); - return new Response( - JSON.stringify({ error: err.message, exists: false, status: "error" }), - { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } } - ); - } -}); \ No newline at end of file