山东大学软件工程2023级创新项目实训 | 三、StoryEcho项目框架功能初步探索
时间: 2026年4月上旬 - 4月中旬
在完成初步框架搭建后,我们FateWeaver团队进入了功能细化与验证阶段。这段时间的工作主要围绕两个方向展开:一是完善前端界面的核心交互功能,为后续分工开发打好基础;二是验证大模型API接入的可行性,确保技术路线的正确性。
目录
一、角色创建功能的完善与优化
在初步框架中,角色创建界面只有一个简单的弹窗结构。为了让用户体验更加完整,我负责对角色创建模块进行了详细的功能实现和界面优化。以下是目前的角色创建界面:






1.1 多题材差异化设计
考虑到我们的平台需要支持不同题材的故事(奇幻、科幻等),我设计了差异化的天赋和出身系统。不同故事类型拥有各自独立的选项池:
奇幻题材(如“迷雾森林的传说”)的天赋设计:
// 奇幻故事天赋数据
const fantasyTalents = ref([
{ id: 'talent_001', name: '战斗天才', description: '你在战斗方面有着非凡的天赋',
effects: { strength: 5, agility: 3 }, rarity: 'rare', unlocked: true, storyId: 'fantasy_001' },
{ id: 'talent_002', name: '博学者', description: '你拥有广博的知识储备',
effects: { intelligence: 8, mp: 20 }, rarity: 'rare', unlocked: true, storyId: 'fantasy_001' },
{ id: 'talent_003', name: '幸运儿', description: '命运似乎总是眷顾着你',
effects: { luck: 10 }, rarity: 'epic', unlocked: true, storyId: 'fantasy_001' },
{ id: 'talent_005', name: '龙裔血脉', description: '你的血脉中流淌着龙的力量',
effects: { hp: 50, strength: 10 }, rarity: 'legendary', unlocked: false, storyId: 'fantasy_001' },
// ...更多天赋
]);
科幻题材(如“赛博2077:觉醒”)的天赋设计:
// 科幻故事天赋数据
const scifiTalents = ref([
{ id: 'sci_talent_001', name: '黑客大师', description: '你精通各种黑客技术',
effects: { intelligence: 8, tech_skill: 10 }, rarity: 'rare', unlocked: true, storyId: 'scifi_001' },
{ id: 'sci_talent_002', name: '义体适应', description: '你的身体能更好地适应义体',
effects: { hp: 20, strength: 5 }, rarity: 'rare', unlocked: true, storyId: 'scifi_001' },
{ id: 'sci_talent_004', name: '战斗义体', description: '你装备了军用级战斗义体',
effects: { strength: 15, hp: 10 }, rarity: 'legendary', unlocked: false, storyId: 'scifi_001' },
// ...更多天赋
]);
通过计算属性 availableTalents 和 backgrounds,系统会根据用户选择的故事ID自动筛选出对应的天赋和出身选项:
// 当前故事可用的天赋
const availableTalents = computed(() => {
const allTalents = [...fantasyTalents.value, ...scifiTalents.value];
if (!selectedStory.value) return fantasyTalents.value;
return allTalents.filter(t => t.storyId === selectedStory.value.story_id);
});
1.2 属性上限系统设计
不同题材的故事拥有不同的属性体系。例如,奇幻题材关注HP、MP、力量、敏捷等,而科幻题材则引入了能量值、科技技能等新属性。为此,我设计了故事属性配置对象:
const storyConfigs = {
fantasy_001: {
baseAttributes: { hp: 100, mp: 50, strength: 15, agility: 12, intelligence: 10, luck: 8 },
maxValues: { hp: 150, mp: 100, strength: 50, agility: 50, intelligence: 50, luck: 50 }
},
scifi_001: {
baseAttributes: { hp: 80, energy: 100, strength: 18, intelligence: 20, tech_skill: 15, money: 500 },
maxValues: { hp: 120, energy: 150, strength: 60, intelligence: 60, tech_skill: 50, money: 9999 }
}
};
属性预览会动态计算基础值加上天赋和出身的加成,并确保不超过上限:
const previewAttributes = computed(() => {
const config = currentStoryConfig.value;
const base = { ...config.baseAttributes };
const maxValues = config.maxValues;
if (selectedTalent.value) {
Object.entries(selectedTalent.value.effects).forEach(([attr, value]) => {
if (base[attr] !== undefined) {
base[attr] = Math.min(base[attr] + value, maxValues[attr] || 100);
}
});
}
if (selectedBackground.value) {
Object.entries(selectedBackground.value.attribute_modifiers).forEach(([attr, value]) => {
if (base[attr] !== undefined) {
base[attr] = Math.min(base[attr] + value, maxValues[attr] || 100);
}
});
}
return base;
});
当属性接近或达到上限时,界面会显示提示信息:
const hasExceededLimit = computed(() => {
const config = currentStoryConfig.value;
const maxValues = config.maxValues;
return Object.entries(previewAttributes.value).some(([attr, value]) => {
return value >= (maxValues[attr] || 100);
});
});
1.3 属性预览进度条优化
在属性预览区域,我实现了带有最大值显示的进度条,让用户直观了解当前属性在其上限中的占比:
<div class="attr-item">
<span class="attr-name">{{ getAttrName(attr) }}</span>
<div class="attr-bar">
<div class="attr-fill" :style="{width: (value / getAttrMaxValue(attr) * 100) + '%'}"></div>
<span class="attr-value">{{ value }}/{{ getAttrMaxValue(attr) }}</span>
</div>
</div>
对应的CSS样式确保进度条正确显示:
.attr-bar {
flex: 1;
height: 20px;
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
position: relative;
overflow: hidden;
}
.attr-fill {
height: 100%;
background: linear-gradient(90deg, #667eea, #764ba2);
border-radius: 10px;
transition: width 0.3s;
}
.attr-value {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
font-size: 11px;
color: white;
text-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
z-index: 1;
}
1.4 界面遮挡问题的解决
在开发过程中,我遇到了一个样式问题:当角色创建界面的内容过多时,属性值显示框会与下方的性格倾向滑动条发生重叠遮挡。这导致用户无法正常操作滑动条,影响体验。

经过在DeepSeek等大模型的协助下进行调试,我发现问题出在 .creation-content 和 .creation-form 的高度设置上。原来的CSS没有对内容区域进行滚动限制,导致内容溢出。
修复前的代码:
.creation-content {
display: grid;
grid-template-columns: 1fr 1.5fr;
gap: 30px;
}
修复后的代码:
.creation-content {
display: grid;
grid-template-columns: 1fr 1.5fr;
gap: 30px;
max-height: 500px;
}
.creation-form {
overflow-y: auto;
padding-right: 10px;
max-height: 500px;
}
.step-content {
max-height: 350px;
overflow-y: auto;
padding-right: 10px;
}
通过为各个容器设置 max-height 和 overflow-y: auto,当内容超出时会出现滚动条,避免了元素之间的遮挡问题。同时,性格倾向滑动条的样式也进行了优化:
.personality-slider {
padding: 15px 0;
}
.personality-slider input {
width: 100%;
height: 6px;
-webkit-appearance: none;
appearance: none;
background: linear-gradient(90deg, #10b981, #f59e0b, #ef4444);
border-radius: 3px;
outline: none;
}
.personality-slider input::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
background: white;
border-radius: 50%;
cursor: pointer;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
1.5 故事筛选功能的添加
为了让故事大厅更加友好,我还添加了按题材筛选故事的功能。在首页增加了标签切换组件:
<div class="story-tabs-container">
<div class="story-tab-item" :class="{active: activeStoryFilter === 'all'}" @click="activeStoryFilter = 'all'">
<span>📚 全部</span>
</div>
<div class="story-tab-item" :class="{active: activeStoryFilter === 'fantasy'}" @click="activeStoryFilter = 'fantasy'">
<span>🌲 奇幻</span>
</div>
<div class="story-tab-item" :class="{active: activeStoryFilter === 'scifi'}" @click="activeStoryFilter = 'scifi'">
<span>🤖 科幻</span>
</div>
</div>
对应的筛选逻辑:
const filteredStories = computed(() => {
if (activeStoryFilter.value === 'all') return stories.value;
if (activeStoryFilter.value === 'fantasy') {
return stories.value.filter(s => s.genre === '奇幻');
}
if (activeStoryFilter.value === 'scifi') {
return stories.value.filter(s => s.genre === '科幻');
}
return stories.value;
});
同时为故事卡片添加了图标展示,增强视觉效果:
<div class="story-card-header">
<span class="story-icon">{{ story.icon || '📖' }}</span>
<h3>{{ story.title }}</h3>
</div>
二、团队协作与代码整合
在各自完成负责的功能模块后,我们进行了一次集中的代码整合。其他成员在同期完成的工作包括:
-
故事大厅界面的优化:美化了故事卡片的样式,添加了难度标签和更详细的背景描述展示。
-
主游戏界面的工具栏完善:在叙事窗口顶部添加了任务日志、命运之网、结局画廊、多周目传承的快捷入口按钮。
-
侧边栏状态面板的优化:优化了属性条的显示效果,添加了NPC好感度面板的折叠展开功能。
-
结局界面和画廊界面的基础框架:搭建了结局展示和收集系统的UI框架。
进行代码合并后,我们得到了一个功能相对完整的前端框架。虽然大部分数据仍是Mock数据,但界面交互流程已经基本打通:用户可以选择故事、创建角色、进入游戏、进行对话交互。
三、API接入验证与首次AI对话成功
在完善前端的同时,团队中的一名成员负责尝试接入DeepSeek API,验证大模型驱动的互动叙事是否能够真正跑通。
3.1 LLMClient类的实现
在 story_engine.py 中,我们实现了 LLMClient 类来封装对大模型API的调用:
class LLMClient:
def __init__(self, api_key: str = None, base_url: str = None, model: str = None):
self.api_key = api_key or os.getenv("DEEPSEEK_API_KEY", "sk-2666c4c1dcfc4b0990dedc7b021cf29c")
self.base_url = base_url or os.getenv("LLM_BASE_URL", "https://api.deepseek.com/v1")
self.model = model or os.getenv("LLM_MODEL", "deepseek-chat")
self.headers = {"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}
def generate(self, messages: List[Dict[str, str]], temperature: float = 0.8) -> str:
url = f"{self.base_url}/chat/completions"
payload = {"model": self.model, "messages": messages, "temperature": temperature, "max_tokens": 800}
try:
resp = requests.post(url, headers=self.headers, json=payload, timeout=30)
resp.raise_for_status()
return resp.json()["choices"][0]["message"]["content"]
except Exception as e:
print(f"LLM 调用失败: {e}")
return "(大模型暂时无法响应,请稍后再试。)"
3.2 后端初始化调整
在 app.py 中,我们修改了引擎初始化方式,注入真实的LLM客户端:
# 初始化故事引擎(使用大模型)
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY", "sk-2666c4c1dcfc4b0990dedc7b021cf29c")
llm_client = LLMClient(api_key=DEEPSEEK_API_KEY)
engine = StoryEngine(llm_client=llm_client)
3.3 首次AI对话成功
经过调试,我们成功实现了与AI的完整对话流程!



这次成功的验证给了团队极大的信心。它证明了我们的技术架构是可行的——前端通过API发送用户输入,后端调用大模型进行意图识别和叙事生成,再将结果返回前端展示。整个流程顺畅运行!
四、当前成果与后续规划
4.1 当前成果总结
经过这一阶段的工作,我们取得了以下进展:
-
完善的角色创建系统:支持多题材差异化设计,包含属性上限管理、实时预览、三步向导流程。
-
故事筛选功能:用户可按题材快速筛选感兴趣的故事。
-
AI对话验证成功:成功接入DeepSeek API,实现了从用户输入到AI剧情生成的完整闭环。
-
统一的前端框架:整合了团队成员各自完成的界面模块,形成了功能相对完整的交互原型。
4.2 后续工作规划
后端方面,我们将逐步实现:
-
数据库持久化:使用数据库存储用户存档、结局收集记录、天赋解锁状态等。
-
状态追踪完善:扩展逻辑裁判节点,支持更丰富的行动类型判定。
-
多结局收敛算法:基于用户决策倾向和属性累积,自动匹配最合适的结局。
-
上下文管理优化:实现对话历史的智能摘要,保证长程交互的连贯性。
这一阶段的工作让我们对项目有了更清晰的认识。前端框架的确立和AI对话的成功验证,为后续的并行开发扫清了障碍。接下来,我们将按照分工各自推进,定期进行代码合并和集成测试,向着一个功能完整的沉浸式互动叙事平台稳步前进。
更多推荐


所有评论(0)