Преглед на файлове

feat: add & implement task-chain page

cyx преди 5 месеца
родител
ревизия
7c27a7879a

+ 67 - 0
TFPower-app/src/app/agent/agent.task.ts

@@ -0,0 +1,67 @@
+interface AgentTaskStepOptions {
+  title: string;
+  shareData?: any;
+  handle?(): { (): Promise<any> };
+}
+
+export class AgentTaskStep {
+  // 任务标题
+  title: string = '';
+  // 共享数据
+  shareData: any = {};
+  // 私有数据
+  data: any = {};
+
+  // 父级组件
+  parentComp: any | undefined;
+  parentIndex: number | undefined;
+
+  /**
+   * 任务生命周期
+   * constructor()  // 构造时执行一次
+   * onInit()  // 初始化后执行一次
+   * onProgress() // 进度变化时执行一次
+   * onComplete() // 完成前执行一次
+   */
+
+  constructor(metaData: AgentTaskStepOptions) {
+    this.title = metaData.title;
+    this.shareData = metaData?.shareData;
+    if (metaData.handle) {
+      this.handle = metaData.handle;
+    }
+    this.init(metaData); // 处理异步函数
+  }
+  onInit(step: AgentTaskStep) {
+    this.isInit = true;
+  }
+  beforeHandle(step: AgentTaskStep) {}
+  afterhandle(step: AgentTaskStep) {}
+  onProgress(step: AgentTaskStep) {}
+  onComplete(step: AgentTaskStep) {}
+  onError(step: AgentTaskStep) {}
+
+  /**
+   * 任务初始化函数
+   * 因为构造器里不能执行异步函数,而metaData里传进来的数据中可能有需要异步处理的函数
+   */
+  isInit: boolean = false;
+  async init(metaData: AgentTaskStepOptions) {}
+  /**
+   * 执行任务
+   * @desc 函数内必须有明确的完成、结束情形和函数进度变化指示
+   */
+  progress: number = 0;
+  handle(): Promise<any> | any {
+    this.beforeHandle(this);
+
+    this.onComplete(this);
+    this.onError(this);
+    return true;
+  }
+
+  /**
+   * 函数报错
+   */
+  error: string = ''; // 报错原因
+}

+ 3 - 2
TFPower-app/src/app/page/aipicture-page/aipicture-page.component.html

@@ -16,12 +16,13 @@
     <ion-list>
       <ion-item>
         <!-- 生成提示词 -->
-        <ion-textarea [value]="needs" (ionInput)="promptInput($event)" placeholder="DALLE3图片提示词"
+        <ion-textarea [value]="needs" (ionInput)="promptInput($event)" placeholder="输入你的所思所想,我来给你生成图片。"
           autoGrow="true"></ion-textarea>
       </ion-item>
       <ion-grid [fixed]="true">
         <ion-row style="text-align: center;">
-          <ion-button (click)="createImage()" expand="block">生成图片 {{imagineWork?.progress || 0}}</ion-button>
+          <ion-button (click)="createImage()" expand="block">生成图片 {{ imagineWork?.progress || 0
+            }}</ion-button>
         </ion-row>
       </ion-grid>
     </ion-list>

+ 28 - 0
TFPower-app/src/app/page/taskchain-page/taskchain-page.component.html

@@ -0,0 +1,28 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-title>TaskChain</ion-title>
+  </ion-toolbar>
+</ion-header>
+<ion-content [fullscreen]="true">
+  <ion-button (click)="createTask()">运行</ion-button>
+
+  @for(task of taskList; track task.title){
+  <ion-card>
+    <ion-card-content>
+      @if(task.progress === 0) {
+      <div class="loader"></div>
+      <!-- <ion-icon name="ellipse-outline"></ion-icon> -->
+      }
+      @if(task.progress !==0 && task.progress !== 1){
+      <div class="loader"></div>
+      <!-- <ion-icon name="reload-circle-outline"></ion-icon> -->
+      }
+      @if(task.progress === 1) {
+      <ion-icon name="checkmark-circle-outline" style="color:green"></ion-icon>
+      }
+      <span style="margin-left: 10px;">{{task.title}}</span>
+    </ion-card-content>
+  </ion-card>
+  }
+
+</ion-content>

+ 20 - 0
TFPower-app/src/app/page/taskchain-page/taskchain-page.component.scss

@@ -0,0 +1,20 @@
+/* HTML: <div class="loader"></div> */
+.loader {
+  width: 16px;
+  display: inline-block;
+  aspect-ratio: 1.154;
+  --_g: no-repeat radial-gradient(farthest-side, #000 90%, #0000);
+  background: var(--_g) 50% 0, var(--_g) 0 100%, var(--_g) 100% 100%;
+  background-size: 35% calc(35% * 1.154);
+  animation: l16 1s infinite;
+}
+@keyframes l16 {
+  50%,
+  100% {
+    background-position: 100% 100%, 50% 0, 0 100%;
+  }
+}
+
+ion-icon {
+  width: 16px;
+}

+ 24 - 0
TFPower-app/src/app/page/taskchain-page/taskchain-page.component.spec.ts

@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { IonicModule } from '@ionic/angular';
+
+import { TaskchainPageComponent } from './taskchain-page.component';
+
+describe('TaskchainPageComponent', () => {
+  let component: TaskchainPageComponent;
+  let fixture: ComponentFixture<TaskchainPageComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      declarations: [ TaskchainPageComponent ],
+      imports: [IonicModule.forRoot()]
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(TaskchainPageComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 92 - 0
TFPower-app/src/app/page/taskchain-page/taskchain-page.component.ts

@@ -0,0 +1,92 @@
+import { Component } from '@angular/core';
+import {
+  IonButton,
+  IonCard,
+  IonCardContent,
+  IonContent,
+  IonHeader,
+  IonIcon,
+  IonItem,
+  IonProgressBar,
+  IonTitle,
+  IonToolbar,
+} from '@ionic/angular/standalone';
+import { AgentTaskStep } from 'src/app/agent/agent.task';
+import { addIcons } from 'ionicons';
+import {
+  checkmarkCircleOutline,
+  ellipseOutline,
+  reloadCircleOutline,
+} from 'ionicons/icons';
+addIcons({ ellipseOutline, checkmarkCircleOutline, reloadCircleOutline });
+
+@Component({
+  selector: 'app-taskchain-page',
+  templateUrl: './taskchain-page.component.html',
+  styleUrls: ['./taskchain-page.component.scss'],
+  standalone: true,
+  imports: [
+    IonButton,
+    IonHeader,
+    IonToolbar,
+    IonTitle,
+    IonContent,
+    IonItem,
+    IonCard,
+    IonCardContent,
+    IonProgressBar,
+    IonIcon,
+  ],
+})
+export class TaskchainPageComponent {
+  constructor() {}
+
+  taskList: AgentTaskStep[] = [];
+  wait(duration: number = 1000) {
+    return new Promise((resolve, reject) => {
+      setInterval(() => {
+        resolve(true);
+      }, duration);
+    });
+  }
+  shareData: any = {};
+  createTask() {
+    let task1 = new AgentTaskStep({
+      title: 'AI扩展更多信息',
+      shareData: this.shareData,
+    });
+    task1.handle = async () => {
+      await this.wait(5000);
+      console.log('AI扩展更多信息,执行中...');
+      task1.progress = 1;
+    };
+
+    let task2 = new AgentTaskStep({
+      title: 'AI生成图片',
+      shareData: this.shareData,
+    });
+    task2.handle = async () => {
+      await this.wait(3000);
+      console.log('AI生成图片,执行中...');
+      task2.progress = 1;
+    };
+
+    this.taskList = [task1, task2];
+    this.AngentExecutor(this.taskList);
+  }
+
+  /**
+   * 任务执行函数
+   */
+  async AngentExecutor(taskStepList: AgentTaskStep[]) {
+    for (let index = 0; index < taskStepList.length; index++) {
+      let step = taskStepList[index];
+      let result = await step.handle();
+      if (result == false) {
+        break;
+      }
+      if (!step.error) {
+      }
+    }
+  }
+}

+ 3 - 0
TFPower-app/src/app/tab1/tab1.page.html

@@ -19,6 +19,9 @@
           <ion-item>
             <ion-label><a (click)="navigateTo('aipicture')">AIpicture</a></ion-label>
           </ion-item>
+          <ion-item>
+            <ion-label><a (click)="navigateTo('taskchain')">TaskChain for AIpicture</a></ion-label>
+          </ion-item>
         </ion-list>
         <!-- <ion-button>Go to TodolistPage </ion-button> -->
 

+ 7 - 0
TFPower-app/src/app/tabs/tabs.routes.ts

@@ -47,6 +47,13 @@ export const routes: Routes = [
             (m) => m.AipicturePageComponent
           ),
       },
+      {
+        path: 'taskchain',
+        loadComponent: () =>
+          import('../page/taskchain-page/taskchain-page.component').then(
+            (m) => m.TaskchainPageComponent
+          ),
+      },
       {
         path: '',
         redirectTo: '/tabs/tab1',