Bläddra i källkod

feat: poem picture generation

haitao 4 månader sedan
förälder
incheckning
4faafa0163

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 641 - 14
package-lock.json


+ 1 - 0
package.json

@@ -27,6 +27,7 @@
     "@capacitor/keyboard": "6.0.3",
     "@capacitor/status-bar": "6.0.2",
     "@ionic/angular": "^8.0.0",
+    "fmode-ng": "^0.0.62",
     "ionicons": "^7.2.1",
     "rxjs": "~7.8.0",
     "tslib": "^2.3.0",

+ 33 - 0
src/app/poem-picture/poem-picture.component.html

@@ -0,0 +1,33 @@
+<ion-header [translucent]="true">
+  <ion-toolbar>
+    <ion-title>
+      示例:古诗文意境生成{{imagineWork?.progress || 0}}
+    </ion-title> 
+  </ion-toolbar>
+</ion-header>
+
+<ion-content [fullscreen]="true">
+  <!-- 生成提示词 -->
+  <ion-textarea [value]="userPrompt" (ionInput)="promptInput($event)" placeholder="古诗文填写" autoGrow="true"></ion-textarea>
+  <ion-button (click)="createImage()" expand="block">生成意境</ion-button>
+  <!-- 意境画面提示词 -->
+  <div>
+    {{PictureDescResult}}
+  </div>
+  <!-- 生成结果 -->
+  @if(images.length) {
+    @for(imageUrl of images;track imageUrl){
+      <img [src]="imageUrl" alt="" srcset="">
+    }
+  }
+  <!-- 生成状态 -->
+  @if(!images.length){
+    @if(imagineWork){
+      <h1>生成中</h1>
+    }
+    @if(!imagineWork){
+      <h1>未开始</h1>
+    }
+  }
+
+</ion-content>

+ 0 - 0
src/app/poem-picture/poem-picture.component.scss


+ 22 - 0
src/app/poem-picture/poem-picture.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { PoemPictureComponent } from './poem-picture.component';
+
+describe('PoemPictureComponent', () => {
+  let component: PoemPictureComponent;
+  let fixture: ComponentFixture<PoemPictureComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [PoemPictureComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(PoemPictureComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 69 - 0
src/app/poem-picture/poem-picture.component.ts

@@ -0,0 +1,69 @@
+import { Component, OnInit } from '@angular/core';
+import { IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/angular/standalone';
+import { IonTextarea, IonButton,IonInput } from "@ionic/angular/standalone";
+import { DalleOptions, ImagineWork, FmodeChatCompletion } from 'fmode-ng';
+
+@Component({
+  selector: 'app-poem-picture',
+  templateUrl: './poem-picture.component.html',
+  styleUrls: ['./poem-picture.component.scss'],
+  standalone: true,
+  imports: [
+    IonHeader, IonToolbar, IonTitle, IonContent, 
+    IonButton,
+    IonInput,
+    IonTextarea
+  ],
+})
+export class PoemPictureComponent  implements OnInit {
+  userPrompt:string = "犬吠水声中,桃花带露浓。\n树深时见鹿,溪午不闻钟。"
+  promptInput(ev:any){
+    this.userPrompt = ev.detail.value;
+  }
+  imagineWork:ImagineWork|undefined
+  images:Array<string> = []
+  constructor(
+  ){
+    // 示例任务,自己生成图片后请存储新的ID
+    this.imagineWork = new ImagineWork("lpJGiFwWeA");
+    this.imagineWork.fetchTask().then(work=>{
+      this.images = this.imagineWork?.images || [];
+    })
+  }
+
+  PictureDescResult:string = `` // 画面描述结果
+  async createImage(){
+    this.imagineWork = new ImagineWork();
+    // 文本生成
+    let PromptTemplate = `您是一名专业的美术画家,请您根据古诗文的内容,将其描述的画面、场景、人物、物品等用最简短的语言表达,直接写出画面,并且以中国的古风意境为主
+    诗文如下:
+    ${this.userPrompt}
+    `
+    let completion = new FmodeChatCompletion([
+      {role:"system",content:""},
+      {role:"user",content:PromptTemplate}
+    ])
+    completion.sendCompletion().subscribe((message:any)=>{
+      // 打印消息体
+      console.log(message.content)
+      // 赋值消息内容给组件内属性
+      this.PictureDescResult = message.content
+      if(message?.complete){ // 判断message为完成状态,则设置isComplete为完成
+        // 图片生成
+        let PicturePrompt = `${this.PictureDescResult}\n风格:中国古风。画面不带任何文字。突出色彩。`
+      let options:DalleOptions = {prompt:PicturePrompt}
+      this.imagineWork?.draw(options).subscribe(work=>{
+          console.log("imagineWork",work?.toJSON())
+          console.log("images",work?.get("images"))
+          if(work?.get("images")?.length){
+            this.images = work?.get("images");
+          }
+      })
+      }
+    })
+
+    
+  }
+  ngOnInit() {}
+
+}

+ 1 - 1
src/app/tab1/tab1.page.html

@@ -18,6 +18,6 @@
 我的学习记录
 </ion-button>
 
-<ion-button (click)="goTestPage()">进入测试页面</ion-button>
+<ion-button (click)="goPicture()">诗文意境绘画</ion-button>
 <ion-button (click)="goanalysePage()">进入测试页面</ion-button>
 </ion-content>

+ 7 - 7
src/app/tab1/tab1.page.ts

@@ -11,17 +11,17 @@ import { Router } from '@angular/router';
   imports: [IonIcon,IonButton,  IonHeader, IonToolbar, IonTitle, IonContent],
 })
 export class Tab1Page {
+  constructor(private router:Router) {}
 
   toRecordLearn(){
     alert("记录学习情况,双击666")
   }
-      constructor(private router:Router) {}
-      goTestPage() {
-        this.router.navigate(['/tabs/test']);
-      }
-      goanalysePage(){
-        this.router.navigate(['/tabs/poem/analyse']);
-      }
+  goPicture() {
+    this.router.navigate(['/tabs/poem/picture']);
+  }
+  goanalysePage(){
+    // this.router.navigate(['/tabs/poem/analyse']);
+  }
 
       
 }

+ 7 - 2
src/app/tabs/tabs.routes.ts

@@ -26,10 +26,15 @@ export const routes: Routes = [
         loadComponent: () =>
           import('../page-test/page-test.component').then((m) => m.PageTestComponent),
       },
+      // {
+      //   path: '/poem/analyse',
+      //   loadComponent: () =>
+      //     import('../poem-analyse/poem-analyse.component').then((m) => m.PoemAnalyseComponent),
+      // },
       {
-        path: '/poem/analyse',
+        path: 'poem/picture',
         loadComponent: () =>
-          import('../poem-analyse/poem-analyse.component').then((m) => m.PoemAnalyseComponent),
+          import('../poem-picture/poem-picture.component').then((m) => m.PoemPictureComponent),
       },
       {
         path: '',

+ 17 - 0
src/main.ts

@@ -5,10 +5,27 @@ import { IonicRouteStrategy, provideIonicAngular } from '@ionic/angular/standalo
 import { routes } from './app/app.routes';
 import { AppComponent } from './app/app.component';
 
+// 引用HttpClient方法
+import { provideHttpClient } from '@angular/common/http';
+// 引用移动端授权检测供应器
+import { Diagnostic } from '@awesome-cordova-plugins/diagnostic/ngx';
+// 设置Parse服务属性
+import Parse from "parse";
+Parse.initialize("ncloudmaster");
+Parse.serverURL = "https://server.fmode.cn/parse";
+localStorage.setItem("NOVA_APIG_SERVER", 'aHR0cHMlM0ElMkYlMkZzZXJ2ZXIuZm1vZGUuY24lMkZhcGklMkZhcGlnJTJG')
+
+// 注意:替换Token 根据Token设置Parse服务帐套权限
+Parse.User.become("r:24e50e03574b50d118ac59446300ef78")
+
 bootstrapApplication(AppComponent, {
   providers: [
     { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
     provideIonicAngular(),
     provideRouter(routes, withPreloading(PreloadAllModules)),
+     // 添加HttpClient供应器
+     provideHttpClient(),
+     // 添加Diagnostic
+     Diagnostic,
   ],
 });

+ 1 - 0
tsconfig.json

@@ -4,6 +4,7 @@
   "compilerOptions": {
     "baseUrl": "./",
     "outDir": "./dist/out-tsc",
+    "allowSyntheticDefaultImports":true,
     "forceConsistentCasingInFileNames": true,
     "strict": true,
     "noImplicitOverride": true,

Vissa filer visades inte eftersom för många filer har ändrats