第七章:部署指南

7.1 环境要求

依赖 最低版本 用途
Bun >= 1.3 运行时、包管理、构建
Node.js >= 18 可选,Bun 的 fallback
Caddy >= 2.x 反向代理
SQLite 内嵌 无需独立安装

7.2 部署流程

代理阶段

运行阶段

构建阶段

准备阶段

bun install
安装依赖

bun run db:generate
生成Prisma Client

bun run db:push
推送Schema到SQLite

bun run build
next build + standalone

bun run start
启动生产服务

服务监听
localhost:3000

配置Caddyfile

caddy reload
重载配置

Caddy监听
Port 81

7.3 构建配置详解

// next.config.ts
{
  output: "standalone",           // 独立部署模式
  typescript: { 
    ignoreBuildErrors: true        // 构建时忽略TS错误(生产环境)
  },
  reactStrictMode: false           // 关闭严格模式(避免双重渲染)
}

配置说明:

配置项 原因
output: "standalone" 独立模式 减少生产依赖,简化部署
ignoreBuildErrors: true 忽略TS错误 某些类型问题不影响运行时
reactStrictMode: false 关闭严格模式 避免 useEffect 双重执行导致的状态异常

7.4 Caddy 反向代理配置

# Caddyfile
:81 {
    # 动态端口转发规则
    @transform_port_query {
        query XTransformPort=*
    }
    handle @transform_port_query {
        reverse_proxy localhost:{query.XTransformPort} {
            header_up Host {host}
            header_up X-Forwarded-For {remote_host}
            header_up X-Forwarded-Proto {scheme}
            header_up X-Real-IP {remote_host}
        }
    }

    # 默认转发到Next.js服务
    handle {
        reverse_proxy localhost:3000 {
            header_up Host {host}
            header_up X-Forwarded-For {remote_host}
            header_up X-Forwarded-Proto {scheme}
            header_up X-Real-IP {remote_host}
        }
    }
}

特性说明:

特性 说明
默认转发 所有流量转发到 localhost:3000
动态端口 支持 ?XTransformPort=<port> 查询参数动态转发到指定端口
请求头透传 自动传递 Host、X-Forwarded-For、X-Forwarded-Proto、X-Real-IP

7.5 环境变量

变量 说明 默认值
DATABASE_URL SQLite 数据库路径 file:/home/z/my-project/db/custom.db
NODE_ENV 运行环境 production(start 时自动设置)

7.6 部署脚本

项目 .zscripts/ 目录包含以下脚本(需根据实际部署环境调整路径):

脚本 用途
build.sh 执行完整构建流程
start.sh 启动生产服务
dev.sh 开发模式启动(监听 :3000,日志输出到 dev.log)
mini-services-build.sh 微服务构建
mini-services-install.sh 微服务依赖安装
mini-services-start.sh 微服务启动

第八章:项目目录结构

幽境物語/
├── 📄 配置文件
│   ├── .env                          # 环境变量
│   ├── .gitignore
│   ├── Caddyfile                     # Caddy 反向代理配置
│   ├── bun.lock                      # Bun 依赖锁
│   ├── components.json               # shadcn/ui 配置
│   ├── next.config.ts                # Next.js 配置
│   ├── package.json                  # 项目清单
│   ├── postcss.config.mjs            # PostCSS 配置
│   ├── tailwind.config.ts            # Tailwind 配置
│   ├── tsconfig.json                 # TypeScript 配置
│   └── worklog.md                    # 开发日志
│
├── 💾 数据层
│   ├── db/
│   │   └── custom.db                 # SQLite 数据库文件
│   └── prisma/
│       └── schema.prisma             # Prisma 数据模型
│
├── 📦 静态资源
│   └── public/
│       ├── logo.svg
│       ├── robots.txt
│       └── game-images/              # 游戏图片资源
│           ├── hero-banner.png
│           ├── scene-tavern.png
│           ├── character-yukino.png
│           ├── character-sousuke.png
│           └── character-rin.png
│
├── 🔧 部署脚本
│   └── zscripts/
│       ├── build.sh
│       ├── dev.sh
│       ├── start.sh
│       ├── mini-services-build.sh
│       ├── mini-services-install.sh
│       └── mini-services-start.sh
│
├── ⚙️ 微服务
│   └── mini-services/
│       └── .gitkeep
│
└── 📝 源代码
    └── src/
        ├── app/                          # Next.js App Router
        │   ├── globals.css               # 全局样式(暗色主题、自定义滚动条、动画)
        │   ├── layout.tsx                # 根布局(zh-CN、暗色主题)
        │   ├── page.tsx                  # 主页面(AnimatePresence 阶段路由)
        │   └── api/
        │       ├── route.ts              # 根 API 路由
        │       ├── chat/
        │       │   └── route.ts          # 对话 API(核心)
        │       └── llm-test/
        │           └── route.ts          # LLM 连接测试 API
        │
        ├── components/
        │   ├── game/                     # 游戏业务组件
        │   │   ├── landing-screen.tsx
        │   │   ├── character-select.tsx
        │   │   ├── character-portrait.tsx
        │   │   ├── chat-panel.tsx
        │   │   ├── status-panel.tsx
        │   │   ├── mobile-status.tsx
        │   │   ├── game-scene.tsx
        │   │   ├── llm-config-panel.tsx
        │   │   ├── puzzle-card.tsx
        │   │   ├── puzzle-journal.tsx
        │   │   └── item-card.tsx
        │   └── ui/                       # shadcn/ui 组件库(50+组件)
        │
        ├── hooks/
        │   ├── use-mobile.ts             # 移动端检测
        │   └── use-toast.ts              # Toast 通知
        │
        └── lib/                          # 核心逻辑库
            ├── db.ts                     # Prisma Client 单例
            ├── game-types.ts             # 游戏类型定义
            ├── game-store.ts             # Zustand 状态管理(含持久化)
            ├── game-constants.ts         # 共享常量(mood/atmosphere 配置)
            ├── soul-files.ts             # 角色 Soul File + 系统提示词构建
            ├── puzzles.ts                # 谜题数据 + 逻辑
            ├── items.ts                  # 物品数据 + 检测逻辑
            └── utils.ts                  # 通用工具函数

第九章:关键设计决策

9.1 为什么采用客户端主导的状态持久化?

方案 优点 缺点
客户端持久化(采用) 无需登录即可游玩;保护玩家隐私;零服务端压力;离线可玩 换设备丢失进度;浏览器清理数据丢失
服务端持久化 跨设备同步;数据不丢失 需要用户系统;增加服务端复杂度;隐私风险

决策理由:游戏的核心体验是个人化的叙事旅程,玩家进度不需要跨设备共享。采用 localStorage 分层持久化,在简单性和功能性之间取得了最佳平衡。

9.2 为什么设计 Soul File 而非简单提示词?

传统 AI 角色通常使用一段固定的提示词(Prompt)定义。Soul File 的区别在于:

维度 传统提示词 Soul File
结构化 自由文本 模块化、类型安全
可维护性 修改一处可能影响整体 模块化修改,影响范围可控
一致性 依赖模型对长文本的理解 通过认知过滤器强制约束
可扩展性 难以添加新维度 可轻松添加新模块

Soul File 的核心价值:通过认知过滤器(cognitiveFilter) 明确告知 AI “你不知道什么”,从根本上减少了 AI 幻觉(Hallucination),确保角色不会编造设定之外的信息。

9.3 为什么采用双重谜题校验?

客户端校验(Fallback)

AI判定(Primary)

优先采用

AI未判定时采用

AI理解玩家输入

AI判断是否正确

返回puzzleSolved

关键词匹配

正则表达式

返回clientPuzzleEvent

玩家答案

最终结果

双重校验的必要性

  • AI 判定是"语义理解",能处理同义词、变体表达,但可能因模型波动出错
  • 客户端校验是"精确匹配",作为兜底确保关键谜题不会被遗漏
  • 以 AI 判定为准,客户端仅作为 fallback,兼顾了灵活性和可靠性

9.4 情绪与氛围系统的设计意图

系统 设计意图 玩家感知
情绪系统(7种) 让角色"活"起来,每次对话都有情感反馈 角色不是冷冰冰的机器人
氛围系统(6种) 通过视觉变化强化叙事沉浸感 场景随故事推进而变化
红线机制 给角色设定底线,增强真实感 角色有自己的原则和边界

情绪与氛围的联动:当 AI 返回 mood: "sad"atmosphere: "melancholic" 时,前端同时更新角色表情和场景背景色,形成视听一致的沉浸体验。

9.5 信任度系统:游戏化的核心驱动力

游戏反馈

信任度变化

玩家行为

礼貌对话

帮助角色

成功解谜

触发红线

重复冒犯

+2 ~ +5

+5 ~ +10

+8 ~ +15

-5 ~ -10

-10 ~ -20

对话更开放

解锁新谜题

揭示秘密

对话更封闭

角色拒绝互动

设计哲学:信任度不是简单的"好感度系统",而是叙事进度的量化指标。它决定了:

  • AI 愿意分享的信息深度
  • 可解锁的谜题数量
  • 可发现的秘密层级
  • 角色的对话态度和语气

这使得每一次对话都具有策略性——玩家需要思考如何与角色建立真正的信任,而非简单刷好感。


附录

A. 情绪状态表

情绪 标识 Emoji 颜色 典型场景
平静 neutral 😐 灰色 日常对话
开心 happy 😊 黄色 收到礼物、解开谜题
悲伤 sad 😢 蓝色 提及往事、失去
愤怒 angry 😠 红色 触发红线、被冒犯
惊讶 surprised 😲 橙色 意外发现
思考 thinking 🤔 紫色 面对难题
神秘 mysterious 🌙 靛蓝 暗示秘密

B. 氛围状态表

氛围 标识 渐变背景色 典型场景
宁静 calm 蓝绿色渐变 日常、休息
紧张 tense 暗红色渐变 危机、冲突
欢快 joyful 明黄色渐变 庆祝、和解
神秘 mysterious 深紫色渐变 发现秘密
忧郁 melancholic 灰蓝色渐变 回忆、离别
浪漫 romantic 粉紫色渐变 羁绊加深

C. 快速参考:信任度影响

信任区间 等级 AI 行为 可解锁内容
0-20 戒备 简短疏远,回应谨慎 基础问候
20-40 礼貌 基本礼貌但有所保留 个人背景、1星谜题
40-70 保留 愿意分享深层想法 内心困惑、2星谜题
70-100 深厚羁绊 坦诚分享内心和秘密 核心秘密、3星谜题

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐