5230254 8 months ago
parent
commit
9f6298ca12

+ 2 - 1
package-lock.json

@@ -31,7 +31,7 @@
         "@angular-eslint/eslint-plugin-template": "^18.0.0",
         "@angular-eslint/schematics": "^18.0.0",
         "@angular-eslint/template-parser": "^18.0.0",
-        "@angular/cli": "^18.0.0",
+        "@angular/cli": "18.0.7",
         "@angular/compiler-cli": "^18.0.0",
         "@angular/language-service": "^18.0.0",
         "@ionic/angular-toolkit": "^11.0.1",
@@ -467,6 +467,7 @@
       "resolved": "https://registry.npmmirror.com/@angular/cli/-/cli-18.0.7.tgz",
       "integrity": "sha512-CHnpI6d6MpXFsx3750jN4IX3oeieIMKzUPVZUMvPgDbhGFfChHKdxdJStDjYsH47pORb2pMHULw0RJCAPvtB9A==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "@angular-devkit/architect": "0.1800.7",
         "@angular-devkit/core": "18.0.7",

+ 1 - 1
package.json

@@ -36,7 +36,7 @@
     "@angular-eslint/eslint-plugin-template": "^18.0.0",
     "@angular-eslint/schematics": "^18.0.0",
     "@angular-eslint/template-parser": "^18.0.0",
-    "@angular/cli": "^18.0.0",
+    "@angular/cli": "18.0.7",
     "@angular/compiler-cli": "^18.0.0",
     "@angular/language-service": "^18.0.0",
     "@ionic/angular-toolkit": "^11.0.1",

+ 17 - 0
src/app/agent-shige/agent-shige-routing.module.ts

@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { AgentShigePage } from './agent-shige.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: AgentShigePage
+  }
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule],
+})
+export class AgentShigePageRoutingModule {}

+ 20 - 0
src/app/agent-shige/agent-shige.module.ts

@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { IonicModule } from '@ionic/angular';
+
+import { AgentShigePageRoutingModule } from './agent-shige-routing.module';
+
+import { AgentShigePage } from './agent-shige.page';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    AgentShigePageRoutingModule
+  ],
+  declarations: [AgentShigePage]
+})
+export class AgentShigePageModule {}

+ 41 - 0
src/app/agent-shige/agent-shige.page.html

@@ -0,0 +1,41 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-title>
+      诗词创作
+    </ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <ion-item>
+    <ion-input placeholder="关键词" [(ngModel)]="shigeOptions.keywords"></ion-input>
+  </ion-item>
+  <ion-item>
+    <ion-input placeholder="创作灵感" [(ngModel)]="shigeOptions.content"></ion-input>
+  </ion-item>
+  <ion-item>
+    <ion-select label="诗歌格律" placeholder="格律" [(ngModel)]="shigeOptions.type">
+      <ion-select-option value="不限制">不限制</ion-select-option>
+      <ion-select-option value="七言绝句">七言绝句</ion-select-option>
+      <ion-select-option value="五言律诗">五言律诗</ion-select-option>
+      <ion-select-option value="藏头诗">藏头诗</ion-select-option>
+      <ion-select-option value="宋词">藏头诗</ion-select-option>
+    </ion-select>
+  </ion-item>
+  <ion-item>
+    <ion-select label="诗歌主题" placeholder="主题" [(ngModel)]="shigeOptions.theme">
+      <ion-select-option value="不限制">不限制</ion-select-option>
+      <ion-select-option [value]="item" *ngFor="let item of themeList">{{item}}</ion-select-option>
+    </ion-select>
+  </ion-item>
+  <ion-button expand="block" (click)="sendMessage()">发送</ion-button>
+
+  <ion-card *ngFor="let message of messageList">
+    <ion-card-header>
+      {{message?.role}}
+    </ion-card-header>
+    <ion-card-content>
+      {{ message?.content }}
+    </ion-card-content>
+  </ion-card>
+</ion-content>

+ 0 - 0
src/app/agent-shige/agent-shige.page.scss


+ 17 - 0
src/app/agent-shige/agent-shige.page.spec.ts

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

+ 91 - 0
src/app/agent-shige/agent-shige.page.ts

@@ -0,0 +1,91 @@
+import { Component, OnInit } from '@angular/core';
+// 引用FmodeChatCompletion类
+import { TestRxjsChatCompletion,TestRxjsChatMessage } from './class-rxjs-chat-completion';
+import Parse from "parse";
+@Component({
+  selector: 'app-agent-shige',
+  templateUrl: './agent-shige.page.html',
+  styleUrls: ['./agent-shige.page.scss'],
+})
+export class AgentShigePage implements OnInit {
+  messageList:Array<TestRxjsChatMessage> = []
+  shigeOptions:any ={
+    content:"",
+    type:"不限制",
+    theme:"不限制",
+  }
+  themeList = ['羁旅思乡诗','爱情闺怨诗','咏史怀古诗','咏物言志诗','送别怀人诗','边塞征战诗','山水田园诗']
+
+  constructor() { 
+  }
+
+  ngOnInit() {
+  }
+  sendMessage(){
+    /*
+4. 风格:选择风格,例如“豪放”或“婉约”。
+5. 情感:描述诗中应表达的情感,例如“喜悦”、“忧愁”、“思念”等。
+
+    */
+    let GuhiPromoptTemplate = `
+你是一位中国的古代诗人,擅长文言文,和现代词汇转古词语经验和技巧,并且精通各类主题、格律的诗词。请根据以下要求创作一首诗:
+1. 主题:${this.shigeOptions?.theme}。
+2. 格律:${this.shigeOptions?.type}。
+3. 关键词:${this.shigeOptions?.keywords}。
+4. 创意灵感:${this.shigeOptions?.content}。
+请根据以上要求创作一首古代诗词,并且格式要严格,有必要的情况下,可以牺牲一些关键词原意。
+
+请开始创作,并按照以下格式返回
+题目:
+内容:
+简介:
+    `
+    this.messageList.push({
+      role:"user",
+      content: GuhiPromoptTemplate
+    })
+    
+    // messageList在competion内部,已经赋予了完整的message
+    // 下方暴露出来的可订阅内容,主要是用于关键字过滤,或者其他开发逻辑的续写
+    let resultStr = ""
+    let testChatCompletion = new TestRxjsChatCompletion(this.messageList);
+    testChatCompletion.createCompletionByStream({model:"fmode-3.6-16k"}).subscribe({
+        next: ({ content, cumulativeContent, done }) => {
+          resultStr = cumulativeContent
+            console.log(`Content: ${content}`);
+            console.log(`Cumulative Content: ${cumulativeContent}`);
+            if (done) {
+                console.log('Stream completed');
+            }
+        },
+        error: err => console.error(err),
+        complete: () => {
+          // 诗歌创建完成:正则表达式,匹配诗歌json内容
+          console.log("原文",resultStr)
+                    
+          let pattern = /题目:\s*(.*?)\s*内容:\s*(.*?)\s*简介:\s*(.*)/;
+          let match = resultStr.match(pattern);
+
+          if (match) {
+            let gushi:any = {}
+              gushi.title = match[1];
+              gushi.content = match[2];
+              gushi.intro = match[3];
+              gushi.source = "AI创作";
+              console.log(`题目: ${gushi.title}`);
+              console.log(`内容: ${gushi.content}`);
+              console.log(`简介: ${gushi.intro}`);
+              console.log(gushi);
+              let Shige = Parse.Object.extend("Shige");
+              let sg = new Shige();
+              sg.set(gushi);
+              sg.save();
+          } else {
+              console.log("未能匹配到任何内容");
+          }
+        }
+    });
+
+  }
+
+}

+ 111 - 0
src/app/agent-shige/class-rxjs-chat-completion.ts

@@ -0,0 +1,111 @@
+import { Observable, from, of } from 'rxjs';
+import { switchMap, map, catchError, finalize } from 'rxjs/operators';
+
+export interface TestRxjsChatMessage {
+    role: string;
+    content: string;
+}
+
+export class TestRxjsChatCompletion {
+    messageList: Array<TestRxjsChatMessage>;
+
+    constructor(messageList: Array<TestRxjsChatMessage>) {
+        this.messageList = messageList;
+    }
+
+    createCompletionByStream(options?:{
+        model?:string
+    }): Observable<{ content: string, cumulativeContent: string, done: boolean }> {
+        const token = localStorage.getItem("token");
+        const bodyJson = {
+            "token": `Bearer ${token}`,
+            "messages": this.messageList,
+            "model": options?.model || "fmode-3.6-16k",
+            "temperature": 0.5,
+            "presence_penalty": 0,
+            "frequency_penalty": 0,
+            "top_p": 1,
+            "stream": true
+        };
+
+        return from(fetch("https://test.fmode.cn/api/apig/aigc/gpt/v1/chat/completions", {
+            "headers": {
+                "accept": "text/event-stream",
+                "sec-fetch-dest": "empty",
+                "sec-fetch-mode": "cors",
+                "sec-fetch-site": "same-site"
+            },
+            "referrer": "https://ai.fmode.cn/",
+            "referrerPolicy": "strict-origin-when-cross-origin",
+            "body": JSON.stringify(bodyJson),
+            "method": "POST",
+            "mode": "cors",
+            "credentials": "omit"
+        })).pipe(
+            switchMap(response => {
+                const reader = response.body?.getReader();
+                if (!reader) {
+                    throw new Error("Failed to get the response reader.");
+                }
+                const decoder = new TextDecoder();
+                let buffer = "";
+                let messageAiReply = "";
+                let messageIndex = this.messageList.length;
+
+                return new Observable<{ content: string, cumulativeContent: string, done: boolean }>(observer => {
+                    const read = () => {
+                        reader.read().then(({ done, value }) => {
+                            if (done) {
+                                observer.complete();
+                                return;
+                            }
+
+                            buffer += decoder.decode(value);
+                            let messages = buffer.split("\n");
+
+                            for (let i = 0; i < messages.length - 1; i++) {
+                                let message = messages[i];
+                                let dataText = message.replace("data: ", "");
+
+                                if (dataText.startsWith("{")) {
+                                    try {
+                                        let dataJson = JSON.parse(dataText);
+                                        let content = dataJson?.choices?.[0]?.delta?.content || "";
+                                        messageAiReply += content;
+                                        this.messageList[messageIndex] = {
+                                            role: "assistant",
+                                            content: messageAiReply
+                                        };
+                                        observer.next({ content, cumulativeContent: messageAiReply, done: false });
+                                    } catch (err) { }
+                                }
+
+                                if (dataText.startsWith("[")) {
+                                    this.messageList[messageIndex] = {
+                                        role: "assistant",
+                                        content: messageAiReply
+                                    };
+                                    observer.next({ content: "", cumulativeContent: messageAiReply, done: true });
+                                    messageAiReply = "";
+                                }
+
+                                buffer = buffer.slice(message.length + 1);
+                            }
+
+                            read();
+                        }).catch(err => observer.error(err));
+                    };
+
+                    read();
+                });
+            }),
+            catchError(err => {
+                console.error(err);
+                return of({ content: "", cumulativeContent: "", done: true });
+            }),
+            finalize(() => {
+                console.log("Stream completed");
+            })
+        );
+    }
+}

+ 103 - 0
src/app/agent-shige/class-test-chat-completion.ts

@@ -0,0 +1,103 @@
+/*
+  案例:纯fetch读取http event stream数据
+*/
+export interface TestChatMessage{
+    role:string
+    content:string
+}
+export class TestChatCompletion{
+messageList:Array<TestChatMessage>
+constructor(messageList:Array<TestChatMessage>){
+    this.messageList = messageList
+}
+async createCompletionByStream() {
+
+let token = localStorage.getItem("token");
+let bodyJson = {
+  "token": `Bearer ${token}`,
+  "messages": this.messageList,
+  "model": "fmode-3.6-16k",
+  "temperature": 0.5,
+  "presence_penalty": 0,
+  "frequency_penalty": 0,
+  "top_p": 1,
+  "stream":true
+};
+
+let response = await fetch("https://test.fmode.cn/api/apig/aigc/gpt/v1/chat/completions", {
+  "headers": {
+    "accept": "text/event-stream",
+    "sec-fetch-dest": "empty",
+    "sec-fetch-mode": "cors",
+    "sec-fetch-site": "same-site"
+  },
+  "referrer": "https://ai.fmode.cn/",
+  "referrerPolicy": "strict-origin-when-cross-origin",
+  "body": JSON.stringify(bodyJson),
+  "method": "POST",
+  "mode": "cors",
+  "credentials": "omit"
+});
+
+let messageAiReply = ""
+let messageIndex = this.messageList.length
+let reader = response.body?.getReader();
+if (!reader) {
+  throw new Error("Failed to get the response reader.");
+}
+
+let decoder = new TextDecoder();
+let buffer = "";
+
+while (true) {
+  let { done, value } = await reader.read();
+  if (done) {
+    break;
+  }
+
+  buffer += decoder.decode(value);
+
+  // Split the buffer by newlines to get individual messages
+  let messages = buffer.split("\n");
+
+  // Process each message
+  for (let i = 0; i < messages.length - 1; i++) {
+    let message = messages[i];
+
+    // Process the message as needed
+    /**
+     * data: {"id":"chatcmpl-y2PLKqPDnwAFJIj2L5aqdH5TWK9Yv","object":"chat.completion.chunk","created":1696770162,"model":"gpt-3.5-turbo-0613","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
+     * data: {"id":"chatcmpl-y2PLKqPDnwAFJIj2L5aqdH5TWK9Yv","object":"chat.completion.chunk","created":1696770162,"model":"gpt-3.5-turbo-0613","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
+     * data: [DONE]
+     */
+    let dataText = message.replace("data:\ ","")
+    console.log(dataText)
+    if(dataText.startsWith("{")){
+      try{
+        let dataJson = JSON.parse(dataText)
+        console.log(dataJson)
+        messageAiReply += dataJson?.choices?.[0]?.delta?.content || ""
+        this.messageList[messageIndex] = {
+          role:"assistant",
+          content:messageAiReply
+        }
+      }catch(err){}
+    }
+    if(dataText.startsWith("[")){
+      console.log(message)
+      console.log("完成")
+      this.messageList[messageIndex] = {
+        role:"assistant",
+        content:messageAiReply
+      }
+      messageAiReply = ""
+    }
+    // Parse the message as JSON
+    // let data = JSON.parse(message);
+
+    // Clear the processed message from the buffer
+    buffer = buffer.slice(message.length + 1);
+  }
+}
+}
+}

+ 0 - 2
src/app/app-routing.module.ts

@@ -10,8 +10,6 @@ const routes: Routes = [
     path: 'detail',
     loadChildren: () => import('./detail-page/detail-page.module').then( m => m.DetailPagePageModule)
   },
-
-  
 ];
 @NgModule({
   imports: [

+ 17 - 0
src/app/pocircle/pocircle-routing.module.ts

@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { PocirclePage } from './pocircle.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: PocirclePage
+  }
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule],
+})
+export class PocirclePageRoutingModule {}

+ 20 - 0
src/app/pocircle/pocircle.module.ts

@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { IonicModule } from '@ionic/angular';
+
+import { PocirclePageRoutingModule } from './pocircle-routing.module';
+
+import { PocirclePage } from './pocircle.page';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    PocirclePageRoutingModule
+  ],
+  declarations: [PocirclePage]
+})
+export class PocirclePageModule {}

+ 233 - 0
src/app/pocircle/pocircle.page.html

@@ -0,0 +1,233 @@
+<ion-header>
+  <ion-toolbar class="custom-toolbar">
+    <!-- <ion-searchbar placeholder="诗词歌赋,作者,姓名" class="custom-searchbar"></ion-searchbar> -->
+    <ion-searchbar placeholder="诗词歌赋,作者,姓名" [debounce]="1000" (ionInput)="search($event)" class="custom-searchbar"></ion-searchbar> 
+    <ion-list class="list" *ngIf="results.length > 0">
+      <ion-item *ngFor="let result of results"(click)="goToDetailPage(result)">
+          <ion-label>{{ result?.get("title") }} {{result?.get("author")}}</ion-label>
+      </ion-item>
+  </ion-list>
+  
+
+    <ion-segment [(ngModel)]="selectedSegment" (ionChange)="segmentChanged($event)">  
+      <ion-segment-button value="discover" checked>  
+        <ion-label>发现</ion-label>  
+      </ion-segment-button>  
+      <ion-segment-button value="follow">  
+        <ion-label>关注</ion-label>  
+      </ion-segment-button>  
+      <ion-segment-button value="post">  
+        <ion-label>libai作诗</ion-label>  
+      </ion-segment-button>  
+    </ion-segment>  
+  </ion-toolbar>
+</ion-header>
+
+
+  
+  <ion-content>  
+    
+    
+    <div [ngSwitch]="selectedSegment">  
+      <div *ngSwitchCase="'discover'" class="svg-container">  
+        <!-- 循环展示用户发的内容 -->  
+        <svg class="svg"  width="310.5" height="290.5" viewBox="0 0 310.5 290.5">
+          <!-- 在这里粘贴SVG代码 -->
+          <svg  width="310.5" height="290.5" viewBox="0 0 310.5 290.5">
+            <defs>
+              <pattern id="pattern" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 800 1252">
+                <image width="800" height="1252" href="../../assets/icon/Ellipse 7.png"/>
+              </pattern>
+            </defs>
+            <text id="白客居士" transform="translate(43.5 0.5)" fill="#645a58" font-size="13" font-family="MicrosoftYaHei-Bold, Microsoft YaHei" font-weight="700" style="isolation: isolate"><tspan x="0" y="14">白客居士</tspan></text>
+            <g id="chat-quote" transform="translate(97.5 273.5)" style="isolation: isolate">
+              <path id="Vector" d="M2.678,10.894A5.5,5.5,0,0,1,1,7C1,3.808,4,1,8,1s7,2.808,7,6-3,6-7,6a8.059,8.059,0,0,1-2.088-.272A1,1,0,0,0,5.2,12.8a11.78,11.78,0,0,1-2.634.893,10.971,10.971,0,0,0,.4-2A1,1,0,0,0,2.678,10.894Zm-.493,3.9a13.628,13.628,0,0,0,3.468-1.1A9.061,9.061,0,0,0,8,14c4.418,0,8-3.134,8-7S12.418,0,8,0,0,3.134,0,7a6.5,6.5,0,0,0,1.97,4.6,10.437,10.437,0,0,1-.523,2.318l0,.011q-.045.131-.092.257c-.049.132-.1.259-.151.38a.26.26,0,0,0,.273.361q.211-.034.412-.071l.281-.053ZM5.667,5a1.667,1.667,0,1,0,.895,3.073,3.285,3.285,0,0,1-.778,1.221.417.417,0,0,0,.6.579,3.246,3.246,0,0,0,.683-4.112A1.665,1.665,0,0,0,5.667,5Zm4,0a1.667,1.667,0,1,0,.895,3.073,3.285,3.285,0,0,1-.778,1.221.417.417,0,0,0,.6.579,3.246,3.246,0,0,0,.683-4.112A1.665,1.665,0,0,0,9.667,5Z" transform="translate(0 1)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <g id="Rectangle_1201" data-name="Rectangle 1201" transform="translate(8.5 146.5)" fill="none" style="isolation: isolate">
+              <path d="M0,0H302V108H0Z" stroke="none"/>
+              <path d="M 1 1 L 1 107 L 301 107 L 301 1 L 1 1 M 0 0 L 302 0 L 302 108 L 0 108 L 0 0 Z" stroke="none" fill="#dbab56"/>
+            </g>
+            <g id="bookmark-frame" transform="translate(39.5 274.5)" style="isolation: isolate">
+              <path id="bookmark" d="M0,2V15.5a.5.5,0,0,0,.777.416L6,13.1l5.223,2.815A.5.5,0,0,0,12,15.5V2a2,2,0,0,0-2-2H2A2,2,0,0,0,0,2ZM2,1h8a1,1,0,0,1,1,1V14.566L6.277,12.084a.5.5,0,0,0-.555,0L1,14.566V2A1,1,0,0,1,2,1Z" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            
+            <g id="suit-heart"  transform="translate(8.5 274.5)" style="isolation: isolate">
+              <path id="Vector_Stroke_" data-name="Vector (Stroke)" d="M8-8.473l-.894-1.789a5.853,5.853,0,0,0-1.151-1.6A2.807,2.807,0,0,0,4-12.709a2.961,2.961,0,0,0-3,2.92c0,1.211.554,2.066,1.868,3.37.337.334.721.695,1.145,1.093A52.531,52.531,0,0,1,8-1.263a52.532,52.532,0,0,1,3.986-4.064c.424-.4.809-.759,1.145-1.093C14.446-7.724,15-8.578,15-9.789a2.961,2.961,0,0,0-3-2.92,2.807,2.807,0,0,0-1.954.852,5.854,5.854,0,0,0-1.151,1.6ZM7.608-.181A48.987,48.987,0,0,0,3.365-4.563C1.3-6.5,0-7.721,0-9.789a3.961,3.961,0,0,1,4-3.92A4.263,4.263,0,0,1,7.4-11.7a7.47,7.47,0,0,1,.6.992,7.47,7.47,0,0,1,.6-.992A4.263,4.263,0,0,1,12-13.709a3.961,3.961,0,0,1,4,3.92c0,2.069-1.3,3.288-3.365,5.227A48.989,48.989,0,0,0,8.392-.181.513.513,0,0,1,7.608-.181Z" transform="translate(0 14.709)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+
+            <g id="escape" transform="translate(82.5 274.5) rotate(180)" style="isolation: isolate">
+              <path id="Union" d="M7.538,0A7,7,0,0,0,14-6.981a7,7,0,0,0-7-7A7,7,0,0,0,.02-7.519a.5.5,0,0,0,.461.536.5.5,0,0,0,.536-.461A6,6,0,0,1,7-12.981a6,6,0,0,1,6,6A6,6,0,0,1,7.462-1,.5.5,0,0,0,7-.462.5.5,0,0,0,7.538,0ZM6.1-6.81,1-1.713V-4.481a.5.5,0,0,0-.5-.5.5.5,0,0,0-.5.5V-.506a.5.5,0,0,0,.5.5H4.475a.5.5,0,0,0,.5-.5.5.5,0,0,0-.5-.5H1.707L6.8-6.1a.5.5,0,0,0,0-.707A.5.5,0,0,0,6.1-6.81Z" transform="translate(1 -1.019)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <text id="辛弃疾" transform="translate(25.5 185.5)" fill="#dbab56" font-size="12" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="13">辛弃疾</tspan></text>
+            <text id="刚刚推荐" transform="translate(43.5 22.5)" fill="rgba(128,100,74,0.5)" font-size="11" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="12">刚刚推荐</tspan></text>
+            <text id="南乡子_节选_" data-name="南乡子(节选)" transform="translate(25.5 158.5)" fill="#dbab56" font-size="15" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="16">南乡子(节选)</tspan></text>
+            <text id="何处望神州_满眼风光北固楼_千古兴亡多少事_悠悠_不尽长江滚滚流_年少万兜鍪_坐断东南战未休_天下英雄谁敌手_曹刘_生子当如孙仲谋_" data-name="何处望神州?满眼风光北固楼。千古兴亡多少事?悠悠。不尽长江滚滚流。年少万兜鍪,坐断东南战未休。天下英雄谁敌手?曹刘。生子当如孙仲谋。" transform="translate(25.5 201.5)" fill="#dbab56" font-size="10" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="11">何处望神州?满眼风光北固楼。千古兴亡多少事?悠悠。不</tspan><tspan x="0" y="25">尽长江滚滚流。年少万兜鍪,坐断东南战未休。天下英雄谁</tspan><tspan x="0" y="39">敌手?曹刘。生子当如孙仲谋。</tspan></text>
+            <text id="_读辛弃疾_南乡子_这支曲子一二两句_对仗工丽_写景如画_点染出一幅清丽无比的秋江图_然而这仅仅是表层_作者还另有深意_" data-name="——读辛弃疾《南乡子》
+          这支曲子一二两句,对仗工丽,写景如画,点染出一幅清丽无比的秋江图。然而这仅仅是表层,作者还另有深意。" transform="translate(7.5 50.5)" fill="#645a58" font-size="13" font-family="MicrosoftYaHei, Microsoft YaHei" style="isolation: isolate"><tspan x="0" y="14">——读辛弃疾《南乡子》</tspan><tspan x="0" y="31">这支曲子一二两句,对仗工丽,写景如画,点染出一</tspan><tspan x="0" y="48">幅清丽无比的秋江图。然而这仅仅是表层,作者还另</tspan><tspan x="0" y="65">有深意。</tspan></text>
+            <path id="Ellipse_7" data-name="Ellipse 7" d="M0,18A18,18,0,1,1,18,36,18,18,0,0,1,0,18Z" transform="translate(0.5 0.5)" stroke="#645a58" stroke-width="1" fill="url(#pattern)" style="isolation: isolate"/>
+            
+          </svg>
+        
+          
+        </svg>
+      
+        <svg class="svg"  width="310.5" height="290.5" viewBox="0 0 310.5 290.5">
+          <!-- 在这里粘贴SVG代码 -->
+          <svg  width="310.5" height="290.5" viewBox="0 0 310.5 290.5">
+            <defs>
+              <pattern id="pattern" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 800 1252">
+                <image width="800" height="1252" xlink:href=""/>
+              </pattern>
+            </defs>
+            <text id="东晋田园诗人" transform="translate(43.5 0.5)" fill="#645a58" font-size="13" font-family="MicrosoftYaHei-Bold, Microsoft YaHei" font-weight="700" style="isolation: isolate"><tspan x="0" y="14">东晋田园诗人</tspan></text>
+            <g id="chat-quote" transform="translate(97.5 273.5)" style="isolation: isolate">
+              <path id="Vector" d="M2.678,10.894A5.5,5.5,0,0,1,1,7C1,3.808,4,1,8,1s7,2.808,7,6-3,6-7,6a8.059,8.059,0,0,1-2.088-.272A1,1,0,0,0,5.2,12.8a11.78,11.78,0,0,1-2.634.893,10.971,10.971,0,0,0,.4-2A1,1,0,0,0,2.678,10.894Zm-.493,3.9a13.628,13.628,0,0,0,3.468-1.1A9.061,9.061,0,0,0,8,14c4.418,0,8-3.134,8-7S12.418,0,8,0,0,3.134,0,7a6.5,6.5,0,0,0,1.97,4.6,10.437,10.437,0,0,1-.523,2.318l0,.011q-.045.131-.092.257c-.049.132-.1.259-.151.38a.26.26,0,0,0,.273.361q.211-.034.412-.071l.281-.053ZM5.667,5a1.667,1.667,0,1,0,.895,3.073,3.285,3.285,0,0,1-.778,1.221.417.417,0,0,0,.6.579,3.246,3.246,0,0,0,.683-4.112A1.665,1.665,0,0,0,5.667,5Zm4,0a1.667,1.667,0,1,0,.895,3.073,3.285,3.285,0,0,1-.778,1.221.417.417,0,0,0,.6.579,3.246,3.246,0,0,0,.683-4.112A1.665,1.665,0,0,0,9.667,5Z" transform="translate(0 1)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <g id="Rectangle_1201" data-name="Rectangle 1201" transform="translate(8.5 146.5)" fill="none" style="isolation: isolate">
+              <path d="M0,0H302V108H0Z" stroke="none"/>
+              <path d="M 1 1 L 1 107 L 301 107 L 301 1 L 1 1 M 0 0 L 302 0 L 302 108 L 0 108 L 0 0 Z" stroke="none" fill="#dbab56"/>
+            </g>
+            <g id="bookmark-frame" transform="translate(39.5 274.5)" style="isolation: isolate">
+              <path id="bookmark" d="M0,2V15.5a.5.5,0,0,0,.777.416L6,13.1l5.223,2.815A.5.5,0,0,0,12,15.5V2a2,2,0,0,0-2-2H2A2,2,0,0,0,0,2ZM2,1h8a1,1,0,0,1,1,1V14.566L6.277,12.084a.5.5,0,0,0-.555,0L1,14.566V2A1,1,0,0,1,2,1Z" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <g id="suit-heart" transform="translate(8.5 274.5)" style="isolation: isolate">
+              <path id="Vector_Stroke_" data-name="Vector (Stroke)" d="M8-8.473l-.894-1.789a5.853,5.853,0,0,0-1.151-1.6A2.807,2.807,0,0,0,4-12.709a2.961,2.961,0,0,0-3,2.92c0,1.211.554,2.066,1.868,3.37.337.334.721.695,1.145,1.093A52.531,52.531,0,0,1,8-1.263a52.532,52.532,0,0,1,3.986-4.064c.424-.4.809-.759,1.145-1.093C14.446-7.724,15-8.578,15-9.789a2.961,2.961,0,0,0-3-2.92,2.807,2.807,0,0,0-1.954.852,5.854,5.854,0,0,0-1.151,1.6ZM7.608-.181A48.987,48.987,0,0,0,3.365-4.563C1.3-6.5,0-7.721,0-9.789a3.961,3.961,0,0,1,4-3.92A4.263,4.263,0,0,1,7.4-11.7a7.47,7.47,0,0,1,.6.992,7.47,7.47,0,0,1,.6-.992A4.263,4.263,0,0,1,12-13.709a3.961,3.961,0,0,1,4,3.92c0,2.069-1.3,3.288-3.365,5.227A48.989,48.989,0,0,0,8.392-.181.513.513,0,0,1,7.608-.181Z" transform="translate(0 14.709)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <g id="escape" transform="translate(82.5 274.5) rotate(180)" style="isolation: isolate">
+              <path id="Union" d="M7.538,0A7,7,0,0,0,14-6.981a7,7,0,0,0-7-7A7,7,0,0,0,.02-7.519a.5.5,0,0,0,.461.536.5.5,0,0,0,.536-.461A6,6,0,0,1,7-12.981a6,6,0,0,1,6,6A6,6,0,0,1,7.462-1,.5.5,0,0,0,7-.462.5.5,0,0,0,7.538,0ZM6.1-6.81,1-1.713V-4.481a.5.5,0,0,0-.5-.5.5.5,0,0,0-.5.5V-.506a.5.5,0,0,0,.5.5H4.475a.5.5,0,0,0,.5-.5.5.5,0,0,0-.5-.5H1.707L6.8-6.1a.5.5,0,0,0,0-.707A.5.5,0,0,0,6.1-6.81Z" transform="translate(1 -1.019)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <text id="陶渊明" transform="translate(25.5 185.5)" fill="#dbab56" font-size="12" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="13">陶渊明</tspan></text>
+            <text id="刚刚推荐" transform="translate(43.5 22.5)" fill="rgba(128,100,74,0.5)" font-size="11" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="12">刚刚推荐</tspan></text>
+            <text id="南乡子_节选_" data-name="南乡子(节选)" transform="translate(25.5 158.5)" fill="#dbab56" font-size="15" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="16">桃花源记(节选)</tspan></text>
+            <text id="何处望神州_满眼风光北固楼_千古兴亡多少事_悠悠_不尽长江滚滚流_年少万兜鍪_坐断东南战未休_天下英雄谁敌手_曹刘_生子当如孙仲谋_" data-name="何处望神州?满眼风光北固楼。千古兴亡多少事?悠悠。不尽长江滚滚流。年少万兜鍪,坐断东南战未休。天下英雄谁敌手?曹刘。生子当如孙仲谋。" transform="translate(25.5 201.5)" fill="#dbab56" font-size="10" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="11">林尽水源,便得山,山有小口,仿佛若有光。便舍船,从口入。</tspan><tspan x="0" y="25">初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨</tspan><tspan x="0" y="39">然,有良田美池桑竹之属。</tspan></text>
+            <text id="《桃花源记》通过对桃花源的安宁和乐、自由平等生活的描绘,表现了作者追求美好生活的理想和对现实,生活的不满。" data-name="——读陶渊明《桃花源记》
+          这支曲子一二两句,对仗工丽,写景如画,点染出一幅清丽无比的秋江图。然而这仅仅是表层,作者还另有深意。" transform="translate(7.5 50.5)" fill="#645a58" font-size="13" font-family="MicrosoftYaHei, Microsoft YaHei" style="isolation: isolate"><tspan x="0" y="14">——读陶渊明《桃花源记》</tspan><tspan x="0" y="31">《桃花源记》通过对桃花源的安宁和乐、自由平等生</tspan><tspan x="0" y="48">活的描绘,表现了作者追求美好生活的理想和对现实</tspan><tspan x="0" y="65">生活的不满。</tspan></text>
+            <path id="Ellipse_7" data-name="Ellipse 7" d="M0,18A18,18,0,1,1,18,36,18,18,0,0,1,0,18Z" transform="translate(0.5 0.5)" stroke="#645a58" stroke-width="1" fill="url(#pattern)" style="isolation: isolate"/>
+          </svg>
+          
+          
+        </svg>
+
+        <svg class="svg"  width="310.5" height="290.5" viewBox="0 0 310.5 290.5">
+          <!-- 在这里粘贴SVG代码 -->
+          <svg  width="310.5" height="290.5" viewBox="0 0 310.5 290.5">
+            <defs>
+              <pattern id="pattern" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 800 1252">
+                <image width="800" height="1252" xlink:href=""/>
+              </pattern>
+            </defs>
+            <text id="白客居士" transform="translate(43.5 0.5)" fill="#645a58" font-size="13" font-family="MicrosoftYaHei-Bold, Microsoft YaHei" font-weight="700" style="isolation: isolate"><tspan x="0" y="14">白客居士</tspan></text>
+            <g id="chat-quote" transform="translate(97.5 273.5)" style="isolation: isolate">
+              <path id="Vector" d="M2.678,10.894A5.5,5.5,0,0,1,1,7C1,3.808,4,1,8,1s7,2.808,7,6-3,6-7,6a8.059,8.059,0,0,1-2.088-.272A1,1,0,0,0,5.2,12.8a11.78,11.78,0,0,1-2.634.893,10.971,10.971,0,0,0,.4-2A1,1,0,0,0,2.678,10.894Zm-.493,3.9a13.628,13.628,0,0,0,3.468-1.1A9.061,9.061,0,0,0,8,14c4.418,0,8-3.134,8-7S12.418,0,8,0,0,3.134,0,7a6.5,6.5,0,0,0,1.97,4.6,10.437,10.437,0,0,1-.523,2.318l0,.011q-.045.131-.092.257c-.049.132-.1.259-.151.38a.26.26,0,0,0,.273.361q.211-.034.412-.071l.281-.053ZM5.667,5a1.667,1.667,0,1,0,.895,3.073,3.285,3.285,0,0,1-.778,1.221.417.417,0,0,0,.6.579,3.246,3.246,0,0,0,.683-4.112A1.665,1.665,0,0,0,5.667,5Zm4,0a1.667,1.667,0,1,0,.895,3.073,3.285,3.285,0,0,1-.778,1.221.417.417,0,0,0,.6.579,3.246,3.246,0,0,0,.683-4.112A1.665,1.665,0,0,0,9.667,5Z" transform="translate(0 1)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <g id="Rectangle_1201" data-name="Rectangle 1201" transform="translate(8.5 146.5)" fill="none" style="isolation: isolate">
+              <path d="M0,0H302V108H0Z" stroke="none"/>
+              <path d="M 1 1 L 1 107 L 301 107 L 301 1 L 1 1 M 0 0 L 302 0 L 302 108 L 0 108 L 0 0 Z" stroke="none" fill="#dbab56"/>
+            </g>
+            <g id="bookmark-frame" transform="translate(39.5 274.5)" style="isolation: isolate">
+              <path id="bookmark" d="M0,2V15.5a.5.5,0,0,0,.777.416L6,13.1l5.223,2.815A.5.5,0,0,0,12,15.5V2a2,2,0,0,0-2-2H2A2,2,0,0,0,0,2ZM2,1h8a1,1,0,0,1,1,1V14.566L6.277,12.084a.5.5,0,0,0-.555,0L1,14.566V2A1,1,0,0,1,2,1Z" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <g id="suit-heart" transform="translate(8.5 274.5)" style="isolation: isolate">
+              <path id="Vector_Stroke_" data-name="Vector (Stroke)" d="M8-8.473l-.894-1.789a5.853,5.853,0,0,0-1.151-1.6A2.807,2.807,0,0,0,4-12.709a2.961,2.961,0,0,0-3,2.92c0,1.211.554,2.066,1.868,3.37.337.334.721.695,1.145,1.093A52.531,52.531,0,0,1,8-1.263a52.532,52.532,0,0,1,3.986-4.064c.424-.4.809-.759,1.145-1.093C14.446-7.724,15-8.578,15-9.789a2.961,2.961,0,0,0-3-2.92,2.807,2.807,0,0,0-1.954.852,5.854,5.854,0,0,0-1.151,1.6ZM7.608-.181A48.987,48.987,0,0,0,3.365-4.563C1.3-6.5,0-7.721,0-9.789a3.961,3.961,0,0,1,4-3.92A4.263,4.263,0,0,1,7.4-11.7a7.47,7.47,0,0,1,.6.992,7.47,7.47,0,0,1,.6-.992A4.263,4.263,0,0,1,12-13.709a3.961,3.961,0,0,1,4,3.92c0,2.069-1.3,3.288-3.365,5.227A48.989,48.989,0,0,0,8.392-.181.513.513,0,0,1,7.608-.181Z" transform="translate(0 14.709)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <g id="escape" transform="translate(82.5 274.5) rotate(180)" style="isolation: isolate">
+              <path id="Union" d="M7.538,0A7,7,0,0,0,14-6.981a7,7,0,0,0-7-7A7,7,0,0,0,.02-7.519a.5.5,0,0,0,.461.536.5.5,0,0,0,.536-.461A6,6,0,0,1,7-12.981a6,6,0,0,1,6,6A6,6,0,0,1,7.462-1,.5.5,0,0,0,7-.462.5.5,0,0,0,7.538,0ZM6.1-6.81,1-1.713V-4.481a.5.5,0,0,0-.5-.5.5.5,0,0,0-.5.5V-.506a.5.5,0,0,0,.5.5H4.475a.5.5,0,0,0,.5-.5.5.5,0,0,0-.5-.5H1.707L6.8-6.1a.5.5,0,0,0,0-.707A.5.5,0,0,0,6.1-6.81Z" transform="translate(1 -1.019)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <text id="辛弃疾" transform="translate(25.5 185.5)" fill="#dbab56" font-size="12" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="13">辛弃疾</tspan></text>
+            <text id="刚刚推荐" transform="translate(43.5 22.5)" fill="rgba(128,100,74,0.5)" font-size="11" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="12">刚刚推荐</tspan></text>
+            <text id="南乡子_节选_" data-name="南乡子(节选)" transform="translate(25.5 158.5)" fill="#dbab56" font-size="15" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="16">南乡子(节选)</tspan></text>
+            <text id="何处望神州_满眼风光北固楼_千古兴亡多少事_悠悠_不尽长江滚滚流_年少万兜鍪_坐断东南战未休_天下英雄谁敌手_曹刘_生子当如孙仲谋_" data-name="何处望神州?满眼风光北固楼。千古兴亡多少事?悠悠。不尽长江滚滚流。年少万兜鍪,坐断东南战未休。天下英雄谁敌手?曹刘。生子当如孙仲谋。" transform="translate(25.5 201.5)" fill="#dbab56" font-size="10" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="11">何处望神州?满眼风光北固楼。千古兴亡多少事?悠悠。不</tspan><tspan x="0" y="25">尽长江滚滚流。年少万兜鍪,坐断东南战未休。天下英雄谁</tspan><tspan x="0" y="39">敌手?曹刘。生子当如孙仲谋。</tspan></text>
+            <text id="_读辛弃疾_南乡子_这支曲子一二两句_对仗工丽_写景如画_点染出一幅清丽无比的秋江图_然而这仅仅是表层_作者还另有深意_" data-name="——读辛弃疾《南乡子》
+          这支曲子一二两句,对仗工丽,写景如画,点染出一幅清丽无比的秋江图。然而这仅仅是表层,作者还另有深意。" transform="translate(7.5 50.5)" fill="#645a58" font-size="13" font-family="MicrosoftYaHei, Microsoft YaHei" style="isolation: isolate"><tspan x="0" y="14">——读辛弃疾《南乡子》</tspan><tspan x="0" y="31">这支曲子一二两句,对仗工丽,写景如画,点染出一</tspan><tspan x="0" y="48">幅清丽无比的秋江图。然而这仅仅是表层,作者还另</tspan><tspan x="0" y="65">有深意。</tspan></text>
+            <path id="Ellipse_7" data-name="Ellipse 7" d="M0,18A18,18,0,1,1,18,36,18,18,0,0,1,0,18Z" transform="translate(0.5 0.5)" stroke="#645a58" stroke-width="1" fill="url(#pattern)" style="isolation: isolate"/>
+          </svg>
+          
+          
+        </svg>
+
+        <svg class="svg"  width="310.5" height="290.5" viewBox="0 0 310.5 290.5">
+          <!-- 在这里粘贴SVG代码 -->
+          <svg  width="310.5" height="290.5" viewBox="0 0 310.5 290.5">
+            <defs>
+              <pattern id="pattern" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 800 1252">
+                <image width="800" height="1252" xlink:href=""/>
+              </pattern>
+            </defs>
+            <text id="东晋田园诗人" transform="translate(43.5 0.5)" fill="#645a58" font-size="13" font-family="MicrosoftYaHei-Bold, Microsoft YaHei" font-weight="700" style="isolation: isolate"><tspan x="0" y="14">东晋田园诗人</tspan></text>
+            <g id="chat-quote" transform="translate(97.5 273.5)" style="isolation: isolate">
+              <path id="Vector" d="M2.678,10.894A5.5,5.5,0,0,1,1,7C1,3.808,4,1,8,1s7,2.808,7,6-3,6-7,6a8.059,8.059,0,0,1-2.088-.272A1,1,0,0,0,5.2,12.8a11.78,11.78,0,0,1-2.634.893,10.971,10.971,0,0,0,.4-2A1,1,0,0,0,2.678,10.894Zm-.493,3.9a13.628,13.628,0,0,0,3.468-1.1A9.061,9.061,0,0,0,8,14c4.418,0,8-3.134,8-7S12.418,0,8,0,0,3.134,0,7a6.5,6.5,0,0,0,1.97,4.6,10.437,10.437,0,0,1-.523,2.318l0,.011q-.045.131-.092.257c-.049.132-.1.259-.151.38a.26.26,0,0,0,.273.361q.211-.034.412-.071l.281-.053ZM5.667,5a1.667,1.667,0,1,0,.895,3.073,3.285,3.285,0,0,1-.778,1.221.417.417,0,0,0,.6.579,3.246,3.246,0,0,0,.683-4.112A1.665,1.665,0,0,0,5.667,5Zm4,0a1.667,1.667,0,1,0,.895,3.073,3.285,3.285,0,0,1-.778,1.221.417.417,0,0,0,.6.579,3.246,3.246,0,0,0,.683-4.112A1.665,1.665,0,0,0,9.667,5Z" transform="translate(0 1)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <g id="Rectangle_1201" data-name="Rectangle 1201" transform="translate(8.5 146.5)" fill="none" style="isolation: isolate">
+              <path d="M0,0H302V108H0Z" stroke="none"/>
+              <path d="M 1 1 L 1 107 L 301 107 L 301 1 L 1 1 M 0 0 L 302 0 L 302 108 L 0 108 L 0 0 Z" stroke="none" fill="#dbab56"/>
+            </g>
+            <g id="bookmark-frame" transform="translate(39.5 274.5)" style="isolation: isolate">
+              <path id="bookmark" d="M0,2V15.5a.5.5,0,0,0,.777.416L6,13.1l5.223,2.815A.5.5,0,0,0,12,15.5V2a2,2,0,0,0-2-2H2A2,2,0,0,0,0,2ZM2,1h8a1,1,0,0,1,1,1V14.566L6.277,12.084a.5.5,0,0,0-.555,0L1,14.566V2A1,1,0,0,1,2,1Z" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <g id="suit-heart" transform="translate(8.5 274.5)" style="isolation: isolate">
+              <path id="Vector_Stroke_" data-name="Vector (Stroke)" d="M8-8.473l-.894-1.789a5.853,5.853,0,0,0-1.151-1.6A2.807,2.807,0,0,0,4-12.709a2.961,2.961,0,0,0-3,2.92c0,1.211.554,2.066,1.868,3.37.337.334.721.695,1.145,1.093A52.531,52.531,0,0,1,8-1.263a52.532,52.532,0,0,1,3.986-4.064c.424-.4.809-.759,1.145-1.093C14.446-7.724,15-8.578,15-9.789a2.961,2.961,0,0,0-3-2.92,2.807,2.807,0,0,0-1.954.852,5.854,5.854,0,0,0-1.151,1.6ZM7.608-.181A48.987,48.987,0,0,0,3.365-4.563C1.3-6.5,0-7.721,0-9.789a3.961,3.961,0,0,1,4-3.92A4.263,4.263,0,0,1,7.4-11.7a7.47,7.47,0,0,1,.6.992,7.47,7.47,0,0,1,.6-.992A4.263,4.263,0,0,1,12-13.709a3.961,3.961,0,0,1,4,3.92c0,2.069-1.3,3.288-3.365,5.227A48.989,48.989,0,0,0,8.392-.181.513.513,0,0,1,7.608-.181Z" transform="translate(0 14.709)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <g id="escape" transform="translate(82.5 274.5) rotate(180)" style="isolation: isolate">
+              <path id="Union" d="M7.538,0A7,7,0,0,0,14-6.981a7,7,0,0,0-7-7A7,7,0,0,0,.02-7.519a.5.5,0,0,0,.461.536.5.5,0,0,0,.536-.461A6,6,0,0,1,7-12.981a6,6,0,0,1,6,6A6,6,0,0,1,7.462-1,.5.5,0,0,0,7-.462.5.5,0,0,0,7.538,0ZM6.1-6.81,1-1.713V-4.481a.5.5,0,0,0-.5-.5.5.5,0,0,0-.5.5V-.506a.5.5,0,0,0,.5.5H4.475a.5.5,0,0,0,.5-.5.5.5,0,0,0-.5-.5H1.707L6.8-6.1a.5.5,0,0,0,0-.707A.5.5,0,0,0,6.1-6.81Z" transform="translate(1 -1.019)" fill="rgba(128,100,74,0.5)" style="isolation: isolate"/>
+            </g>
+            <text id="陶渊明" transform="translate(25.5 185.5)" fill="#dbab56" font-size="12" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="13">陶渊明</tspan></text>
+            <text id="刚刚推荐" transform="translate(43.5 22.5)" fill="rgba(128,100,74,0.5)" font-size="11" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="12">刚刚推荐</tspan></text>
+            <text id="南乡子_节选_" data-name="南乡子(节选)" transform="translate(25.5 158.5)" fill="#dbab56" font-size="15" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="16">桃花源记(节选)</tspan></text>
+            <text id="何处望神州_满眼风光北固楼_千古兴亡多少事_悠悠_不尽长江滚滚流_年少万兜鍪_坐断东南战未休_天下英雄谁敌手_曹刘_生子当如孙仲谋_" data-name="何处望神州?满眼风光北固楼。千古兴亡多少事?悠悠。不尽长江滚滚流。年少万兜鍪,坐断东南战未休。天下英雄谁敌手?曹刘。生子当如孙仲谋。" transform="translate(25.5 201.5)" fill="#dbab56" font-size="10" font-family="MicrosoftYaHei, Microsoft YaHei" letter-spacing="0.001em" style="isolation: isolate"><tspan x="0" y="11">林尽水源,便得山,山有小口,仿佛若有光。便舍船,从口入。</tspan><tspan x="0" y="25">初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨</tspan><tspan x="0" y="39">然,有良田美池桑竹之属。</tspan></text>
+            <text id="《桃花源记》通过对桃花源的安宁和乐、自由平等生活的描绘,表现了作者追求美好生活的理想和对现实,生活的不满。" data-name="——读陶渊明《桃花源记》
+          这支曲子一二两句,对仗工丽,写景如画,点染出一幅清丽无比的秋江图。然而这仅仅是表层,作者还另有深意。" transform="translate(7.5 50.5)" fill="#645a58" font-size="13" font-family="MicrosoftYaHei, Microsoft YaHei" style="isolation: isolate"><tspan x="0" y="14">——读陶渊明《桃花源记》</tspan><tspan x="0" y="31">《桃花源记》通过对桃花源的安宁和乐、自由平等生</tspan><tspan x="0" y="48">活的描绘,表现了作者追求美好生活的理想和对现实</tspan><tspan x="0" y="65">生活的不满。</tspan></text>
+            <path id="Ellipse_7" data-name="Ellipse 7" d="M0,18A18,18,0,1,1,18,36,18,18,0,0,1,0,18Z" transform="translate(0.5 0.5)" stroke="#645a58" stroke-width="1" fill="url(#pattern)" style="isolation: isolate"/>
+          </svg>
+          
+          
+          
+        </svg>
+
+      </div>  
+    
+      <div *ngSwitchCase="'follow'">  
+        <!-- 循环展示关注板块内容 -->  
+        
+      </div>  
+    
+      <div *ngSwitchCase="'post'">  
+        <!-- 发动态板块 -->  
+        <!-- 这里可以放置上传图片和诗文创作的表单 -->  
+        <ion-item>
+          <ion-input placeholder="关键词" [(ngModel)]="shigeOptions.keywords"></ion-input>
+        </ion-item>
+        <ion-item>
+          <ion-input placeholder="创作灵感" [(ngModel)]="shigeOptions.content"></ion-input>
+        </ion-item>
+        <ion-item>
+          <ion-select label="诗歌格律" placeholder="格律" [(ngModel)]="shigeOptions.type">
+            <ion-select-option value="不限制">不限制</ion-select-option>
+            <ion-select-option value="七言绝句">七言绝句</ion-select-option>
+            <ion-select-option value="五言律诗">五言律诗</ion-select-option>
+            <ion-select-option value="藏头诗">藏头诗</ion-select-option>
+            <ion-select-option value="宋词">藏头诗</ion-select-option>
+          </ion-select>
+        </ion-item>
+        <ion-item>
+          <ion-select label="诗歌主题" placeholder="主题" [(ngModel)]="shigeOptions.theme">
+            <ion-select-option value="不限制">不限制</ion-select-option>
+            <ion-select-option [value]="item" *ngFor="let item of themeList">{{item}}</ion-select-option>
+          </ion-select>
+        </ion-item>
+        <ion-button expand="block" (click)="sendMessage()">发送</ion-button>
+      
+        <ion-card *ngFor="let message of messageList">
+          <ion-card-header>
+            {{message?.role}}
+          </ion-card-header>
+          <ion-card-content>
+            {{ message?.content }}
+          </ion-card-content>
+        </ion-card>
+
+        <form>
+        </form>
+      </div>  
+      
+
+        

+ 76 - 0
src/app/pocircle/pocircle.page.scss

@@ -0,0 +1,76 @@
+
+// .custom-toolbar{
+//     background: #f7b824; 
+//   }
+  ion-toolbar{
+    --background:#faf8ec;/* 设置ion-toolbar背景颜色为#faf8ec */
+    
+  }
+  ion-searchbar.custom-searchbar {
+    padding-top: 30px;
+    --background: #ffffff; /* 设置搜索框内部背景颜色为白色 */
+    background:#faf8ec;
+  
+    margin: 0%;
+    padding-bottom: 10px;
+  }
+
+  ion-segment {
+
+    ion-segment-button::part(indicator-background) {
+      background: #dbab56;
+    }
+    
+    /* Material Design styles */
+    ion-segment-button.md::part(native) {
+      color: #000;
+    }
+    
+    .segment-button-checked.md::part(native) {
+      color: #dbab56;
+    }
+    
+    ion-segment-button.md::part(indicator-background) {
+      height: 4px;
+    }
+    
+    /* iOS styles */
+    ion-segment-button.ios::part(native) {
+      color: #dbab56;
+    }
+    
+    .segment-button-checked.ios::part(native) {
+      color: #fff;
+    }
+    
+    ion-segment-button.ios::part(indicator-background) {
+      border-radius: 20px;
+    }
+  }
+
+  // svg {
+  //   position: absolute; /* 或 relative */
+  //   top: 50px;
+  //   left: 50px;
+   
+  // }
+
+  .svg-container {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    // height: 100vh; /* 设置容器高度为视口高度 */
+  }
+
+  .svg {
+    margin: 20px 0;
+  }
+
+  .svg:first-child {
+    margin-top: 20px; /* 调整第一个SVG与顶部的距离 */
+  }
+
+  .red-color {
+    fill: red !important;
+}

+ 17 - 0
src/app/pocircle/pocircle.page.spec.ts

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

+ 173 - 0
src/app/pocircle/pocircle.page.ts

@@ -0,0 +1,173 @@
+import { Component, OnInit } from '@angular/core';
+// 引用FmodeChatCompletion类
+import { NavController } from '@ionic/angular';
+import { TestRxjsChatCompletion, TestRxjsChatMessage } from '../agent-shige/class-rxjs-chat-completion';
+import Parse from "parse";
+
+@Component({
+  selector: 'app-pocircle',
+  templateUrl: './pocircle.page.html',
+  styleUrls: ['./pocircle.page.scss'],
+})
+export class PocirclePage implements OnInit {
+  // segment: string = 'discover'; // 默认显示发现板块
+
+
+  // 假设这是用户发布的内容数组  
+  userPosts: any[] = [
+    { id: 1, username: '用户A', content: '这是一段诗的创作内容' },
+    { id: 2, username: '用户B', content: '这是另一段创作' },
+    // ... 可以添加更多用户内容  
+  ];
+
+  // 假设这是用户关注的对象数组  
+  userFollows: any[] = [
+    { id: 1, username: '关注者A', relatedContent: '相关创作A' },
+    { id: 2, username: '关注者B', relatedContent: '相关创作B' },
+    // ... 可以添加更多关注对象  
+  ];
+  selectedSegment: string = 'discover'; // 初始值  
+
+  // 定义 segmentChanged 方法  
+  segmentChanged(event: CustomEvent) {
+    // event.detail 通常包含新选中的段的值  
+    this.selectedSegment = event.detail.value;
+    // 这里可以添加更多的逻辑,比如根据选中的段来过滤数据或执行其他操作  
+  }
+
+
+  // 初始化图标名称和颜色  
+  favoriteIconName = 'heart'; // 默认图标名称  
+  favoriteColor = 'white'; // 默认颜色  
+
+  // 跟踪图标是否激活  
+  isFavoriteActive = false;
+  // 切换图标颜色的函数  
+  toggleIconColor(iconName: string) {
+    // 这里可以添加更多的逻辑来处理不同的图标  
+    if (iconName === 'favorite') {
+      this.isFavoriteActive = !this.isFavoriteActive;
+      this.favoriteColor = this.isFavoriteActive ? 'red' : 'white';
+    }
+  }
+
+  //搜索下拉框内容
+  results: Parse.Object[] = []
+  segment = 'tang';
+  search(event: any) {
+    console.log('Searching for:', event.detail.value);
+    if (event?.detail?.value) {
+      this.loadShigeList(event?.detail?.value)
+    }
+  }
+  filteredAuthors: any[] = [];
+
+  async loadShigeList(search: string) {
+    let query = new Parse.Query("Shige");
+    query.select("title");
+    query.contains("title", search);
+    query.limit(5);
+    this.results = await query.find();
+  }
+
+  constructor(private navController: NavController) { }
+  goToDetailPage(item: Parse.Object) {
+    this.results = []
+    this.navController.navigateForward('/detail/' + item.id);
+  }
+
+  //ai生成诗
+  messageList: Array<TestRxjsChatMessage> = []
+  shigeOptions: any = {
+    content: "",
+    type: "不限制",
+    theme: "不限制",
+  }
+  themeList = ['羁旅思乡诗', '爱情闺怨诗', '咏史怀古诗', '咏物言志诗', '送别怀人诗', '边塞征战诗', '山水田园诗']
+
+
+  ngOnInit() {
+  }
+  sendMessage() {
+    /*
+4. 风格:选择风格,例如“豪放”或“婉约”。
+5. 情感:描述诗中应表达的情感,例如“喜悦”、“忧愁”、“思念”等。
+
+    */
+    let GuhiPromoptTemplate = `
+你是一位中国的古代诗人,擅长文言文,和现代词汇转古词语经验和技巧,并且精通各类主题、格律的诗词。请根据以下要求创作一首诗:
+1. 主题:${this.shigeOptions?.theme}。
+2. 格律:${this.shigeOptions?.type}。
+3. 关键词:${this.shigeOptions?.keywords}。
+4. 创意灵感:${this.shigeOptions?.content}。
+请根据以上要求创作一首古代诗词,并且格式要严格,有必要的情况下,可以牺牲一些关键词原意。
+
+请开始创作,并按照以下格式返回
+题目:
+内容:
+简介:
+    `
+    this.messageList.push({
+      role: "user",
+      content: GuhiPromoptTemplate
+    })
+
+    // messageList在competion内部,已经赋予了完整的message
+    // 下方暴露出来的可订阅内容,主要是用于关键字过滤,或者其他开发逻辑的续写
+    let resultStr = ""
+    let testChatCompletion = new TestRxjsChatCompletion(this.messageList);
+    testChatCompletion.createCompletionByStream({ model: "fmode-3.6-16k" }).subscribe({
+      next: ({ content, cumulativeContent, done }) => {
+        resultStr = cumulativeContent
+        console.log(`Content: ${content}`);
+        console.log(`Cumulative Content: ${cumulativeContent}`);
+        if (done) {
+          console.log('Stream completed');
+        }
+      },
+      error: err => console.error(err),
+      complete: () => {
+        // 诗歌创建完成:正则表达式,匹配诗歌json内容
+        console.log("原文", resultStr)
+
+        let pattern = /题目:\s*(.*?)\s*内容:\s*(.*?)\s*简介:\s*(.*)/;
+        let match = resultStr.match(pattern);
+
+        if (match) {
+          let gushi: any = {}
+          gushi.title = match[1];
+          gushi.content = match[2];
+          gushi.intro = match[3];
+          gushi.source = "AI创作";
+          console.log(`题目: ${gushi.title}`);
+          console.log(`内容: ${gushi.content}`);
+          console.log(`简介: ${gushi.intro}`);
+          console.log(gushi);
+          let Shige = Parse.Object.extend("Shige");
+          let sg = new Shige();
+          sg.set(gushi);
+          sg.save();
+        } else {
+          console.log("未能匹配到任何内容");
+        }
+      }
+    });
+
+  }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}

+ 52 - 3
src/app/tab2/tab2.page.html

@@ -1,7 +1,10 @@
+
 <ion-header>
-  <ion-toolbar>
-    <ion-title>文库</ion-title>
+  <!-- <ion-toolbar>
+    <ion-title></ion-title>
   </ion-toolbar>
+  <ion-searchbar placeholder="诗词歌赋、作者、风格" class="antique-search-bar">
+  </ion-searchbar>
   <ion-segment (ionChange)="segmentChanged($event)">
     <ion-segment-button value="categories">
       <ion-label>分类</ion-label>
@@ -9,7 +12,28 @@
     <ion-segment-button value="works">
       <ion-label>作品</ion-label>
     </ion-segment-button>
-  </ion-segment>
+  </ion-segment> -->
+  <ion-toolbar class="custom-toolbar">
+    <!-- <ion-searchbar placeholder="诗词歌赋,作者,姓名" class="custom-searchbar"></ion-searchbar> -->
+    <ion-searchbar placeholder="诗词歌赋,作者,姓名" (ionBlur)="results=[]" [debounce]="1000" (ionInput)="search($event)" class="custom-searchbar"></ion-searchbar> 
+    <ion-list class="list" *ngIf="results.length > 0">
+      <ion-item *ngFor="let result of results">
+          <ion-label>{{ result?.get("title") }} {{result?.get("author")}}</ion-label>
+      </ion-item>
+  </ion-list>
+  
+    <ion-segment [(ngModel)]="selectedSegment" (ionChange)="segmentChanged($event)">  
+      <ion-segment-button value="categories" checked>  
+        <ion-label>分类</ion-label>  
+      </ion-segment-button>  
+      <ion-segment-button value="works">  
+        <ion-label>作品</ion-label>  
+      </ion-segment-button>  
+      
+    </ion-segment>  
+  </ion-toolbar>
+
+
 </ion-header>
 
     <ion-content>
@@ -37,6 +61,7 @@
             </ion-select>
           </ion-item>
           <ion-item>
+
             <ion-label>作者</ion-label>
             <ion-select [(ngModel)]="selectedAuthor">
               <ion-select-option *ngFor="let author of authors" [value]="author">{{ author }}</ion-select-option>
@@ -53,4 +78,28 @@
           </ion-list>
         </div>
       </div>
+      <ion-card>
+        <img src="assets/icon/仇英 柳下眠琴图轴局部.jpg" alt="仇英 柳下眠琴图轴局部">
+        <ion-card-content>
+          <ion-card-subtitle>仇英 柳下眠琴图轴局部</ion-card-subtitle>
+          <ion-card-title>君子之学进于道,小人之学进于利。</ion-card-title>
+        </ion-card-content>
+      </ion-card> 
+      <div *ngFor="let poetry of poetries; let i = index; let isLast = last">
+        <ion-card>
+          <ion-card-header>
+            <ion-card-title>
+              <strong>{{ poetry.title }}</strong>
+            </ion-card-title>
+            <ion-card-subtitle>{{ poetry.author }}</ion-card-subtitle>
+          </ion-card-header>
+          <ion-card-content>
+            <p>{{ poetry.content }}</p>
+          </ion-card-content>
+          <div class="icon-container" >
+            <ion-icon name="share-outline"></ion-icon>
+            <ion-icon name="bookmark-outline"></ion-icon>
+          </div>
+        </ion-card>
+      </div>                                                                 
     </ion-content>

+ 116 - 9
src/app/tab2/tab2.page.scss

@@ -1,14 +1,121 @@
 ion-card {
-    text-align: center;
+  text-align: center;
+}
+// ion-toolbar{
+//   text-align: center;
+//   background:#D2B48C;
+// }
+ion-card-content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+ion-icon {
+  font-size: 2em;
+  margin-bottom: 0.5em;
+}
+// .custom-toolbar{
+//   background: #f7b824; /* 设置ion-toolbar背景颜色为#FCE8B9 */
+// }
+ion-toolbar{
+  --background:#faf8ec; /* 设置ion-toolbar背景颜色为#faf8ec */
+  
+}
+ion-searchbar.custom-searchbar {
+  padding-top: 30px;
+  --background: #ffffff; /* 设置搜索框内部背景颜色为白色 */
+  // background:#faf8ec;
+
+  margin: 0%;
+  padding-bottom: 10px;
+}
+
+ion-segment {
+
+  ion-segment-button::part(indicator-background) {
+    background: #dbab56;
+  }
+  
+  /* Material Design styles */
+  ion-segment-button.md::part(native) {
+    color: #000;
+  }
+  
+  .segment-button-checked.md::part(native) {
+    color: #dbab56;
+  }
+  
+  ion-segment-button.md::part(indicator-background) {
+    height: 4px;
+  }
+  
+  /* iOS styles */
+  ion-segment-button.ios::part(native) {
+    color: #dbab56;
   }
   
-  ion-card-content {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
+  .segment-button-checked.ios::part(native) {
+    color: #fff;
   }
   
-  ion-icon {
-    font-size: 2em;
-    margin-bottom: 0.5em;
-  }
+  ion-segment-button.ios::part(indicator-background) {
+    border-radius: 20px;
+  }
+}
+
+ion-card {
+  max-width: 90%; /* 设置卡片最大宽度为屏幕宽度的80% */
+  margin: 20px auto;
+}
+
+img {
+  width: 100%; /* 图片宽度设置为父元素宽度的100% */
+  height: auto;
+}
+ion-card {
+  margin: 10px;
+  padding: 10px;
+}
+
+ion-card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+ion-card-title strong {
+  margin-right: 10px;
+}
+
+ion-card-subtitle {
+  font-size: 0.85em;
+  color: #666;
+}
+
+p {
+  white-space: pre-wrap; /* Preserve line breaks in the poem content */
+}
+
+ion-card-content {
+  position: relative; /* 使子元素可以相对于卡片内容定位 */
+  padding-bottom: 50px; /* 增加底部内边距 */
+}
+
+/* 图标容器样式 */
+.icon-container {
+  position: absolute; /* 绝对定位相对于卡片内容 */
+  left: 0; /* 定位到左下角 */
+  bottom: 0; /* 定位到底部 */
+  display: flex; /* 使用 Flexbox 布局 */
+  align-items: center; /* 垂直居中对齐图标 */
+  justify-content: center; /* 水平居中对齐图标 */
+  gap: 10px; /* 图标之间的间隔 */
+  padding: 5px; /* 给图标添加一些内边距 */
+}
+
+/* 可以为图标添加一些样式,如大小和颜色 */
+ion-icon {
+  font-size: 20px; /* 图标大小 */
+  color: #666; /* 图标颜色 */
+}

+ 51 - 1
src/app/tab2/tab2.page.ts

@@ -1,10 +1,15 @@
 import { Component,OnInit } from '@angular/core';
-
+"assets"; [
+  "src/favicon.ico",
+  "src/assets"
+]
+import Parse from "parse";
 @Component({
   selector: 'app-tab2',
   templateUrl: 'tab2.page.html',
   styleUrls: ['tab2.page.scss']
 })
+
 export class Tab2Page implements OnInit {
   selectedSegment: string = 'categories';
   categories: any[] = [
@@ -39,4 +44,49 @@ export class Tab2Page implements OnInit {
              (!this.selectedAuthor || poem.author === this.selectedAuthor);
     });
   }
+ poetries = [
+    {
+      title: '南乡子·登京口北固亭有怀',
+      author: '辛弃疾【宋代】',
+      content: '何处望神州?满眼风光北固楼。干古兴亡多少事?悠悠。不尽长江滚滚流。年少万兜整,坐断东南战未休。天下英雄谁敌手?曹刘。生子当如孙仲谋。'
+    },
+    {
+      title: '菩萨蛮·书江西造口壁',
+      author: '辛弃疾【宋代】',
+      content: '郁孤台下清江水,中间多少行人泪。可无数山。'
+    }
+    // Add more poems as needed
+  ];
+
+  isLastPoetry(poetry: any): boolean {
+    return poetry === this.poetries[this.poetries.length - 1];
+  }
+
+
+
+  results:Parse.Object[] = []
+  segment = 'tang';  
+  search(event: any) {  
+   console.log('Searching for:', event.detail.value);  
+   if(event?.detail?.value){
+     this.loadShigeList(event?.detail?.value)
+   }
+ }  
+ async loadShigeList(search:string){
+   let query = new Parse.Query("Shige");
+   query.select("title");
+   query.contains("title",search);
+   query.limit(5);
+   this.results = await query.find();
+ }
+
+
+
+
+
+
+
+
+
+
 }

+ 2 - 2
src/app/tabs/tabs-routing.module.ts

@@ -20,8 +20,8 @@ const routes: Routes = [
         loadChildren: () => import('../tab3/tab3.module').then(m => m.Tab3PageModule)
       },
       {
-        path: 'listenbook',
-        loadChildren: () => import('../listenbook/listenbook.module').then( m => m.ListenbookPageModule)
+        path: 'pocircle',
+        loadChildren: () => import('../pocircle/pocircle.module').then( m => m.PocirclePageModule)
       },
       {
         path: '',

File diff suppressed because it is too large
+ 18 - 1
src/app/tabs/tabs.page.html


Some files were not shown because too many files changed in this diff