1.修复项目管理页面侧栏收起图标显示问题 2.优化1-n模式章节展开和章节内容生成逻辑和提示词结构 3.更新登录成功公告页面UI样式适配当前主题风格

This commit is contained in:
xiamuceer
2025-12-12 13:45:27 +08:00
parent c7bc5190c4
commit 86b73e85fb
10 changed files with 268 additions and 156 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
# 应用配置
# ==========================================
APP_NAME=MuMuAINovel
APP_VERSION=1.1.0
APP_VERSION=1.1.1
APP_HOST=0.0.0.0
APP_PORT=8000
DEBUG=false
+21
View File
@@ -1128,6 +1128,27 @@ async def generate_chapter_content_stream(
previous_content += smart_context['recent_summary'] + "\n\n"
if smart_context['recent_full']:
previous_content += smart_context['recent_full']
# 🔧 修复1-n模式重复问题: 提取上一章结尾作为精确衔接点
if current_chapter.chapter_number > 1:
recent_chapters_parts = smart_context['recent_full'].split('===')
if len(recent_chapters_parts) >= 2:
# 提取最后一章(recent_full包含最近3章,最后一个是上一章)
last_chapter_content = recent_chapters_parts[-1].strip()
# 提取结尾500字
last_chapter_ending = last_chapter_content[-600:] if len(last_chapter_content) > 600 else last_chapter_content
previous_content += f"\n\n{'='*50}\n"
previous_content += f"【⚠️ 上一章结尾内容(必读,用于衔接)】\n"
previous_content += f"以下是上一章(第{current_chapter.chapter_number-1}章)的结尾部分:\n\n"
previous_content += last_chapter_ending + "\n"
previous_content += f"\n{'='*50}\n"
previous_content += f"【本章({current_chapter.chapter_number}章)创作要求】\n"
previous_content += f"1. 必须自然承接上述结尾的场景/情节/对话\n"
previous_content += f"2. 不要重复叙述上一章已经发生的事件\n"
previous_content += f"3. 从新的情节点、新的场景或新的时间点开始\n"
previous_content += f"4. 角色状态要延续,不要重新介绍已出场角色\n"
previous_content += f"{'='*50}\n"
# 日志输出统计信息
stats = smart_context['stats']
+40 -14
View File
@@ -604,24 +604,32 @@ class PromptService:
- 不能出现与前文矛盾的内容
- 自然过渡,避免突兀的跳跃
2. **情节推进**
- 严格按照本章大纲展开情节
- 推动故事向前发展
- 保持与全书大纲的一致性
2. **🔴 防止内容重复(关键)**
- ⚠️ 仔细阅读【上一章结尾内容】,绝对不要重复叙述已经发生的事件
- ⚠️ 本章必须从新的情节点开始,不要重新描述上一章的场景或对话
- ⚠️ 如果上一章以某个动作或对话结束,本章应该从紧接着的下一个动作或反应开始
- ⚠️ 角色状态应该延续而非重置,不要让角色重新经历上一章已经经历的心理过程
- ⚠️ 场景转换要明确,如果是同一场景的延续,要从不同的视角或新的细节切入
3. **角色一致性**
3. **情节推进**
- 严格按照本章大纲(expansion_plan)展开情节
- 推动故事向前发展,不要原地踏步
- 保持与全书大纲的一致性
- 确保本章有独特的叙事价值,而非前章内容的重复
4. **角色一致性**
- 符合角色性格设定
- 延续角色在前文中的成长和变化
- 保持角色关系的连贯性
4. **写作风格**
5. **写作风格**
- 使用{narrative_perspective}视角
- **字数要求:目标{target_word_count}字,不得低于{target_word_count}字,建议控制在{target_word_count}{max_word_count}字之间**
- 语言自然流畅,避免AI痕迹
- 体现世界观特色
5. **承上启下**
- 开头自然衔接上一章结尾
6. **承上启下**
- 开头自然衔接上一章结尾(但不重复上一章内容)
- 结尾为下一章做好铺垫
6. **记忆系统使用指南**
@@ -1067,6 +1075,14 @@ class PromptService:
- 不要直接写到"解决困境",除非原大纲明确包含解决过程
- 如果看到【后一节】的内容,那些是禁区,绝不提前展开
4. **🔴 相邻章节差异化约束(重要 - 防止内容重复)**:
- 每个章节必须有独特的开场方式(不同的场景、时间点、角色状态)
- 每个章节必须有独特的结束方式(不同的悬念、转折、情感收尾)
- key_events在相邻章节间绝不允许重叠,每章的关键事件必须完全不同
- plot_summary必须描述该章的独特内容,不能与其他章节雷同
- 即使是同一事件的不同阶段,也要明确区分"前、中、后"的具体内容
- 例如:第1章可以是"发现线索",第2章必须是"追踪调查"而非再次"发现线索"
【任务要求】
1. 深度分析该大纲的剧情容量和叙事节奏
2. 识别关键剧情点、冲突点和情感转折点(仅限当前大纲范围内)
@@ -1081,12 +1097,13 @@ class PromptService:
- conflict_type: 冲突类型(如:内心挣扎、人际冲突、环境挑战等)
- estimated_words: 预计字数(建议2000-5000字)
{scene_instruction}
4. 确保章节间:
- 衔接自然流畅
5. 确保章节间:
- 衔接自然流畅(每章从不同的起点开始)
- 剧情递进合理(但不超出当前大纲边界)
- 节奏张弛有度
- 每章都有明确的叙事价值
- 每章都有明确且独特的叙事价值(不重复前一章的内容)
- 最后一章结束时,剧情发展程度应恰好完成当前大纲描述的内容,不多不少
- **关键事件无重叠**:仔细检查相邻章节的key_events,确保没有任何重复或雷同
【输出格式】
请严格按照以下JSON数组格式输出,不要添加任何其他文字:
@@ -1154,6 +1171,14 @@ class PromptService:
- 放慢叙事节奏,让读者充分体验当前阶段的剧情
- 每个章节都应该是当前大纲内容的不同侧面或阶段
4. **🔴 相邻章节差异化约束(重要 - 防止内容重复)**:
- 每个章节必须有独特的开场方式(不同的场景、时间点、角色状态)
- 每个章节必须有独特的结束方式(不同的悬念、转折、情感收尾)
- key_events在相邻章节间绝不允许重叠,每章的关键事件必须完全不同
- plot_summary必须描述该章的独特内容,不能与其他章节雷同
- 特别注意与【已生成的前序章节】的差异化,避免重复已有内容
- 即使是同一事件的不同阶段,也要明确区分"前、中、后"的具体内容
【任务要求】
1. 深度分析该大纲的剧情容量和叙事节奏
2. 识别关键剧情点、冲突点和情感转折点(仅限当前大纲范围内)
@@ -1168,11 +1193,12 @@ class PromptService:
- conflict_type: 冲突类型(如:内心挣扎、人际冲突、环境挑战等)
- estimated_words: 预计字数(建议2000-5000字)
{scene_instruction}
4. 确保章节间:
- 与前面章节衔接自然流畅
5. 确保章节间:
- 与前面章节衔接自然流畅(每章从不同的起点开始)
- 剧情递进合理(但不超出当前大纲边界)
- 节奏张弛有度
- 每章都有明确的叙事价值
- 每章都有明确且独特的叙事价值(不重复前面章节的内容)
- **关键事件无重叠**:仔细检查本批次章节的key_events,以及与前序章节的key_events,确保没有任何重复或雷同
【输出格式】
请严格按照以下JSON数组格式输出,不要添加任何其他文字:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "frontend",
"private": true,
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"scripts": {
"dev": "vite",
+43 -3
View File
@@ -31,15 +31,44 @@ export default function AnnouncementModal({ visible, onClose, onDoNotShowToday,
return (
<Modal
title="🎉 欢迎使用 AI小说创作助手"
title={
<div style={{
fontSize: '20px',
fontWeight: 600,
color: 'var(--color-primary)',
textAlign: 'center',
}}>
🎉 使 AI小说创作助手
</div>
}
open={visible}
onCancel={onClose}
footer={
<Space style={{ width: '100%', justifyContent: 'center' }}>
<Button onClick={handleDoNotShowToday} size="large">
<Button
onClick={handleDoNotShowToday}
size="large"
style={{
borderRadius: '8px',
height: '40px',
fontSize: '14px',
}}
>
</Button>
<Button type="primary" onClick={handleNeverShow} size="large">
<Button
type="primary"
onClick={handleNeverShow}
size="large"
style={{
borderRadius: '8px',
height: '40px',
fontSize: '14px',
background: 'var(--color-primary)',
borderColor: 'var(--color-primary)',
boxShadow: 'var(--shadow-primary)',
}}
>
</Button>
</Space>
@@ -49,6 +78,17 @@ export default function AnnouncementModal({ visible, onClose, onDoNotShowToday,
styles={{
body: {
padding: '24px',
background: 'var(--color-bg-container)',
},
header: {
background: 'linear-gradient(135deg, rgba(77, 128, 136, 0.08) 0%, rgba(248, 246, 241, 0.95) 100%)',
borderBottom: '1px solid var(--color-border-secondary)',
padding: '20px 24px',
},
footer: {
background: 'var(--color-bg-container)',
borderTop: '1px solid var(--color-border-secondary)',
padding: '16px 24px',
},
}}
>
+10
View File
@@ -320,6 +320,16 @@ body {
transform: scale(1.15);
}
/* 折叠状态下图标去边距并隐藏文字容器,确保居中 */
.modern-sider.ant-layout-sider-collapsed .ant-menu-item .anticon {
margin-right: 0 !important;
font-size: 22px !important;
}
.modern-sider.ant-layout-sider-collapsed .ant-menu-item .ant-menu-title-content {
display: none !important;
}
/* 选中项左侧指示条 */
.modern-sider .ant-menu-item-selected::before {
content: '';
+1
View File
@@ -887,6 +887,7 @@ export default function Outline() {
modalApi.confirm({
title: '确认删除',
icon: <ExclamationCircleOutlined />,
centered: true,
content: (
<div>
<p>{outlineTitle} <strong>{data.chapter_count}</strong> </p>
+1
View File
@@ -179,6 +179,7 @@ export default function ProjectDetail() {
}}>
<Menu
mode="inline"
inlineCollapsed={collapsed}
selectedKeys={[selectedKey]}
style={{
borderRight: 0,
+2 -2
View File
@@ -347,7 +347,7 @@ export default function ProjectList() {
padding: `${topPadding}px ${sidePadding}px 0`,
}}>
<div style={{
maxWidth: 1400,
maxWidth: 1800,
margin: '0 auto'
}}>
{/* 现代化头部区域 */}
@@ -822,7 +822,7 @@ export default function ProjectList() {
padding: `${isMobile ? 16 : 24}px ${sidePadding}px`,
paddingBottom: footerHeight + (isMobile ? 24 : 32),
}}>
<div style={{ maxWidth: 1400, margin: '0 auto' }}>
<div style={{ maxWidth: 1800, margin: '0 auto' }}>
<Spin spinning={loading}>
{!Array.isArray(projects) || projects.length === 0 ? (
<Card
+148 -135
View File
@@ -56,146 +56,159 @@ export default function Sponsor() {
return (
<div style={{
height: '100%',
overflowY: 'auto',
padding: '16px'
display: 'flex',
flexDirection: 'column',
overflow: 'hidden'
}}>
<div style={{
maxWidth: '1200px',
margin: '0 auto'
flex: 1,
overflowY: 'auto',
overflowX: 'hidden',
padding: 'clamp(16px, 3vh, 24px) clamp(12px, 2vw, 16px)'
}}>
{/* 头部标题区域 */}
<div style={{ textAlign: 'center', marginBottom: '24px' }}>
<Title level={1} style={{ marginBottom: '8px', fontSize: '32px', fontWeight: 'bold' }}>
MuMuAINovel
</Title>
<Text type="secondary" style={{ fontSize: '13px', letterSpacing: '2px' }}>
SUPPORT AI NOVEL CREATION
</Text>
<div style={{
marginTop: '16px',
padding: '16px',
background: 'var(--color-primary)',
borderRadius: '12px',
color: '#fff'
}}>
<Title level={4} style={{ color: '#fff', marginBottom: '8px' }}>
📚 MuMuAINovel - AI
</Title>
<Paragraph style={{ color: '#fff', fontSize: '14px', margin: 0 }}>
AI模型
</Paragraph>
</div>
</div>
{/* 赞助专属权益 */}
<div style={{ marginBottom: '32px' }}>
<Title level={3} style={{ textAlign: 'center', marginBottom: '20px' }}>
<CheckCircleOutlined style={{ color: 'var(--color-success)', marginRight: '8px' }} />
</Title>
<Row gutter={[16, 16]}>
{benefits.map((benefit, index) => (
<Col xs={24} md={8} key={index}>
<Card
hoverable
style={{
height: '100%',
textAlign: 'center',
borderRadius: '10px',
boxShadow: '0 2px 8px rgba(0,0,0,0.08)'
}}
styles={{
body: { padding: '20px 16px' }
}}
>
<div style={{ marginBottom: '12px' }}>
{benefit.icon}
</div>
<Title level={5} style={{ marginBottom: '8px' }}>{benefit.title}</Title>
<Paragraph style={{ color: '#666', marginBottom: 0, fontSize: '13px' }}>
{benefit.description}
</Paragraph>
</Card>
</Col>
))}
</Row>
</div>
{/* 选择金额 */}
<div style={{ marginBottom: '32px' }}>
<Title level={3} style={{ textAlign: 'center', marginBottom: '20px' }}>
<HeartOutlined style={{ color: '#f5222d', marginRight: '8px' }} />
</Title>
<Row gutter={[16, 16]} justify="center">
{sponsorOptions.map((option, index) => (
<Col xs={12} sm={8} md={6} lg={4} key={index}>
<Card
hoverable
onClick={() => handleCardClick(option)}
style={{
textAlign: 'center',
borderRadius: '10px',
boxShadow: 'var(--shadow-card)',
cursor: 'pointer',
transition: 'all 0.3s',
border: '2px solid var(--color-border)'
}}
styles={{
body: { padding: '20px 12px' }
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'translateY(-8px)';
e.currentTarget.style.boxShadow = 'var(--shadow-elevated)';
e.currentTarget.style.borderColor = 'var(--color-primary)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = 'var(--shadow-card)';
e.currentTarget.style.borderColor = 'var(--color-border)';
}}
>
<Title level={3} style={{
color: 'var(--color-primary)',
marginBottom: '4px',
fontSize: '28px',
fontWeight: 'bold'
}}>
{option.description}
</Title>
<Text style={{ fontSize: '14px', color: '#666' }}>
{option.label}
</Text>
</Card>
</Col>
))}
</Row>
</div>
<Divider style={{ margin: '24px 0' }} />
{/* 感谢文案 */}
<div style={{
textAlign: 'center',
padding: '24px 20px',
background: '#f9f9f9',
borderRadius: '10px'
maxWidth: '1200px',
margin: '0 auto',
width: '100%',
display: 'flex',
flexDirection: 'column',
minHeight: 'fit-content'
}}>
<Title level={4} style={{ marginBottom: '12px' }}>
💖 MuMuAINovel
</Title>
<Paragraph style={{ fontSize: '14px', color: '#666', marginBottom: '12px' }}>
AI小说创作体验
</Paragraph>
<div style={{ fontSize: '24px' }}>
<StarOutlined style={{ color: '#faad14', margin: '0 4px' }} />
<StarOutlined style={{ color: '#faad14', margin: '0 4px' }} />
<StarOutlined style={{ color: '#faad14', margin: '0 4px' }} />
<StarOutlined style={{ color: '#faad14', margin: '0 4px' }} />
<StarOutlined style={{ color: '#faad14', margin: '0 4px' }} />
{/* 头部标题区域 */}
<div style={{ textAlign: 'center', marginBottom: 'clamp(20px, 4vh, 32px)' }}>
<Title level={1} style={{ marginBottom: '8px', fontSize: 'clamp(24px, 5vw, 32px)', fontWeight: 'bold' }}>
MuMuAINovel
</Title>
<Text type="secondary" style={{ fontSize: 'clamp(11px, 2vw, 13px)', letterSpacing: '2px' }}>
SUPPORT AI NOVEL CREATION
</Text>
<div style={{
marginTop: 'clamp(12px, 2vh, 16px)',
padding: 'clamp(12px, 2vh, 16px)',
background: 'var(--color-primary)',
borderRadius: '12px',
color: '#fff'
}}>
<Title level={4} style={{ color: '#fff', marginBottom: '8px' }}>
📚 MuMuAINovel - AI
</Title>
<Paragraph style={{ color: '#fff', fontSize: '14px', margin: 0 }}>
AI模型
</Paragraph>
</div>
</div>
{/* 赞助专属权益 */}
<div style={{ marginBottom: 'clamp(24px, 4vh, 32px)' }}>
<Title level={3} style={{ textAlign: 'center', marginBottom: 'clamp(16px, 3vh, 20px)', fontSize: 'clamp(18px, 3vw, 24px)' }}>
<CheckCircleOutlined style={{ color: 'var(--color-success)', marginRight: '8px' }} />
</Title>
<Row gutter={[{ xs: 8, sm: 12, md: 16 }, { xs: 8, sm: 12, md: 16 }]}>
{benefits.map((benefit, index) => (
<Col xs={24} md={8} key={index}>
<Card
hoverable
style={{
height: '100%',
textAlign: 'center',
borderRadius: '10px',
boxShadow: '0 2px 8px rgba(0,0,0,0.08)'
}}
styles={{
body: { padding: 'clamp(16px, 3vh, 20px) clamp(12px, 2vw, 16px)' }
}}
>
<div style={{ marginBottom: '12px' }}>
{benefit.icon}
</div>
<Title level={5} style={{ marginBottom: '8px', fontSize: 'clamp(14px, 2.5vw, 16px)' }}>{benefit.title}</Title>
<Paragraph style={{ color: '#666', marginBottom: 0, fontSize: 'clamp(12px, 2vw, 13px)' }}>
{benefit.description}
</Paragraph>
</Card>
</Col>
))}
</Row>
</div>
{/* 选择金额 */}
<div style={{ marginBottom: 'clamp(24px, 4vh, 32px)' }}>
<Title level={3} style={{ textAlign: 'center', marginBottom: 'clamp(16px, 3vh, 20px)', fontSize: 'clamp(18px, 3vw, 24px)' }}>
<HeartOutlined style={{ color: '#f5222d', marginRight: '8px' }} />
</Title>
<Row gutter={[{ xs: 8, sm: 12, md: 16 }, { xs: 8, sm: 12, md: 16 }]} justify="center">
{sponsorOptions.map((option, index) => (
<Col xs={12} sm={8} md={6} lg={6} xl={4} key={index}>
<Card
hoverable
onClick={() => handleCardClick(option)}
style={{
textAlign: 'center',
borderRadius: '10px',
boxShadow: 'var(--shadow-card)',
cursor: 'pointer',
transition: 'all 0.3s',
border: '2px solid var(--color-border)'
}}
styles={{
body: { padding: 'clamp(16px, 3vh, 20px) clamp(10px, 2vw, 12px)' }
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'translateY(-8px)';
e.currentTarget.style.boxShadow = 'var(--shadow-elevated)';
e.currentTarget.style.borderColor = 'var(--color-primary)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = 'var(--shadow-card)';
e.currentTarget.style.borderColor = 'var(--color-border)';
}}
>
<Title level={3} style={{
color: 'var(--color-primary)',
marginBottom: '4px',
fontSize: 'clamp(20px, 4vw, 28px)',
fontWeight: 'bold'
}}>
{option.description}
</Title>
<Text style={{ fontSize: 'clamp(12px, 2vw, 14px)', color: '#666' }}>
{option.label}
</Text>
</Card>
</Col>
))}
</Row>
</div>
<Divider style={{ margin: 'clamp(16px, 3vh, 24px) 0' }} />
{/* 感谢文案 */}
<div style={{
textAlign: 'center',
padding: 'clamp(16px, 3vh, 24px) clamp(16px, 3vw, 20px)',
background: '#f9f9f9',
borderRadius: '10px',
marginTop: 'auto'
}}>
<Title level={4} style={{ marginBottom: '12px', fontSize: 'clamp(16px, 3vw, 20px)' }}>
💖 MuMuAINovel
</Title>
<Paragraph style={{ fontSize: 'clamp(12px, 2vw, 14px)', color: '#666', marginBottom: '12px' }}>
AI小说创作体验
</Paragraph>
<div style={{ fontSize: 'clamp(18px, 3vw, 24px)' }}>
<StarOutlined style={{ color: '#faad14', margin: '0 4px' }} />
<StarOutlined style={{ color: '#faad14', margin: '0 4px' }} />
<StarOutlined style={{ color: '#faad14', margin: '0 4px' }} />
<StarOutlined style={{ color: '#faad14', margin: '0 4px' }} />
<StarOutlined style={{ color: '#faad14', margin: '0 4px' }} />
</div>
</div>
</div>
</div>