Kaynağa Gözat

完成我的风格存储功能

s202226701053 5 ay önce
ebeveyn
işleme
9be005082b

+ 5 - 0
E-Cover-app/src/app/app.routes.ts

@@ -66,4 +66,9 @@ export const routes: Routes = [
     loadComponent:()=>
       import('./attention/attention.component').then((m)=>m.AttentionComponent),
   },
+  {
+    path:'myStyleList',
+    loadComponent:()=>
+      import('./my-style-list/my-style-list.component').then((m)=>m.MyStyleListComponent),
+  },
 ];

+ 6 - 4
E-Cover-app/src/app/generate-option/generate-option.component.html

@@ -108,14 +108,16 @@
       <p class="title"> 请选择艺术风格 </p>
       }
     </div>
-
-
   </div>
 
-  <ion-button (click)="sendMsgAndGoGenerateResult()">生成</ion-button>
-  <ion-button>导入默认风格</ion-button>
+  <ion-button id="generate" *ngIf="!isCreateMode && !isEditMode" (click)="sendMsgAndGoGenerateResult()">生成</ion-button>
+  <ion-button id="import" *ngIf="!isCreateMode && !isEditMode"></ion-button>
+  <ion-button shape="round" id="save" *ngIf="isCreateMode" (click)="saveStyle()">保存风格</ion-button>
+  <ion-button shape="round" id="save" *ngIf="isEditMode" (click)="saveStyle()">保存风格</ion-button>
 </ion-content>
 
+
+
 <!--处理动画,默认隐藏-->
 <div id="container">
   <div id="popover-container">

+ 25 - 0
E-Cover-app/src/app/generate-option/generate-option.component.scss

@@ -243,4 +243,29 @@ ion-content {
   font-size: larger;
   text-align: center;
   margin: 5px;
+}
+
+#generate{
+  --background:url(https://s1.imagehub.cc/images/2025/01/12/3db5f609801c3424b76a6f7aa627679c.png) no-repeat center center / contain;
+  height: 15%;
+  --box-shadow: none;
+  width: 40%;
+  margin: 0 5%;
+}
+#import{
+  --background:url(https://s1.imagehub.cc/images/2025/01/12/190f2ffaf12541d0b391589da0f7f897.png) no-repeat center center / contain;
+  height: 15%;
+  --box-shadow: none;
+  width: 40%;
+  margin: 0 5%;
+}
+#save{
+  --background: url(https://s1.imagehub.cc/images/2025/01/11/d21ac75a8836b47796ac3b9efa0779da.png) no-repeat center center / cover;
+  height: 15vw;
+  width: 50%;
+  margin: 10px 25%;
+  color: black;
+  font-size: 25px;
+  font-family: 'mainButton';
+  font-weight: bold;
 }

+ 117 - 11
E-Cover-app/src/app/generate-option/generate-option.component.ts

@@ -10,9 +10,9 @@ import { TaskGenerateUserValiate } from 'src/agent/tasks/generate/generate-user-
 import { TaskExecutor } from 'src/agent/agent.start';
 import { TaskGeneratePrompt } from 'src/agent/tasks/generate/generate-prompt';
 import { TaskGeneratePicture } from 'src/agent/tasks/generate/generate-picture';
-import { CloudQuery, CloudUser } from 'src/lib/ncloud';
+import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
 import { CustomHeaderComponent } from 'src/lib/component/custom-header/custom-header.component';
-import { IonButton, IonCard, IonContent, IonIcon, IonImg, IonText, IonTextarea } from '@ionic/angular/standalone';
+import { AlertController, AlertInput, IonAlert, IonButton, IonCard, IonContent, IonIcon, IonImg, IonText, IonTextarea } from '@ionic/angular/standalone';
 addIcons({ 'arrow-back-outline': arrowBackOutline, radioButtonOffOutline, closeCircleOutline, checkmarkCircleOutline, reloadOutline });
 @Component({
   selector: 'app-generate-option',
@@ -20,7 +20,7 @@ addIcons({ 'arrow-back-outline': arrowBackOutline, radioButtonOffOutline, closeC
   styleUrls: ['./generate-option.component.scss'],
   standalone: true,
   imports: [CustomHeaderComponent, CommonModule, FormsModule, IonButton, IonCard, IonIcon,
-    IonImg, IonText, IonTextarea, IonContent
+    IonImg, IonText, IonTextarea, IonContent, IonAlert
   ],
   providers: [ModalController],
 })
@@ -29,9 +29,14 @@ export class GenerateOptionComponent implements OnInit {
    * @构造和初始化
    */
   //构造器
-  constructor(private modalCtrl: ModalController, private router: Router, private navCtrl: NavController) { }
+  constructor(private alertController: AlertController, private modalCtrl: ModalController, private router: Router, private navCtrl: NavController) { }
   //初始化
-  ngOnInit() { }
+  isCreateMode: boolean = false;
+  isEditMode: boolean = false;
+  ngOnInit() {
+    //接受来自创建风格的路由参数
+    this.handleStyleList();
+  }
   /**
    * @返回按钮事件
    */
@@ -162,11 +167,6 @@ export class GenerateOptionComponent implements OnInit {
     '维多利亚风': false,
     '未来主义': false,
   }
-  //颜色选项卡定义变量
-  color: { [key: string]: boolean } = {
-    '多巴胺穿搭': false,
-    '美拉德穿搭': false
-  };
 
   /**
    * @根据索引找到键值
@@ -175,6 +175,13 @@ export class GenerateOptionComponent implements OnInit {
     const keys = Object.keys(option); // 获取 option 对象中的所有键
     return keys[index]; // 根据索引找到选中的键
   }
+  /**
+   * @根据键值找到索引
+   */
+  getIndexByKey(option: { [key: string]: boolean }, key: string): number {
+    const keys = Object.keys(option); // 获取 option 对象中的所有键
+    return keys.indexOf(key); // 根据键找到索引
+  }
   /**
    * @返回字典中true值对应的key
    */
@@ -201,7 +208,10 @@ export class GenerateOptionComponent implements OnInit {
       // 将选中的键对应的值设置为 true
       option[selectedKey] = true;
       // 更新 userProfile 中的对应字段
-      this.userProfile[name as keyof UserProfile] = selectedKey + ":" + this.description[selectedKey];
+      if (['gender', 'age', 'height', 'weight', 'season'].includes(name))
+        this.userProfile[name as keyof UserProfile] = selectedKey;
+      else
+        this.userProfile[name as keyof UserProfile] = selectedKey + ":" + this.description[selectedKey];
     } else {
       option[selectedKey] = false;
       this.userProfile[name as keyof UserProfile] = '不限制';
@@ -348,6 +358,102 @@ export class GenerateOptionComponent implements OnInit {
     }
     return true;
   }
+  /**
+   * @保存风格信息
+   */
+  //打开保存风格信息的弹窗
+  async saveStyle() {
+    //判断五个字段是否为"不限制"
+    if (this.userProfile.gender === "不限制" || this.userProfile.age === "不限制" || this.userProfile.height === "不限制" || this.userProfile.weight === "不限制" || this.userProfile.season === "不限制") {
+      console.log("信息未完善,不保存风格信息");
+      return;
+    }
+    const alert = await this.alertController.create({
+      header: '请完善风格信息',
+      inputs: this.alertInputs,
+      buttons: [
+        {
+          text: '取消',
+          role: 'cancel',
+          cssClass: 'secondary',
+        },
+        {
+          text: '确认',
+          handler: (data) => {
+            console.log('输入的数据:', data); // 处理用户输入
+            this.handleAlertInput(data); // 调用处理函数
+          },
+        },
+      ],
+    });
+    await alert.present();
+  }
+  //完善风格信息
+  public alertInputs: AlertInput[] = [
+    {
+      name: 'styleName',
+      placeholder: '风格名称',
+    },
+    {
+      name: 'styleDesc',
+      type: 'textarea',
+      placeholder: '自定义描述',
+    },
+  ];
+  //处理风格信息
+  handleAlertInput(data: any) {
+    let object = new CloudObject("UserStyleInfo");
+    const user = new CloudUser().toPointer();
+    let content = JSON.stringify(this.userProfile);
+    object.set({
+      "UserID": user,
+      "name": data.styleName,
+      "desc": data.styleDesc,
+      "content": content,
+    });
+    if(this.isEditMode){
+      object.id = this.editId;
+    }
+    object.save();
+    this.goBack();
+  }
+  /**
+   * @风格列表跳转处理
+   */
+  editId: string|any = "";
+  handleStyleList() {
+    const navigation = this.router.getCurrentNavigation();
+    if (navigation?.extras.state) {
+      this.isCreateMode = navigation.extras.state?.['fromMyStyleListPage'] || false;
+      console.log('创建模式开启:', this.isCreateMode);
+      this.isEditMode = navigation.extras.state?.['fromMyStyleInfoPage'] || false;
+      console.log('编辑模式开启:', this.isEditMode);
+      if (this.isEditMode) {
+        const style: CloudObject = navigation.extras.state?.['style'];
+        const json = JSON.parse(style?.get('content'));
+        this.userProfile = json;
+        console.log('已获取userStyle信息,存储至userProfile', this.userProfile);
+        this.editId = style?.id;
+        //根据json数据模拟用户填充表单
+        this.gender[json.gender]=true;
+        this.age[json.age]=true;
+        this.height[json.height]=true;
+        this.weight[json.weight]=true;
+        this.season[json.season]=true;
+        //json对应字段取“:”前面的所有字符
+        json.areaStyle=json.areaStyle?.split(":")[0];
+        json.function=json.function?.split(":")[0];
+        json.artStyle=json.artStyle?.split(":")[0];
+        json.designIdea=json.designIdea?.split(":")[0];
+        this.areaStyle[json.areaStyle]=true;
+        this.function[json.function]=true;
+        this.artStyle[json.artStyle]=true;
+        this.designIdea[json.designIdea]=true;
+        this.alertInputs[0].value = style?.get('name');
+        this.alertInputs[1].value = style?.get('desc');
+      }
+    }
+  }
 }
 /**
  * @用户信息结构

+ 15 - 0
E-Cover-app/src/app/my-style-list/my-style-list.component.html

@@ -0,0 +1,15 @@
+<app-custom-header [param]="['我的风格','    ']"></app-custom-header>
+<ion-content>
+  <ion-card *ngFor="let style of styleList" (click)="goStyleDetail(style)">
+    <div id="img">
+      <img [src]="style?.get('image') ? style?.get('image') : '/assets/icon/favicon.png'">
+    </div>
+    <div id="content">
+      <h1>{{style?.get('name')}}</h1>
+      <h2>创建时间:{{convertTime(style?.createdAt)}}</h2>
+      <h3>更新时间:{{convertTime(style?.updatedAt)}}</h3>
+      <h4>{{style?.get('desc')}}</h4>
+    </div>
+  </ion-card>
+  <ion-button shape="round" (click)="goCreateStyle()">新建风格</ion-button>
+</ion-content>

+ 68 - 0
E-Cover-app/src/app/my-style-list/my-style-list.component.scss

@@ -0,0 +1,68 @@
+@font-face {
+    font-family: 'mainButton';
+    src: url(/assets/fonts/mainButton.TTC);
+}
+ion-content{
+    --background: #f8f8f8;
+
+    ion-card{
+        --background: #ffffff;
+        box-shadow: 1px 1px 10px rgba(0,0,0,0.1);
+        border-radius: 10px;
+        width: 90%;
+        margin: 10px 5%;
+
+        #img{
+            padding: 15px;
+            width: 40%;
+            float: left;
+            img{
+                width: 100%;
+                height: 100%;
+                border-radius: 10px;
+            }
+        }
+        #content{
+            padding:15px;
+            width: 60%;
+            float: right;
+            h1{
+                color: black;
+                font-size: 20px;
+                margin:0 0 5px 0;
+                font-family: 'mainButton';
+            }
+            h2{
+                color:gray;
+                font-size: 15px;
+                margin:0 0 0 0;
+            }
+            h3{
+                color:gray;
+                font-size: 15px;
+                margin:0 0 10px 0;
+            }
+            h4{
+                color:rgb(93, 93, 93);
+                font-size: 17px;
+                margin:0;
+                display: -webkit-box;
+                -webkit-box-orient: vertical;
+                -webkit-line-clamp: 2; /* 限制最大行数为2 */
+                overflow: hidden;
+                text-overflow: ellipsis; /* 显示省略号 */
+                line-clamp: 2; /* 为支持该属性的浏览器提供 */
+            }
+        }
+    }
+    ion-button{
+        --background: url(https://s1.imagehub.cc/images/2025/01/11/d21ac75a8836b47796ac3b9efa0779da.png) no-repeat center center / cover;
+        height: 15vw;
+        width: 50%;
+        margin: 10px 25%;
+        color: black;
+        font-size: 25px;
+        font-family: 'mainButton';
+        font-weight: bold;
+    }
+}

+ 22 - 0
E-Cover-app/src/app/my-style-list/my-style-list.component.spec.ts

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

+ 49 - 0
E-Cover-app/src/app/my-style-list/my-style-list.component.ts

@@ -0,0 +1,49 @@
+import { CommonModule } from '@angular/common';
+import { Component, OnInit } from '@angular/core';
+import { IonButton, IonCard, IonContent, NavController } from '@ionic/angular/standalone';
+import { CustomHeaderComponent } from 'src/lib/component/custom-header/custom-header.component';
+import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
+
+@Component({
+  selector: 'app-my-style-list',
+  templateUrl: './my-style-list.component.html',
+  styleUrls: ['./my-style-list.component.scss'],
+  standalone: true,
+  imports: [CustomHeaderComponent, IonContent, IonCard, IonButton, CommonModule]
+})
+export class MyStyleListComponent implements OnInit {
+  constructor(private navCtrl: NavController) { }
+  ngOnInit() {
+    this.getStyleList();
+  }
+  /**
+   * @页面跳转函数
+   */
+  goCreateStyle() {
+    this.navCtrl.navigateForward('/generateOption', { state: { fromMyStyleListPage: true } });
+  }
+  goStyleDetail(style: CloudObject) {
+    this.navCtrl.navigateForward('/generateOption', { state: { fromMyStyleInfoPage: true, style } });
+  }
+  /**
+   * @读取风格列表
+   */
+  styleList: CloudObject[] = [];
+  async getStyleList() {
+    let query = new CloudQuery("UserStyleInfo");
+    const user = new CloudUser().toPointer();
+    query.equalTo("UserID", user);
+    let result = await query.find();
+    result = result.reverse();
+    this.styleList = result;
+    console.log(this.styleList);
+  }
+  /**
+   * @内置功能函数
+   */
+  /*转换时间;格式例:2024-01-01 02:08*/
+  convertTime(time: string): string {
+    let date = new Date(time);
+    return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
+  }
+}

+ 6 - 6
E-Cover-app/src/app/tab3/tab3.page.html

@@ -31,11 +31,11 @@
       <!--统计-->
       <div id="count">
         <div (click)="goAttention(false)">
-          <h3 style="display: inline;">{{ fanList.length}}</h3>
+          <h3 style="display: inline;">{{ fanNumber}}</h3>
           <p style="display: inline;">粉丝</p>
         </div>
         <div (click)="goAttention(true)">
-          <h3 style="display: inline;">{{ attentionList.length }}</h3>
+          <h3 style="display: inline;">{{ attentionNumber }}</h3>
           <p style="display: inline;">关注</p>
         </div>
         <h3 style="display: inline;">{{ formatNumber(currentUser?.get('like')) }}</h3>
@@ -58,11 +58,11 @@
       <img class="img-shade" />
       <p>赞过帖子<br />{{likedPostsNumber}}</p>
     </div>
-    <div class="card">
+    <div class="card" (click)="goMyStyleList()">
       <img class="img-background"
-        [src]="(likedPostsImage!='') ? (likedPostsImage) : ('/assets/icon/favicon.png')">
-      <img class="img-shade" />
-      <p>我的风格<br />{{likedPostsNumber}}</p>
+        [src]="(myStyleImage!='') ? (myStyleImage) : ('/assets/icon/favicon.png')">
+      <img class="img-shade"/>
+      <p>我的风格<br />{{myStyleNumber}}</p>
     </div>
     <div class="card">
       <img class="img-background"

+ 36 - 18
E-Cover-app/src/app/tab3/tab3.page.ts

@@ -19,12 +19,13 @@ addIcons({ personAddOutline, cardOutline, flameOutline, chevronForwardOutline })
 export class Tab3Page {
   currentUser: CloudUser | undefined;
   constructor(private modalCtrl: ModalController, private router: Router) { }
-  async ngOnInit() {
+  ngOnInit() {
     this.currentUser = new CloudUser();
-    await this.loadAttentionList();
-    await this.loadFanList();
-    await this.loadPostList();
-    await this.getHistoryCount();
+    this.getAttentionList();
+    this.getFanList();
+    this.getPostList();
+    this.getHistoryCount();
+    this.getMyStyle();
   }
   async ionViewWillEnter() {
     console.warn("-------------------------\n" + "进入tab3界面,执行ionViewWillEnter\n" + "验证用户是否登录")
@@ -45,7 +46,7 @@ export class Tab3Page {
     }
     console.log("进入到我的界面,准备实例化currentUser对象");
     this.currentUser = new CloudUser();
-    this.getPosts();
+    this.loadPosts();
   }
   /**
    * @格式化为带单位的数字
@@ -74,11 +75,14 @@ export class Tab3Page {
   goAttention(isFollowing: boolean) {
     this.router.navigate(['/attention'], { state: { currentTab: isFollowing } }); // 传递状态
   }
+  goMyStyleList() {
+    this.router.navigate(['/myStyleList']);
+  }
   /**
    * @读取用户发布的帖子
    */
   posts: any[] | undefined;
-  async getPosts() {
+  async loadPosts() {
     let query = new CloudQuery('post');
     query.equalTo('UserID', this.currentUser?.toPointer());
     this.posts = await query.find();
@@ -89,21 +93,23 @@ export class Tab3Page {
   /**
    * @读取个人信息卡片数据
    */
-  /*加载关注列表*/
-  attentionList: CloudObject[] = [];
-  async loadAttentionList() {
+  /*加载关注个数*/
+  attentionNumber: number = 0;
+  async getAttentionList() {
     const query = new CloudQuery('attention');
     query.equalTo('UserID', this.currentUser?.toPointer());
-    this.attentionList = await query.find();
-    console.log(this.attentionList);
+    let result = await query.find();
+    this.attentionNumber = result.length;
+    console.log("获取到关注个数:" + this.attentionNumber);
   }
-  /*加载粉丝列表*/
-  fanList: CloudObject[] = [];
-  async loadFanList() {
+  /*加载粉丝个数*/
+  fanNumber: number = 0;
+  async getFanList() {
     const query = new CloudQuery('attention');
     query.equalTo('attentionID', this.currentUser?.toPointer());
-    this.fanList = await query.find();
-    //console.log(this.fanList);
+    let result = await query.find();
+    this.fanNumber = result.length;
+    console.log("获取到粉丝个数:" + this.fanNumber);
   }
   /**
    * @读取统计卡片数据
@@ -111,7 +117,7 @@ export class Tab3Page {
   /*加载点赞帖子列表*/
   likedPostsNumber: number = 0;
   likedPostsImage: string = "";
-  async loadPostList() {
+  async getPostList() {
     const query = new CloudQuery('postLikesRecord');
     query.equalTo('UserID', this.currentUser?.toPointer());
     query.include('postID');
@@ -133,6 +139,18 @@ export class Tab3Page {
     this.generateHistoryCount = result.length;
     console.log("获取到生成历史个数:" + this.generateHistoryCount + "\n" + "获取到生成历史图像:" + this.generateHistoryImage);
   }
+  /*返回我的风格个数和图像*/
+  myStyleNumber: number = 0;
+  myStyleImage: string = "";
+  async getMyStyle() {
+    let query = new CloudQuery('UserStyleInfo');
+    query.equalTo('UserID', this.currentUser?.toPointer());
+    let result = await query.find();
+    result = result.reverse();
+    this.myStyleImage = result[0]?.get('image') || "/assets/icon/favicon.png";
+    this.myStyleNumber = result.length;
+    console.log("获取到我的风格个数:" + this.myStyleNumber + "\n" + "获取到我的风格图像:" + this.myStyleImage);
+  }
 }