Browse Source

Merge branch 'master' of http://git.fmode.cn:3000/19808003398/20222670105

祝雨婧 3 months ago
parent
commit
9c4248489d

+ 404 - 0
novel-app/docs-prod/ShortGeneratorCreation.md

@@ -0,0 +1,404 @@
+# 短篇小说创建模块 uml编写
+
+# 一、Scheema范式设计
+> 提示词 {系统描述} 如上述,请你帮我分析所需的Parse Schema范式表及具体的字段名称,表名大驼峰,字段小驼峰。可以用plantuml的类图来表示,各个表需要符合设计范式。注意外键关联使用Pointer<类名>这种方式表示。每张表默认有objectId唯一表示和createdAt创建时间。
+## 短篇小说创建模块
+- 模块描述
+用户进行短篇小说生成,短篇小说创建有故事大纲,小说角色,小说场景,角色对话,情节发展,反馈等
+为了设计一个智能体创建模块的Parse Schema,我们需要创建故事大纲表(`StoryOutline`)、角色表(`Character`)、场景表(`Scene`)、对话表(`Dialogue`)、情节发展表(`PlotDevelopment`)、反馈与修改表(`FeedbackModification`)。根据你的要求,以下是所需的Parse Schema范式表及具体的字段名称。
+
+
+### 1. 表及字段说明:
+### 1.1 StoryOutline(故事大纲表)
+
+- **objectId**: 唯一标识(自动生成)
+- **createdAt**: 创建时间(自动生成)
+- **title**: 标题(String)
+- **summary**: 简介(String)
+- **theme**: 主题(String)
+- **mainConflict**: 主要冲突(String)
+- **structure**: 结构(如起承转合)(String)
+
+### 1.2 Character(角色表)
+
+- **objectId**: 唯一标识(自动生成)
+- **createdAt**: 创建时间(自动生成)
+- **updateAt**:更新时间(自动生成)
+- **name**: 姓名 (String)
+- **age**: 年龄 (String)
+- **gender**: 性别 (String)
+- **backgroundStory**: 背景故事 (String)
+- **personalityTraits**: 性格特征 (String)
+- **relationships**: 角色关系(与其他角色的关系)(Array<Pointer>)
+
+### 1.3 Scene(场景表)
+
+- **objectId**: 唯一标识 (自动生成)
+- **createdAt**: 创建时间 (自动生成)
+- **updatedAt**: 更新时间(自动生成)
+- **description**: 场景描述 (自动生成)
+- **time**: 发生时间 (Date)
+- **location**: 地点 (String)
+- **participants**: 参与角色  (Array<Pointer>)
+- **importantEvents**: 重要事件 (String)
+
+### 1.4 Dialogue(对话表)
+
+- **objectId**: 唯一标识(自动生成)
+- **createdAt**: 创建时间(自动生成)
+- **updatedAt**: 更新时间(自动生成)
+- **scene**: 关联场景(Pointer)
+- **character**: 关联角色(Pointer)
+- **content**: 对话内容(String)
+- **emotionExpression**: 情感表达(String)
+- **purpose**: 对话目的(String)
+
+### 1.5 PlotDevelopment(情节发展表)
+
+- **objectId**: 唯一标识(自动生成)
+- **createdAt**: 创建时间(自动生成)
+- **updatedAt**: 更新时间(自动生成)
+- **story**: 关联故事大纲(Pointer)
+- **description**: 情节描述(String)
+- **sequence**: 发生顺序(Integer)
+- **keyTurningPoints**: 关键转折点(String)
+
+### 1.6 FeedbackModification(反馈与修改表)
+
+- **objectId**: 唯一标识(自动生成)
+- **createdAt**: 创建时间(自动生成)
+- **updatedAt**: 更新时间(自动生成)
+- **story**: 关联故事大纲(Pointer)
+- **feedbackContent**: 反馈内容(String)
+- **modificationSuggestions**: 修改建议(String)
+- **status**: 状态(待处理、已处理)(String)
+
+关联关系:
+故事大纲包含多个角色和场景。
+场景包含多个对话。
+角色可以参与多个对话。
+故事大纲发展出多个情节。
+故事大纲可以收到多个反馈与修改建议。
+这种设计能够有效地组织短篇小说创作的各个要素,确保数据之间的关系清晰。
+
+### 2. PlantUML 类图表示
+
+```plantuml
+@startuml
+
+class StoryOutline {
+    +objectId: String  // 唯一标识
+    +createdAt: Date  // 创建时间
+    +updatedAt: Date  // 更新时间
+    +title: String  // 标题
+    +summary: String  // 简介
+    +theme: String  // 主题
+    +mainConflict: String  // 主要冲突
+    +structure: String  // 结构(如起承转合)
+}
+
+class Character {
+    +objectId: String  // 唯一标识
+    +createdAt: Date  // 创建时间
+    +updatedAt: Date  // 更新时间
+    +name: String  // 姓名
+    +age: Integer  // 年龄
+    +gender: String  // 性别
+    +backgroundStory: String  // 背景故事
+    +personalityTraits: String  // 性格特征
+    +relationships: Array>  // 角色关系(与其他角色的关系)
+}
+
+class Scene {
+    +objectId: String  // 唯一标识
+    +createdAt: Date  // 创建时间
+    +updatedAt: Date  // 更新时间
+    +description: String  // 场景描述
+    +time: Date  // 发生时间
+    +location: String  // 地点
+    +participants: Array>  // 参与角色
+    +importantEvents: String  // 重要事件
+}
+
+class Dialogue {
+    +objectId: String  // 唯一标识
+    +createdAt: Date  // 创建时间
+    +updatedAt: Date  // 更新时间
+    +scene: Pointer  // 关联场景
+    +character: Pointer  // 关联角色
+    +content: String  // 对话内容
+    +emotionExpression: String  // 情感表达
+    +purpose: String  // 对话目的
+}
+
+class PlotDevelopment {
+    +objectId: String  // 唯一标识
+    +createdAt: Date  // 创建时间
+    +updatedAt: Date  // 更新时间
+    +story: Pointer  // 关联故事大纲
+    +description: String  // 情节描述
+    +sequence: Integer  // 发生顺序
+    +keyTurningPoints: String  // 关键转折点
+}
+
+class FeedbackModification {
+    +objectId: String  // 唯一标识
+    +createdAt: Date  // 创建时间
+    +updatedAt: Date  // 更新时间
+    +story: Pointer  // 关联故事大纲
+    +feedbackContent: String  // 反馈内容
+    +modificationSuggestions: String  // 修改建议
+    +status: String  // 状态(待处理、已处理)
+}
+
+StoryOutline "1" -- "0..*" Character : contains
+StoryOutline "1" -- "0..*" Scene : contains
+Scene "1" -- "0..*" Dialogue : contains
+Character "1" -- "0..*" Dialogue : speaks
+StoryOutline "1" -- "0..*" PlotDevelopment : develops
+StoryOutline "1" -- "0..*" FeedbackModification : receives
+
+@enduml
+```
+
+# 二、业务逻辑描述
+# 短篇小说创建的完整逻辑
+## 创建逻辑
+
+1. **用户在APP内创建短篇小说**
+   - 用户点击“创建小说”按钮,触发创建短篇小说的逻辑。
+
+2. **数据采集**
+   - 用户输入以下数据:
+     - **标题**(title):用户为小说输入标题。
+     - **简介**(summary):用户为小说输入简要介绍。
+     - **主题**(theme):用户选择或输入小说的主题。
+     - **主要冲突**(mainConflict):用户描述小说的主要冲突或矛盾。
+     - **结构**(structure):用户选择或输入小说的结构(如起承转合)。
+
+3. **角色创建**
+   - 用户为小说输入角色信息:
+     - **角色姓名**(name):用户为角色输入姓名。
+     - **角色年龄**(age):用户输入角色的年龄。
+     - **角色性别**(gender):用户选择角色的性别。
+     - **背景故事**(backgroundStory):用户输入角色的背景故事。
+     - **性格特征**(personalityTraits):用户描述角色的性格特征。
+     - **角色关系**(relationships):用户输入角色之间的关系。
+
+4. **场景创建**
+   - 用户为小说输入场景信息:
+     - **场景描述**(description):用户输入场景的详细描述。
+     - **发生时间**(time):用户选择或输入场景发生的时间。
+     - **地点**(location):用户输入场景发生的地点。
+     - **参与角色**(participants):用户选择参与此场景的角色。
+
+5. **对话生成**
+   - 用户为场景创建对话:
+     - **对话内容**(content):用户输入角色之间的对话内容。
+     - **情感表达**(emotionExpression):用户描述对话中角色的情感。
+     - **对话目的**(purpose):用户输入对话的目的。
+
+6. **情节发展描述**
+   - 用户描述情节发展:
+     - **情节描述**(description):用户输入情节发展描述。
+     - **发生顺序**(sequence):用户输入情节发生的顺序。
+     - **关键转折点**(keyTurningPoints):用户描述情节中的关键转折点。
+
+7. **反馈与修改**
+   - 用户可以选择提供反馈和修改建议,输入以下信息:
+     - **反馈内容**(feedbackContent):用户输入对小说的反馈。
+     - **修改建议**(modificationSuggestions):用户输入修改建议。
+     - **状态**(status):用户选择反馈的状态(待处理、已处理)。
+
+8. **文本生成**
+   - 系统根据用户输入的信息生成小说文本,使用提示词来引导生成过程。
+
+9. **结果存储**
+   - 将收集到的数据存入数据库,涉及以下表:
+     - **StoryOutline**表:存储小说的标题、简介、主题、主要冲突、结构及创建人信息。
+     - **Character**表:存储角色的姓名、年龄、性别、背景故事、性格特征及角色关系。
+     - **Scene**表:存储场景的描述、发生时间、地点及参与角色。
+     - **Dialogue**表:存储对话内容、情感表达和对话目的。
+     - **PlotDevelopment**表:存储情节描述、发生顺序及关键转折点。
+     - **FeedbackModification**表:存储用户的反馈内容、修改建议及状态。
+
+10. **用户确认**
+    - 系统向用户展示生成的小说文本,并询问用户是否确认保存。
+    - 用户确认后,系统将所有数据正式保存到数据库中,并返回成功消息。
+
+通过以上步骤,用户能够在APP内顺利创建短篇小说,系统将自动处理数据采集、文本生成和结果存储的逻辑。
+> 提示词:{Dialogue表结构+Dialogue表描述} 请根据Dialogue表结构,生成一个JSON格式的Array数组测试数据。
+```json
+[
+    {
+        "objectId": "1",
+        "createdAt": "2024-12-15T10:00:00Z",
+        "updatedAt": "2024-12-15T10:00:00Z",
+        "scene": {
+            "__type": "Pointer",
+            "className": "Scene",
+            "objectId": "scene123"
+        },
+        "character": {
+            "__type": "Pointer",
+            "className": "Character",
+            "objectId": "char456"
+        },
+        "content": "你好!今天的天气真不错。",
+        "emotionExpression": "快乐",
+        "purpose": "打招呼"
+    },
+    {
+        "objectId": "2",
+        "createdAt": "2024-12-15T10:05:00Z",
+        "updatedAt": "2024-12-15T10:05:00Z",
+        "scene": {
+            "__type": "Pointer",
+            "className": "Scene",
+            "objectId": "scene123"
+        },
+        "character": {
+            "__type": "Pointer",
+            "className": "Character",
+            "objectId": "char789"
+        },
+        "content": "是啊,我也觉得很舒服。",
+        "emotionExpression": "放松",
+        "purpose": "回应"
+    },
+    {
+        "objectId": "3",
+        "createdAt": "2024-12-15T10:10:00Z",
+        "updatedAt": "2024-12-15T10:10:00Z",
+        "scene": {
+            "__type": "Pointer",
+            "className": "Scene",
+            "objectId": "scene456"
+        },
+        "character": {
+            "__type": "Pointer",
+            "className": "Character",
+            "objectId": "char456"
+        },
+        "content": "你想去公园散步吗?",
+        "emotionExpression": "期待",
+        "purpose": "邀请"
+    },
+    {
+        "objectId": "4",
+        "createdAt": "2024-12-15T10:15:00Z",
+        "updatedAt": "2024-12-15T10:15:00Z",
+        "scene": {
+            "__type": "Pointer",
+            "className": "Scene",
+            "objectId": "scene456"
+        },
+        "character": {
+            "__type": "Pointer",
+            "className": "Character",
+            "objectId": "char789"
+        },
+        "content": "好主意!我正想去那里。",
+        "emotionExpression": "兴奋",
+        "purpose": "接受邀请"
+    },
+    {
+        "objectId": "5",
+        "createdAt": "2024-12-15T10:20:00Z",
+        "updatedAt": "2024-12-15T10:20:00Z",
+        "scene": {
+            "__type": "Pointer",
+            "className": "Scene",
+            "objectId": "scene789"
+        },
+        "character": {
+            "__type": "Pointer",
+            "className": "Character",
+            "objectId": "char101"
+        },
+        "content": "你觉得这本书怎么样?",
+        "emotionExpression": "好奇",
+        "purpose": "询问意见"
+    }
+]
+```
+# 智能体创建业务逻辑图例
+>提示词:{业务逻辑},您是一名专业的产品经理,请您将上述逻辑的每个过程,用plantuml的时序图表示出来。 
+以下是根据短篇小说创建逻辑生成的 PlantUML 时序图,展示了每个过程的交互和顺序。
+
+```plantuml
+@startuml
+
+actor User
+participant "APP" as App
+participant "Database" as DB
+participant "Dialogue Generator" as DG
+participant "Character Generator" as CG
+participant "Scene Generator" as SG
+participant "Plot Development" as PD
+participant "Feedback System" as FS
+
+User -> App: 点击“创建小说”
+App -> User: 显示输入表单
+
+User -> App: 输入小说标题、简介、主题、主要冲突、结构
+App -> App: 收集用户输入数据
+
+User -> App: 输入角色信息
+App -> CG: 创建角色
+CG -> DB: 存储角色数据
+DB -> CG: 返回角色ID
+
+User -> App: 输入场景信息
+App -> SG: 创建场景
+SG -> DB: 存储场景数据
+DB -> SG: 返回场景ID
+
+User -> App: 输入对话信息
+App -> DG: 创建对话
+DG -> DB: 存储对话数据
+DB -> DG: 返回对话ID
+
+User -> App: 输入情节发展信息
+App -> PD: 创建情节发展
+PD -> DB: 存储情节数据
+DB -> PD: 返回情节ID
+
+User -> App: 输入反馈与修改信息
+App -> FS: 提交反馈
+FS -> DB: 存储反馈数据
+DB -> FS: 返回反馈ID
+
+App -> DG: 生成小说文本
+DG -> App: 返回生成的小说文本
+
+App -> User: 显示生成的小说文本
+User -> App: 确认保存
+App -> DB: 保存所有数据
+DB -> App: 返回成功消息
+
+@enduml
+```
+
+### 图示说明:
+1. **User**: 代表用户,与APP进行交互。
+2. **APP**: 用户界面,负责收集用户输入和显示结果。
+3. **Database (DB)**: 数据库,负责存储所有数据。
+4. **Dialogue Generator (DG)**: 对话生成模块,负责生成对话内容。
+5. **Character Generator (CG)**: 角色生成模块,负责生成角色信息。
+6. **Scene Generator (SG)**: 场景生成模块,负责生成场景信息。
+7. **Plot Development (PD)**: 情节发展模块,负责生成情节信息。
+8. **Feedback System (FS)**: 反馈系统,负责处理用户反馈和修改建议。
+### 流程:
+1. 用户点击“创建小说”,APP显示输入表单。
+2. 用户输入小说的基本信息。
+3. 用户输入角色信息,角色生成模块创建角色并存储数据。
+4. 用户输入场景信息,场景生成模块创建场景并存储数据。
+5. 用户输入对话信息,对话生成模块创建对话并存储数据。
+6. 用户输入情节发展信息,情节发展模块创建情节并存储数据。
+7. 用户输入反馈与修改信息,反馈系统存储反馈数据。
+8. APP请求对话生成模块生成小说文本。
+9. APP显示生成的小说文本给用户。
+10. 用户确认保存,APP将所有数据保存到数据库。
+11. 数据库返回成功消息。
+这个时序图清晰地展示了短篇小说创建过程中的各个步骤及其交互关系。 

+ 59 - 54
novel-app/src/app/app.routes.ts

@@ -1,58 +1,63 @@
-import { HttpClientModule } from '@angular/common/http';
-import { NgModule } from '@angular/core';
-import { PreloadAllModules, RouteReuseStrategy, RouterModule, Routes } from '@angular/router';
-import { IonicRouteStrategy } from '@ionic/angular';
-
-export const routes: Routes = [
-  {
-    path: '',
-    loadChildren: () => import('./tabs/tabs.routes').then((m) => m.routes),
-  },
-  {
-    path: 'story-generator',
-    loadComponent: () => import('./story-generator/story-generator.page').then(m => m.StoryGeneratorPage)
-  },
-  {
-    path: 'toolbox',
-    loadComponent: () => import('./toolbox/toolbox.page').then(m => m.ToolboxPage)
-  },
-  {
-    path: '',
-    loadChildren: () => import('./tabs/tabs.routes').then((m) => m.routes),
-  },
-  {
-    path: 'register',
-    loadComponent: () => import('./register/register.page').then(m => m.RegisterPage)
-  },
-  {
-    path: 'login',
-    loadComponent: () => import('./login/login.page').then(m => m.LoginPage)
-  },
-  {
-    path: 'short-generator',
-    loadComponent: () => import('./short-generator/short-generator.page').then(m => m.ShortGeneratorPage)
-  },
-  {
-    path: 'short-novel',
-    loadComponent: () => import('./short-novel/short-novel.page').then(m => m.ShortNovelPage)
-  },
  {
+import { HttpClientModule } from '@angular/common/http';
+import { NgModule } from '@angular/core';
+import { PreloadAllModules, RouteReuseStrategy, RouterModule, Routes } from '@angular/router';
+import { IonicRouteStrategy } from '@ionic/angular';
+
+export const routes: Routes = [
+  {
+    path: '',
+    loadChildren: () => import('./tabs/tabs.routes').then((m) => m.routes),
+  },
+  {
+    path: 'story-generator',
+    loadComponent: () => import('./story-generator/story-generator.page').then(m => m.StoryGeneratorPage)
+  },
+  {
+    path: 'toolbox',
+    loadComponent: () => import('./toolbox/toolbox.page').then(m => m.ToolboxPage)
+  },
+  {
+    path: '',
+    loadChildren: () => import('./tabs/tabs.routes').then((m) => m.routes),
+  },
+  {
+    path: 'register',
+    loadComponent: () => import('./register/register.page').then(m => m.RegisterPage)
+  },
+  {
+    path: 'login',
+    loadComponent: () => import('./login/login.page').then(m => m.LoginPage)
+  },
+  {
+    path: 'short-generator',
+    loadComponent: () => import('./short-generator/short-generator.page').then(m => m.ShortGeneratorPage)
+  },
+  {
+    path: 'short-novel',
+    loadComponent: () => import('./short-novel/short-novel.page').then(m => m.ShortNovelPage)
+  },
+  {
     path: 'character',
     loadComponent: () => import('./character/character.page').then( m => m.CharacterPage)
+  },
+  {
+    path: 'character-creator',
+    loadComponent: () => import('./character-creator/character-creator.page').then(m => m.CharacterCreatorPage)
   }
 
-
-
-];
-
-
-
-
-
-@NgModule({
-  imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules }), HttpClientModule],
-  exports: [RouterModule],
-  providers: [
-    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
-  ],
-})
-export class AppRoutingModule { }
+
+
+];
+
+
+
+
+
+@NgModule({
+  imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules }), HttpClientModule],
+  exports: [RouterModule],
+  providers: [
+    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
+  ],
+})
+export class AppRoutingModule { }

+ 53 - 0
novel-app/src/app/character-creator/character-creator.page.html

@@ -0,0 +1,53 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-back-button defaultHref="tabs/character"></ion-back-button>
+    </ion-buttons>
+    <ion-title>创建角色</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content class="ion-padding">
+  <form [formGroup]="characterForm" (ngSubmit)="generateCharacter()">
+    <ion-item>
+      <ion-label position="stacked">角色名称</ion-label>
+      <ion-input formControlName="name" type="text" placeholder="请输入角色名称"></ion-input>
+    </ion-item>
+
+    <ion-item>
+      <ion-label position="stacked">性别</ion-label>
+      <ion-select formControlName="gender" interface="action-sheet">
+        <ion-select-option value="male">男性</ion-select-option>
+        <ion-select-option value="female">女性</ion-select-option>
+      </ion-select>
+    </ion-item>
+
+    <ion-item>
+      <ion-label position="stacked">外貌描述</ion-label>
+      <ion-textarea 
+        formControlName="appearance" 
+        rows="4"
+        class="custom-textarea"
+        placeholder="请详细描述角色的外貌特征,至少20字...">
+      </ion-textarea>
+    </ion-item>
+
+    <ion-item>
+      <ion-label position="stacked">性格描述</ion-label>
+      <ion-textarea 
+        formControlName="personality" 
+        rows="4"
+        class="custom-textarea"
+        placeholder="请详细描述角色的性格特点,至少20字...">
+      </ion-textarea>
+    </ion-item>
+
+    <ion-button 
+      expand="block" 
+      type="submit" 
+      [disabled]="!characterForm.valid"
+      class="ion-margin-top">
+      生成角色智能体
+    </ion-button>
+  </form>
+</ion-content> 

+ 24 - 0
novel-app/src/app/character-creator/character-creator.page.scss

@@ -0,0 +1,24 @@
+ion-item {
+    --padding-start: 0;
+    --padding-end: 0;
+    --inner-padding-end: 0;
+    margin-bottom: 16px;
+  }
+  
+  ion-label {
+    margin-bottom: 8px;
+  }
+  
+  ion-textarea {
+    --padding-top: 8px;
+    --padding-bottom: 8px;
+    --padding-start: 16px;
+    --padding-end: 16px;
+    border: 1px solid var(--ion-color-medium);
+    border-radius: 4px;
+    margin-top: 4px;
+  }
+  
+  .custom-textarea {
+    --background: var(--ion-color-light);
+  } 

+ 17 - 0
novel-app/src/app/character-creator/character-creator.page.spec.ts

@@ -0,0 +1,17 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { CharacterCreatorPage } from './character-creator.page';
+
+describe('CharacterCreatorPage', () => {
+  let component: CharacterCreatorPage;
+  let fixture: ComponentFixture<CharacterCreatorPage>;
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(CharacterCreatorPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 65 - 0
novel-app/src/app/character-creator/character-creator.page.ts

@@ -0,0 +1,65 @@
+import { Component } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { IonicModule } from '@ionic/angular';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { Router } from '@angular/router';
+import { CharacterService } from '../services/character.service';
+import { LoadingController } from '@ionic/angular';
+
+@Component({
+  selector: 'app-character-creator',
+  templateUrl: './character-creator.page.html',
+  styleUrls: ['./character-creator.page.scss'],
+  standalone: true,
+  imports: [CommonModule, IonicModule, FormsModule, ReactiveFormsModule]
+})
+export class CharacterCreatorPage {
+  characterForm!: FormGroup;
+
+  constructor(
+    private formBuilder: FormBuilder,
+    private router: Router,
+    private characterService: CharacterService,
+    private loadingController: LoadingController
+  ) {
+    this.initForm();
+  }
+
+  private initForm() {
+    this.characterForm = this.formBuilder.group({
+      name: ['', Validators.required],
+      gender: ['male', Validators.required],
+      appearance: ['', [Validators.required, Validators.minLength(20)]],
+      personality: ['', [Validators.required, Validators.minLength(20)]]
+    });
+  }
+
+  async generateCharacter() {
+    if (this.characterForm.valid) {
+      const loading = await this.loadingController.create({
+        message: '正在生成角色...'
+      });
+      await loading.present();
+
+      try {
+        const characterData = this.characterForm.value;
+        const avatar = await this.characterService
+          .generateCharacterAvatar(characterData.appearance)
+          .toPromise();
+
+        const character = await this.characterService.createCharacterAgent({
+          ...characterData,
+          avatar,
+          id: Date.now().toString()
+        }).toPromise();
+
+        await loading.dismiss();
+        this.router.navigate(['/character']);
+      } catch (error) {
+        console.error('Error generating character:', error);
+        await loading.dismiss();
+      }
+    }
+  }
+} 

+ 41 - 9
novel-app/src/app/character/character.page.html

@@ -1,13 +1,45 @@
-<ion-header [translucent]="true">
+<ion-header>
   <ion-toolbar>
-    <ion-title>character</ion-title>
+    <ion-title>角色管理</ion-title>
   </ion-toolbar>
 </ion-header>
 
-<ion-content [fullscreen]="true">
-  <ion-header collapse="condense">
-    <ion-toolbar>
-      <ion-title size="large">character</ion-title>
-    </ion-toolbar>
-  </ion-header>
-</ion-content>
+<ion-content>
+  <!-- 空状态显示 -->
+  <div class="empty-state" *ngIf="characters.length === 0">
+    <ion-icon name="people-outline" class="empty-icon"></ion-icon>
+    <h2>暂无角色</h2>
+    <p>点击下方按钮创建新角色</p>
+    <ion-button 
+      expand="block" 
+      style="--background: #ff69b4"
+      (click)="createNewCharacter()">
+      创建角色
+    </ion-button>
+  </div>
+
+  <!-- 角色列表 -->
+  <ion-grid *ngIf="characters.length > 0">
+    <ion-row>
+      <ion-col size="6" size-md="4" size-lg="3" *ngFor="let character of characters">
+        <ion-card class="character-card">
+          <img [src]="character.avatar" [alt]="character.name">
+          <ion-card-header>
+            <ion-card-title>{{character.name}}</ion-card-title>
+          </ion-card-header>
+        </ion-card>
+      </ion-col>
+    </ion-row>
+  </ion-grid>
+
+  <!-- 底部创建按钮 -->
+  <div class="bottom-button" *ngIf="characters.length > 0">
+    <ion-button 
+      expand="block" 
+      style="--background: #ff69b4" 
+      (click)="createNewCharacter()"
+      class="create-button">
+      创建角色
+    </ion-button>
+  </div>
+</ion-content> 

+ 71 - 0
novel-app/src/app/character/character.page.scss

@@ -0,0 +1,71 @@
+.empty-state {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    height: 100%;
+    padding: 2rem;
+    text-align: center;
+  
+    .empty-icon {
+      font-size: 6rem;
+      color: var(--ion-color-medium);
+      margin-bottom: 1rem;
+    }
+  
+    h2 {
+      color: var(--ion-color-dark);
+      margin-bottom: 0.5rem;
+    }
+  
+    p {
+      color: var(--ion-color-medium);
+      margin-bottom: 2rem;
+    }
+  
+    ion-button {
+      max-width: 200px;
+    }
+  }
+  
+  .character-card {
+    margin: 8px;
+    cursor: pointer;
+    transition: transform 0.2s;
+  
+    &:hover {
+      transform: translateY(-4px);
+    }
+  
+    img {
+      width: 100%;
+      height: 200px;
+      object-fit: cover;
+    }
+  
+    ion-card-header {
+      padding: 12px;
+    }
+  
+    ion-card-title {
+      font-size: 1.1rem;
+      text-align: center;
+    }
+  }
+  
+  .bottom-button {
+    position: fixed;
+    bottom: 20px;
+    left: 50%;
+    transform: translateX(-50%);
+    width: 200px;
+    z-index: 999;
+  }
+  
+  .create-button {
+    --background: #ff69b4;  // 粉色
+    --background-hover: #ff1493;  // 深粉色
+    --border-radius: 20px;
+    font-weight: bold;
+    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
+  } 

+ 22 - 3
novel-app/src/app/character/character.page.ts

@@ -2,19 +2,38 @@ import { Component, OnInit } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
 import { IonContent, IonHeader, IonTitle, IonToolbar } from '@ionic/angular/standalone';
+import { IonicModule } from '@ionic/angular';
+import { Router } from '@angular/router';
+import { CharacterService } from '../services/character.service';
+import type { Character } from '../services/character.service';
+
 
 @Component({
   selector: 'app-character',
   templateUrl: './character.page.html',
   styleUrls: ['./character.page.scss'],
   standalone: true,
-  imports: [IonContent, IonHeader, IonTitle, IonToolbar, CommonModule, FormsModule]
+  imports: [CommonModule, IonicModule]
 })
 export class CharacterPage implements OnInit {
+  characters: Character[] = [];
 
-  constructor() { }
+  constructor(
+    private router: Router,
+    private characterService: CharacterService
+  ) {}
 
   ngOnInit() {
+    this.loadCharacters();
+  }
+
+  loadCharacters() {
+    this.characterService.characters$.subscribe(chars => {
+      this.characters = chars;
+    });
   }
 
-}
+  createNewCharacter() {
+    this.router.navigate(['/character-creator']);
+  }
+} 

+ 30 - 0
novel-app/src/app/services/character.service.ts

@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Observable, of } from 'rxjs';
+
+export interface Character {
+  id: string;
+  name: string;
+  gender: string;
+  appearance: string;
+  personality: string;
+  avatar: string;
+}
+
+@Injectable({
+  providedIn: 'root'
+})
+export class CharacterService {
+  private characters = new BehaviorSubject<Character[]>([]);
+  characters$ = this.characters.asObservable();
+
+  generateCharacterAvatar(description: string): Observable<string> {
+    // TODO: 实现AI生成头像的逻辑
+    return of('assets/default-avatar.png');
+  }
+
+  createCharacterAgent(character: Character): Observable<Character> {
+    const currentCharacters = this.characters.value;
+    this.characters.next([...currentCharacters, character]);
+    return of(character);
+  }
+} 

+ 12 - 6
novel-app/src/app/tabs/tabs.routes.ts

@@ -11,17 +11,23 @@ export const routes: Routes = [
         loadComponent: () =>
           import('../home/home.page').then((m) => m.HomePage),
       },
-      {
-        path: 'character',
-        loadComponent: () =>
-          import('../character/character.page').then((m) => m.CharacterPage),
-      },
       {
         path: 'person',
         loadComponent: () =>
           import('../person/person.page').then((m) => m.PersonPage),
       },
-
+      {
+        path: 'character',
+        loadComponent: () => import('../character/character.page').then( m => m.CharacterPage)
+      },
+      {
+        path: 'story-generator',
+        loadComponent: () => import('../story-generator/story-generator.page').then(m => m.StoryGeneratorPage)
+      },
+      {
+        path: 'toolbox',
+        loadComponent: () => import('../toolbox/toolbox.page').then(m => m.ToolboxPage)
+      },
       {
         path: '',
         redirectTo: '/tabs/home',