Anatomy Atelier

3个月前发布 179 00

Anatomy Atelier 是一款基于 three.js 与 GPT 5.6 Sol 构建的浏览器原生3D人体解剖探索应用,用户无需安装任何插件即可在网页中旋转、缩放、点击解剖结构并获取AI驱动的实时解说。

所在地:
美国
收录时间:
2026-08-08
其他站点:
Anatomy AtelierAnatomy Atelier

Anatomy Atelier 是一款基于 three.js 与 GPT 5.6 Sol 构建的浏览器原生3D人体解剖探索应用,用户无需安装任何插件即可在网页中旋转、缩放、点击解剖结构并获取AI驱动的实时解说。

Anatomy Atelier

项目基于 vinext-starter 全栈模板开发,支持 Cloudflare D1/R2 绑定(可选),Node.js ≥ 22.13.0 环境。内置 OpenAI 工作区认证头信息读取(邮箱/全名)及可选 ChatGPT 登录(SIWC)辅助函数,便于构建用户专属学习记录或个性化内容。本地开发通过 vite.config.ts 模拟绑定,数据库 schema 初始为空,Drizzle 迁移按需生成。注意:SIWC 仅验证身份不证明工作区成员资格,访问控制需额外实现;ChatGPT 登录相关路由(/signin-with-chatgpt 等)由平台托管,禁止自定义实现。

核心功能与技术架构

3D交互体验

  • 纯浏览器渲染:three.js 实现轻量级3D场景,支持鼠标/触控旋转、缩放、平移
  • 结构化标注:点击器官/骨骼/肌肉触发高亮与信息面板,避免纯视觉猜测
  • GPT 5.6 Sol集成:选中结构后AI提供层次化解说(位置/功能/临床关联),支持追问深化理解
  • 响应式适配:桌面端精细操作,移动端简化手势,兼顾教学与自学场景

全栈基础设施(vinext-starter)

组件作用注意事项
app/站点业务代码目录编辑此处添加解剖模块
.openai/hosting.json声明D1/R2绑定(可选)未使用时可忽略
vite.config.ts本地开发模拟绑定生产环境由平台注入
db/schema.ts数据库表结构定义初始为空,按需扩展
examples/d1/D1示例界面参考可删除或改造为用户记录存储
drizzle.config.ts迁移生成配置修改schema后执行npm run db:generate

身份认证体系

  • 工作区用户识别:通过请求头 oai-authenticated-user-email 获取邮箱;若SIWC配置文件含名称,则额外提供百分号编码的UTF-8全名(伴随encoding头确认)
  • 安全回退策略:全名缺失时自动降级为邮箱显示,避免空白用户名
  • ChatGPT登录(SIWC):
    • getChatGPTUser():可选登录态检测,用于个性化UI
    • requireChatGPTUser(returnTo):强制登录页保护,匿名访客重定向至登录流
    • chatGPTSignInPath/SignOutPath(returnTo):生成安全编码的登录/登出链接
    • 关键约束:受保护页面必须标记 export const dynamic = "force-dynamic";保留路由(/signin-with-chatgpt等)由平台处理,严禁自定义实现
  • 权限边界:SIWC ≠ 工作区成员资格;敏感操作需服务端显式校验成员身份或白名单

部署与开发实操指南

环境准备

# 确保 Node.js >= 22.13.0
node -v

# 安装依赖
npm install

# 本地开发(自动模拟D1/R2绑定)
npm run dev

# 生产构建验证
npm run build

# 测试构建产物渲染
npm test

数据库工作流

  1. 编辑 db/schema.ts 定义用户记录/学习进度等表结构
  2. 执行 npm run db:generate 生成迁移文件
  3. 本地开发时 vite.config.ts 自动应用迁移;生产环境通过平台部署流程执行

身份集成最佳实践

// app/profile/page.tsx
import { headers } from "next/headers";
import { requireChatGPTUser } from "../chatgpt-auth";

export const dynamic = "force-dynamic"; // 必须!依赖请求头

export default async function ProfilePage() {
  const user = await requireChatGPTUser("/profile"); // 未登录则跳转登录
  
  const requestHeaders = await headers();
  const email = requestHeaders.get("oai-authenticated-user-email");
  const encodedFullName = requestHeaders.get("oai-authenticated-user-full-name");
  const fullName = 
    encodedFullName && 
    requestHeaders.get("oai-authenticated-user-full-name-encoding") === "percent-encoded-utf-8"
      ? decodeURIComponent(encodedFullName)
      : null;
  
  return <div>欢迎, {fullName ?? email}</div>;
}

常见陷阱规避

  • ❌ 勿为 /signin-with-chatgpt 等保留路径创建路由 → 会导致平台OAuth流程失效
  • ❌ 勿在未标记 force-dynamic 的页面读取认证头 → 缓存导致身份错乱
  • ❌ 勿将SIWC当作权限检查 → 仅证明“是谁”,不证明“是否有权”
  • ✅ 公共解剖内容保持匿名可访问;用户笔记/收藏等写入操作才启用SIWC
  • ✅ 全名解码前务必验证encoding头,防止恶意伪造

相关导航