2025.10.25故事生成系统介绍

大作业:儿童故事管理平台设计与开发

系统架构

整体架构

儿童故事管理平台是一个完整的Web应用,集成了三个实验的核心功能:AI故事生成、AI插图生成和AI语音合成。系统采用前后端分离的架构设计,使用Flask作为后端框架,前端使用HTML、CSS和JavaScript构建用户界面。

组件关系

前端界面 (HTML/JS) → Flask应用 (app.py)
                   → 故事管理模块 (story_manager_routes.py/story_manager.py)
                   → 故事生成服务 (story_service.py)
                   → 插图生成服务 (image_service.py)
                   → 语音合成服务 (voice_service.py)

核心代码

1. 应用初始化与配置 (app.py)

import os
from flask import Flask, render_template, send_from_directory
from flask_cors import CORS
from dotenv import load_dotenv
import sys

# 添加项目根目录到Python路径
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

# 加载环境变量
load_dotenv()

# 创建Flask应用实例
app = Flask(__name__)

# 配置CORS,允许跨域请求
CORS(app, resources={r"/*": {"origins": "*"}})

# 配置上传文件夹
UPLOAD_FOLDER = os.path.join(app.root_path, 'uploads')
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

# 健康检查路由
@app.route('/health')
def health_check():
    return {'status': 'ok'}

# 测试路由
@app.route('/test')
def test():
    return {'message': '儿童故事管理平台API正常运行'}

# HTML页面路由
@app.route('/')
def index():
    return render_template('index.html')

@app.route('/generate')
def generate_page():
    return render_template('generate.html')

@app.route('/stories')
def stories_page():
    return render_template('stories.html')

# 注册蓝图
from routes.story_routes import bp as story_bp
from routes.image_routes import bp as image_bp
from routes.voice_routes import bp as voice_bp
from routes.story_manager_routes import bp as story_manager_bp

app.register_blueprint(story_bp, url_prefix='/story')
app.register_blueprint(image_bp, url_prefix='/image')
app.register_blueprint(voice_bp, url_prefix='/voice')
app.register_blueprint(story_manager_bp)

# 数据库初始化
from models.db import init_db
with app.app_context():
    init_db()

# 静态文件服务配置
@app.route('/uploads/<filename>')
def uploaded_file(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename)

# 启动应用
if __name__ == '__main__':
    # 获取端口配置
    port = int(os.environ.get('PORT', 5000))
    
    # 启动Flask应用
    app.run(
        debug=os.environ.get('DEBUG', 'True').lower() == 'true',
        host='0.0.0.0',  # 允许外部访问
        port=port
    )

2. 故事管理路由 (routes/story_manager_routes.py)

from flask import Blueprint, request, jsonify
from services.story_manager import StoryManager

# 创建故事管理蓝图
bp = Blueprint('story_manager', __name__)

# 获取所有故事
@bp.route('/stories', methods=['GET'])
def get_all_stories():
    try:
        # 从请求参数获取分页信息
        page = request.args.get('page', 1, type=int)
        per_page = request.args.get('per_page', 10, type=int)
        
        # 调用故事管理服务获取故事列表
        stories = StoryManager.get_stories(page=page, per_page=per_page)
        
        # 返回故事列表
        return jsonify({
            'stories': stories['stories'],
            'total': stories['total'],
            'page': stories['page'],
            'per_page': stories['per_page'],
            'pages': stories['pages']
        }), 200
        
    except Exception as e:
        print(f"❌ 获取故事列表失败: {e}")
        return jsonify({'error': f'获取故事列表失败: {str(e)}'}), 500

# 获取单个故事
@bp.route('/stories/<int:story_id>', methods=['GET'])
def get_story(story_id):
    try:
        # 调用故事管理服务获取单个故事
        story = StoryManager.get_story(story_id)
        
        if story:
            return jsonify(story), 200
        else:
            return jsonify({'error': '故事不存在'}), 404
            
    except Exception as e:
        print(f"❌ 获取故事失败: {e}")
        return jsonify({'error': f'获取故事失败: {str(e)}'}), 500

# 保存新故事
@bp.route('/save_story', methods=['POST'])
def save_story():
    try:
        # 获取请求数据
        data = request.json
        
        # 验证必要的参数
        if not data or 'title' not in data or 'content' not in data:
            return jsonify({'error': '缺少必要的故事标题或内容参数'}), 400
        
        # 调用故事管理服务创建故事
        story_id = StoryManager.create_story(data)
        
        # 返回创建成功的故事ID
        return jsonify({
            'message': '故事保存成功',
            'story_id': story_id
        }), 201
        
    except Exception as e:
        print(f"❌ 保存故事失败: {e}")
        return jsonify({'error': f'保存故事失败: {str(e)}'}), 500

# 更新故事
@bp.route('/stories/<int:story_id>', methods=['PUT'])
def update_story(story_id):
    try:
        # 获取请求数据
        data = request.json
        
        # 调用故事管理服务更新故事
        success = StoryManager.update_story(story_id, data)
        
        if success:
            return jsonify({'message': '故事更新成功'}), 200
        else:
            return jsonify({'error': '故事不存在或更新失败'}), 404
            
    except Exception as e:
        print(f"❌ 更新故事失败: {e}")
        return jsonify({'error': f'更新故事失败: {str(e)}'}), 500

# 删除故事
@bp.route('/stories/<int:story_id>', methods=['DELETE'])
def delete_story(story_id):
    try:
        # 调用故事管理服务删除故事
        success = StoryManager.delete_story(story_id)
        
        if success:
            return jsonify({'message': '故事删除成功'}), 200
        else:
            return jsonify({'error': '故事不存在或删除失败'}), 404
            
    except Exception as e:
        print(f"❌ 删除故事失败: {e}")
        return jsonify({'error': f'删除故事失败: {str(e)}'}), 500

# 批量删除故事
@bp.route('/stories/batch-delete', methods=['DELETE'])
def batch_delete_stories():
    try:
        # 获取请求数据
        data = request.json
        
        # 验证必要的参数
        if not data or 'ids' not in data or not isinstance(data['ids'], list):
            return jsonify({'error': '缺少必要的故事ID列表参数'}), 400
        
        # 调用故事管理服务批量删除故事
        success_count = StoryManager.batch_delete_story(data['ids'])
        
        return jsonify({
            'message': '批量删除完成',
            'deleted_count': success_count
        }), 200
        
    except Exception as e:
        print(f"❌ 批量删除故事失败: {e}")
        return jsonify({'error': f'批量删除故事失败: {str(e)}'}), 500

# 切换收藏状态
@bp.route('/stories/<int:story_id>/favorite', methods=['POST'])
def toggle_favorite(story_id):
    try:
        # 调用故事管理服务切换收藏状态
        result = StoryManager.toggle_favorite(story_id)
        
        if result:
            return jsonify({
                'message': '收藏状态已更新',
                'is_favorite': result['is_favorite']
            }), 200
        else:
            return jsonify({'error': '故事不存在'}), 404
            
    except Exception as e:
        print(f"❌ 切换收藏状态失败: {e}")
        return jsonify({'error': f'切换收藏状态失败: {str(e)}'}), 500

# 获取收藏的故事
@bp.route('/stories/favorites', methods=['GET'])
def get_favorite_stories():
    try:
        # 调用故事管理服务获取收藏的故事
        favorites = StoryManager.get_favorite_stories()
        
        return jsonify({
            'stories': favorites
        }), 200
        
    except Exception as e:
        print(f"❌ 获取收藏故事失败: {e}")
        return jsonify({'error': f'获取收藏故事失败: {str(e)}'}), 500

3. 故事管理服务 (services/story_manager.py)

from models.story import Story
from models.db import db
from datetime import datetime

class StoryManager:
    """故事管理服务类"""
    
    @staticmethod
    def create_story(story_data):
        """
        创建新故事
        
        Args:
            story_data: 故事数据字典
        
        Returns:
            int: 创建的故事ID
        """
        try:
            # 创建故事对象
            story = Story(
                title=story_data.get('title', ''),
                summary=story_data.get('summary', ''),
                content=story_data.get('content', ''),
                age_group=story_data.get('age_group', 'all'),
                keywords=story_data.get('keywords', ''),
                image_url=story_data.get('image_url', ''),
                audio_url=story_data.get('audio_url', ''),
                is_favorite=False,
                created_at=datetime.utcnow(),
                updated_at=datetime.utcnow()
            )
            
            # 保存到数据库
            db.session.add(story)
            db.session.commit()
            
            return story.id
            
        except Exception as e:
            db.session.rollback()
            raise Exception(f"创建故事失败: {str(e)}")
    
    @staticmethod
    def get_story(story_id):
        """
        获取单个故事
        
        Args:
            story_id: 故事ID
        
        Returns:
            dict: 故事信息字典
        """
        try:
            # 查询故事
            story = Story.query.get(story_id)
            
            if story:
                # 转换为字典返回
                return {
                    'id': story.id,
                    'title': story.title,
                    'summary': story.summary,
                    'content': story.content,
                    'age_group': story.age_group,
                    'keywords': story.keywords,
                    'image_url': story.image_url,
                    'audio_url': story.audio_url,
                    'is_favorite': story.is_favorite,
                    'created_at': story.created_at.isoformat() if story.created_at else None,
                    'updated_at': story.updated_at.isoformat() if story.updated_at else None
                }
            
            return None
            
        except Exception as e:
            raise Exception(f"获取故事失败: {str(e)}")
    
    @staticmethod
    def get_stories(page=1, per_page=10):
        """
        获取故事列表
        
        Args:
            page: 页码
            per_page: 每页数量
        
        Returns:
            dict: 包含故事列表和分页信息的字典
        """
        try:
            # 分页查询
            pagination = Story.query.order_by(Story.created_at.desc()).paginate(
                page=page, per_page=per_page, error_out=False
            )
            
            # 转换为字典列表
            stories = [
                {
                    'id': story.id,
                    'title': story.title,
                    'summary': story.summary,
                    'age_group': story.age_group,
                    'keywords': story.keywords,
                    'image_url': story.image_url,
                    'audio_url': story.audio_url,
                    'is_favorite': story.is_favorite,
                    'created_at': story.created_at.isoformat() if story.created_at else None
                }
                for story in pagination.items
            ]
            
            # 返回分页结果
            return {
                'stories': stories,
                'total': pagination.total,
                'page': page,
                'per_page': per_page,
                'pages': pagination.pages
            }
            
        except Exception as e:
            raise Exception(f"获取故事列表失败: {str(e)}")
    
    @staticmethod
    def update_story(story_id, story_data):
        """
        更新故事
        
        Args:
            story_id: 故事ID
            story_data: 要更新的数据
        
        Returns:
            bool: 更新是否成功
        """
        try:
            # 查询故事
            story = Story.query.get(story_id)
            
            if story:
                # 更新字段
                if 'title' in story_data:
                    story.title = story_data['title']
                if 'summary' in story_data:
                    story.summary = story_data['summary']
                if 'content' in story_data:
                    story.content = story_data['content']
                if 'age_group' in story_data:
                    story.age_group = story_data['age_group']
                if 'keywords' in story_data:
                    story.keywords = story_data['keywords']
                if 'image_url' in story_data:
                    story.image_url = story_data['image_url']
                if 'audio_url' in story_data:
                    story.audio_url = story_data['audio_url']
                
                # 更新时间
                story.updated_at = datetime.utcnow()
                
                # 保存到数据库
                db.session.commit()
                return True
            
            return False
            
        except Exception as e:
            db.session.rollback()
            raise Exception(f"更新故事失败: {str(e)}")
    
    @staticmethod
    def delete_story(story_id):
        """
        删除故事
        
        Args:
            story_id: 故事ID
        
        Returns:
            bool: 删除是否成功
        """
        try:
            # 查询故事
            story = Story.query.get(story_id)
            
            if story:
                # 删除故事
                db.session.delete(story)
                db.session.commit()
                return True
            
            return False
            
        except Exception as e:
            db.session.rollback()
            raise Exception(f"删除故事失败: {str(e)}")
    
    @staticmethod
    def batch_delete_story(story_ids):
        """
        批量删除故事
        
        Args:
            story_ids: 故事ID列表
        
        Returns:
            int: 成功删除的数量
        """
        try:
            # 批量删除
            deleted_count = Story.query.filter(Story.id.in_(story_ids)).delete(synchronize_session=False)
            db.session.commit()
            
            return deleted_count
            
        except Exception as e:
            db.session.rollback()
            raise Exception(f"批量删除故事失败: {str(e)}")
    
    @staticmethod
    def toggle_favorite(story_id):
        """
        切换收藏状态
        
        Args:
            story_id: 故事ID
        
        Returns:
            dict: 更新后的收藏状态,或None
        """
        try:
            # 查询故事
            story = Story.query.get(story_id)
            
            if story:
                # 切换收藏状态
                story.is_favorite = not story.is_favorite
                story.updated_at = datetime.utcnow()
                
                # 保存到数据库
                db.session.commit()
                
                return {
                    'is_favorite': story.is_favorite
                }
            
            return None
            
        except Exception as e:
            db.session.rollback()
            raise Exception(f"切换收藏状态失败: {str(e)}")
    
    @staticmethod
    def get_favorite_stories():
        """
        获取收藏的故事
        
        Returns:
            list: 收藏的故事列表
        """
        try:
            # 查询收藏的故事
            favorite_stories = Story.query.filter_by(is_favorite=True).order_by(
                Story.updated_at.desc()
            ).all()
            
            # 转换为字典列表
            return [
                {
                    'id': story.id,
                    'title': story.title,
                    'summary': story.summary,
                    'age_group': story.age_group,
                    'keywords': story.keywords,
                    'image_url': story.image_url,
                    'audio_url': story.audio_url,
                    'is_favorite': story.is_favorite,
                    'created_at': story.created_at.isoformat() if story.created_at else None,
                    'updated_at': story.updated_at.isoformat() if story.updated_at else None
                }
                for story in favorite_stories
            ]
            
        except Exception as e:
            raise Exception(f"获取收藏故事失败: {str(e)}")

4. 完整工作流前端实现 (static/js/generate.js)

// 生成按钮点击事件
async function generateStory() {
    // 获取表单数据
    const keywords = document.getElementById('keywords').value.trim();
    const ageGroup = document.getElementById('ageGroup').value;
    
    // 表单验证
    if (!keywords) {
        showMessage('请输入故事关键词', 'error');
        return;
    }
    
    // 显示加载状态
    showLoading(true);
    showMessage('开始生成故事...', 'info');
    
    try {
        // 1. 生成故事文本
        const storyData = await generateStoryText(keywords, ageGroup);
        if (!storyData) return;
        
        // 2. 生成故事插图
        const imageData = await generateIllustration(storyData.title, storyData.content);
        if (!imageData) return;
        
        // 3. 生成故事音频
        const audioData = await generateVoice(storyData.content, 'child');
        if (!audioData) return;
        
        // 4. 保存完整故事
        const savedStory = await saveCompleteStory({
            title: storyData.title,
            summary: storyData.summary,
            content: storyData.content,
            age_group: ageGroup,
            keywords: keywords,
            image_url: imageData.url,
            audio_url: audioData.url
        });
        
        if (savedStory) {
            // 显示成功信息
            showMessage('故事生成完成!', 'success');
            
            // 显示生成的故事
            displayStory({
                ...savedStory,
                image_url: imageData.url,
                audio_url: audioData.url
            });
        }
        
    } catch (error) {
        showMessage(`生成过程中出错: ${error.message}`, 'error');
    } finally {
        showLoading(false);
    }
}

// 生成故事文本
async function generateStoryText(keywords, ageGroup) {
    try {
        // 更新进度
        updateProgress(33, '正在生成故事文本...');
        
        // 调用故事生成API
        const response = await fetch('/story/generate', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                keywords: keywords,
                age_group: ageGroup
            })
        });
        
        if (!response.ok) {
            const error = await response.json();
            throw new Error(error.error || '故事生成失败');
        }
        
        const storyData = await response.json();
        showMessage('故事文本生成成功!', 'success');
        
        return storyData;
        
    } catch (error) {
        showMessage(`故事生成失败: ${error.message}`, 'error');
        return null;
    }
}

// 生成故事插图
async function generateIllustration(title, content) {
    try {
        // 更新进度
        updateProgress(66, '正在生成故事插图...');
        
        // 构建插图提示词(使用标题和内容摘要)
        const prompt = `${title}。${content.substring(0, 100)}...`;
        
        // 调用图像生成API
        const response = await fetch('/image/generate', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                prompt: prompt,
                style: 'cartoon',
                size: '1024x1024'
            })
        });
        
        if (!response.ok) {
            const error = await response.json();
            throw new Error(error.error || '插图生成失败');
        }
        
        const imageData = await response.json();
        showMessage('故事插图生成成功!', 'success');
        
        return imageData;
        
    } catch (error) {
        showMessage(`插图生成失败: ${error.message}`, 'error');
        return null;
    }
}

// 生成故事音频
async function generateVoice(content, voiceType) {
    try {
        // 更新进度
        updateProgress(99, '正在生成故事音频...');
        
        // 调用语音合成API
        const response = await fetch('/voice/synthesize', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                text: content,
                voice_type: voiceType,
                speed: 'normal'
            })
        });
        
        if (!response.ok) {
            const error = await response.json();
            throw new Error(error.error || '音频生成失败');
        }
        
        const audioData = await response.json();
        showMessage('故事音频生成成功!', 'success');
        
        return audioData;
        
    } catch (error) {
        showMessage(`音频生成失败: ${error.message}`, 'error');
        return null;
    }
}

// 保存完整故事
async function saveCompleteStory(storyData) {
    try {
        // 调用保存故事API
        const response = await fetch('/save_story', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(storyData)
        });
        
        if (!response.ok) {
            const error = await response.json();
            throw new Error(error.error || '故事保存失败');
        }
        
        const savedData = await response.json();
        
        // 返回完整的故事数据
        return {
            id: savedData.story_id,
            title: storyData.title,
            summary: storyData.summary,
            content: storyData.content,
            age_group: storyData.age_group,
            keywords: storyData.keywords
        };
        
    } catch (error) {
        showMessage(`故事保存失败: ${error.message}`, 'error');
        return null;
    }
}

// 更新进度条
function updateProgress(percentage, message) {
    const progressBar = document.getElementById('progressBar');
    const progressText = document.getElementById('progressText');
    
    progressBar.style.width = `${percentage}%`;
    progressText.textContent = message;
}

// 显示加载状态
function showLoading(show) {
    const loadingOverlay = document.getElementById('loadingOverlay');
    const progressContainer = document.getElementById('progressContainer');
    
    if (show) {
        loadingOverlay.classList.remove('hidden');
        progressContainer.classList.remove('hidden');
    } else {
        loadingOverlay.classList.add('hidden');
        progressContainer.classList.add('hidden');
    }
}

// 显示消息
function showMessage(message, type = 'info') {
    const messageContainer = document.getElementById('messageContainer');
    
    // 清空现有消息
    messageContainer.innerHTML = '';
    
    // 创建新消息元素
    const messageElement = document.createElement('div');
    messageElement.className = `message ${type}`;
    messageElement.textContent = message;
    
    // 添加到容器
    messageContainer.appendChild(messageElement);
    
    // 自动隐藏(非错误消息)
    if (type !== 'error') {
        setTimeout(() => {
            messageElement.remove();
        }, 5000);
    }
}

// 显示生成的故事
function displayStory(story) {
    const storyDisplay = document.getElementById('storyDisplay');
    
    // 创建故事内容
    storyDisplay.innerHTML = `
        <div class="story-container">
            <h2>${story.title}</h2>
            <div class="story-meta">
                <span>适合年龄:${getAgeGroupName(story.age_group)}</span>
                <span>关键词:${story.keywords}</span>
            </div>
            
            <div class="story-content">
                <div class="story-image">
                    <img src="${story.image_url}" alt="${story.title}">
                </div>
                
                <div class="story-text">
                    <p>${story.content}</p>
                </div>
            </div>
            
            <div class="story-audio">
                <h3>🎧 听故事</h3>
                <audio controls>
                    <source src="${story.audio_url}" type="audio/wav">
                    您的浏览器不支持音频播放。
                </audio>
            </div>
            
            <div class="story-actions">
                <button onclick="window.location.href='/stories'" class="btn btn-primary">
                    查看所有故事
                </button>
                <button onclick="window.location.href='/generate'" class="btn btn-secondary">
                    生成新故事
                </button>
            </div>
        </div>
    `;
    
    // 滚动到故事显示区域
    storyDisplay.scrollIntoView({ behavior: 'smooth' });
}

// 获取年龄组名称
function getAgeGroupName(ageGroup) {
    const ageGroups = {
        '3-6': '3-6岁',
        '6-9': '6-9岁',
        '9-12': '9-12岁',
        'all': '所有年龄段'
    };
    
    return ageGroups[ageGroup] || ageGroup;
}

// 初始化
function init() {
    // 绑定生成按钮事件
    document.getElementById('generateBtn').addEventListener('click', generateStory);
    
    // 绑定回车键事件
    document.getElementById('keywords').addEventListener('keypress', (e) => {
        if (e.key === 'Enter') {
            generateStory();
        }
    });
}

// 页面加载完成后初始化
window.addEventListener('DOMContentLoaded', init);

完整工作流程

用户故事生成流程

  1. 用户输入:用户在生成页面输入故事关键词和选择适合的年龄段
  2. 故事生成:系统调用实验一的故事生成服务,基于关键词创建儿童故事
  3. 插图生成:系统调用实验二的插图生成服务,为故事生成配套插图
  4. 语音合成:系统调用实验三的语音合成服务,为故事生成朗读音频
  5. 数据保存:将完整的故事(文本、插图、音频)保存到数据库
  6. 结果展示:在页面上展示生成的故事,包括文本、插图和音频播放器

故事管理流程

  1. 故事列表:用户可以浏览所有生成的故事,支持分页查看
  2. 故事详情:查看单个故事的完整内容,包括文本、插图和音频
  3. 故事收藏:标记喜欢的故事为收藏,方便快速访问
  4. 故事删除:删除不需要的故事,支持单个删除和批量删除

技术栈集成

后端技术栈

  • Python 3.12:主要开发语言
  • Flask:Web框架,处理HTTP请求和路由
  • SQLAlchemy:ORM框架,处理数据库操作
  • 阿里云百炼:提供文本生成、图像生成和语音合成API
  • 百度AI平台:作为语音合成的备用方案
  • pydub:音频处理库,用于音频合并和格式转换

前端技术栈

  • HTML5/CSS3:页面结构和样式
  • JavaScript (ES6+):交互逻辑和API调用
  • Bootstrap:响应式UI框架
  • Fetch API:处理HTTP请求

数据库

  • SQLite:轻量级数据库,用于存储故事数据

文件存储

  • 本地文件系统:存储生成的图像和音频文件

系统特点

完整的工作流

  • 集成了三个实验的核心功能,实现端到端的故事生成体验
  • 用户只需输入关键词,系统自动完成故事、插图和音频的生成
  • 生成的多媒体故事可以保存、管理和再次访问

友好的用户界面

  • 直观的生成页面,简洁的操作流程
  • 美观的故事展示,支持文本阅读和音频播放
  • 方便的故事管理功能,包括收藏和删除

强大的容错机制

  • 每个服务都有错误处理和备用方案
  • 即使某个服务失败,也能保证基本功能可用
  • 详细的错误提示,帮助用户了解问题

灵活的配置选项

  • 支持选择不同的年龄段和声音类型
  • 可配置不同的图像风格和尺寸
  • 支持自定义语速和其他参数

部署说明

  1. 环境准备

    • Python 3.12
    • pip包管理器
    • 环境变量配置(阿里云和百度API密钥)
  2. 安装依赖

    pip install -r requirements.txt
    
  3. 配置文件

    • 创建.env文件,配置必要的环境变量
  4. 启动服务

    python app.py
    
  5. 访问应用

后续扩展方向

  1. 用户系统:添加用户注册和登录功能,支持个人故事收藏
  2. 更多AI模型:集成更多的AI模型,提供多样化的故事风格
  3. 多语言支持:支持生成和朗读不同语言的故事
  4. 社交分享:添加故事分享功能,方便用户分享给朋友
  5. 数据分析:添加用户行为分析,优化故事推荐
  6. 移动端适配:优化移动端体验,开发移动应用

总结

儿童故事管理平台成功集成了三个实验的核心功能,构建了一个完整的AI驱动的儿童故事生成和管理系统。用户可以通过简单的关键词输入,快速生成包含文本、插图和音频的多媒体故事,并进行管理和收藏。系统采用了模块化的设计,各组件之间松耦合,便于维护和扩展。同时,完善的错误处理和备用方案确保了系统的稳定性和可用性。

posted @ 2025-12-28 23:52  ysd666  阅读(3)  评论(0)    收藏  举报