// GenQi Sabah Intake App - Single-file MVP // 技术:React + Tailwind + supabase-js(浏览器端使用 anon key) // 用途: // 1) 公网顾客自助填写问诊表(/intake) // 2) 店内员工使用 Admin 区域(登录后)可搜索/查看/追踪顾客档案 // 3) 可新增回访记录(Visits)与上传舌象/脉象图片(Supabase Storage) // // ⚙️ 上线前配置(必读): // - 新建 Supabase Project,拷贝 Project URL 与 anon 公钥到 .env(或临时粘贴至下方 env 占位) // - SQL 建表与 RLS(复制到 Supabase SQL Editor 运行): // ------------------------------------------------------------- // -- schema: public // create table if not exists customers ( // id uuid primary key default gen_random_uuid(), // full_name text not null, // phone text, // gender text, // age int, // created_at timestamp with time zone default now(), // updated_at timestamp with time zone default now() // ); // create table if not exists visits ( // id uuid primary key default gen_random_uuid(), // customer_id uuid references customers(id) on delete cascade, // visit_date date default current_date, // symptoms text, // bowel text, // urine text, // sleep text, // thirst text, // tongue text, // pulse text, // body_feel text, // menstrual text, // notes text, // created_at timestamp with time zone default now() // ); // -- 开启 RLS // alter table customers enable row level security; // alter table visits enable row level security; // -- 匿名可插入数据(顾客自助提交) // create policy "anon_insert_customers" on customers // for insert to anon with check (true); // create policy "anon_insert_visits" on visits // for insert to anon with check (true); // -- 登录用户可读写全部(店内员工账号) // create policy "auth_full_access_customers" on customers // for all to authenticated using (true) with check (true); // create policy "auth_full_access_visits" on visits // for all to authenticated using (true) with check (true); // ------------------------------------------------------------- // - Storage: 建 bucket name = "uploads",Public // - Auth: 启用 Email/Password,创建店员账户(如 admin@sabah.genqi.vip ) // - 部署:推荐 Vercel,绑定自定义域 sabah.genqi.vip(DNS CNAME 到 Vercel) // ---------------------------------------------- import React, { useEffect, useMemo, useState } from "react"; import { createClient } from "@supabase/supabase-js"; // ====== 1) 环境变量占位(部署到 Vercel 时使用环境变量,不要写死) ====== const SUPABASE_URL = (globalThis as any).env?.SUPABASE_URL || "https://YOUR-PROJECT.supabase.co"; const SUPABASE_ANON_KEY = (globalThis as any).env?.SUPABASE_ANON_KEY || "YOUR-ANON-KEY"; // ====== 2) 初始化 Supabase 客户端 ====== const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY); // ====== 3) UI 小组件 ====== function Section({ title, children }: { title: string; children: React.ReactNode }) { return (

{title}

{children}
); } function Input({ label, ...props }: React.InputHTMLAttributes & { label?: string }) { return ( ); } function Textarea({ label, ...props }: React.TextareaHTMLAttributes & { label?: string }) { return (