林财明 10 сар өмнө
parent
commit
1bc6a45739

+ 5 - 1
CraftsMart-angular/package.json

@@ -40,5 +40,9 @@
     "karma-jasmine": "~5.1.0",
     "karma-jasmine-html-reporter": "~2.1.0",
     "typescript": "~5.1.3"
-  }
+  },
+  "description": "This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 16.2.2.",
+  "main": "index.js",
+  "author": "",
+  "license": "ISC"
 }

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

@@ -3,6 +3,7 @@ import { RouterModule, Routes } from '@angular/router';
 import { HomeComponent } from 'src/modules/craftsmart/home/home.component';
 import { NavTabsComponent } from 'src/modules/craftsmart/nav-tabs/nav-tabs.component';
 import { PageCartComponent } from 'src/modules/craftsmart/page-cart/page-cart.component';
+import { PageChatPanelComponent } from 'src/modules/craftsmart/page-chat-panel/page-chat-panel.component';
 import { PageItemDetailComponent } from 'src/modules/craftsmart/page-item-detail/page-item-detail.component';
 import { PageMineComponent } from 'src/modules/craftsmart/page-mine/page-mine.component';
 
@@ -14,6 +15,7 @@ const routes: Routes = [
    { path: 'page-cart', component: PageCartComponent },
    { path: 'page-mine', component: PageMineComponent },
    {path:'page-item-detail/:name',component:PageItemDetailComponent},
+   {path:'page-chat-panel',component:PageChatPanelComponent}
 ];
 
 @NgModule({

+ 1 - 0
CraftsMart-angular/src/app/app.module.ts

@@ -13,6 +13,7 @@ import { NavTabsComponent } from 'src/modules/craftsmart/nav-tabs/nav-tabs.compo
 import { NgModule ,CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
 import { PageDiscoverComponent } from 'src/modules/craftsmart/page-discover/page-discover.component';
 
+
 const routes: Routes = [
   { path: 'home', component: HomeComponent },
   { path: 'cart', component: PageCartComponent },

+ 99 - 0
CraftsMart-angular/src/modules/craftsmart/class-chat-completion.ts

@@ -0,0 +1,99 @@
+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": "gpt-3.5-turbo",
+  "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:\ ","")
+    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);
+  }
+}
+}
+}

+ 3 - 1
CraftsMart-angular/src/modules/craftsmart/craftsmart-routing.module.ts

@@ -7,6 +7,7 @@ import { NavTabsComponent } from './nav-tabs/nav-tabs.component';
 import { PageDiscoverComponent } from './page-discover/page-discover.component';
 import { PageItemDetailComponent } from './page-item-detail/page-item-detail.component';
 import { authGuard } from '../user/auth.guard';
+import { PageChatPanelComponent } from './page-chat-panel/page-chat-panel.component';
 
 const routes: Routes = [
   {
@@ -16,7 +17,8 @@ const routes: Routes = [
       { path:"page-cart", component:PageCartComponent },
       { path:"page-mine", component:PageMineComponent },
       { path:"page-discover", component:PageDiscoverComponent },
-      { path:"page-item-detail/:name", component:PageItemDetailComponent }
+      { path:"page-item-detail/:name", component:PageItemDetailComponent },
+      {path:"page-chat-panel",component:PageChatPanelComponent},
     ]
   },
   { path: 'detail', component: PageItemDetailComponent, canActivate: [authGuard] },

+ 5 - 1
CraftsMart-angular/src/modules/craftsmart/craftsmart.module.ts

@@ -8,7 +8,8 @@ import { PageItemDetailComponent } from './page-item-detail/page-item-detail.com
 import { IonicModule } from '@ionic/angular';
 import { PageMineComponent } from './page-mine/page-mine.component';
 import { HomeComponent } from './home/home.component';
-
+import { PageChatPanelComponent } from './page-chat-panel/page-chat-panel.component';
+import { FormsModule } from '@angular/forms';
 
 @NgModule({
   declarations: [
@@ -17,6 +18,7 @@ import { HomeComponent } from './home/home.component';
     PageItemDetailComponent,
     PageMineComponent,
     HomeComponent,
+    PageChatPanelComponent,
     
   ],
   imports: [
@@ -24,6 +26,8 @@ import { HomeComponent } from './home/home.component';
     RouterModule,
     CraftsmartRoutingModule,
     IonicModule,
+    FormsModule
+
   ],
   exports:[
     PageCartComponent,

+ 7 - 7
CraftsMart-angular/src/modules/craftsmart/page-cart/page-cart.component.html

@@ -13,29 +13,29 @@
 </div>
 
 <div class="content-wrapper">
-  <div class="item-container">
+  <div class="item-container" >
     <div *ngFor="let item of items" class="image-container">
-      <div *ngIf="item.choice === 1" class="left-column">
+      <div *ngIf="item.choice === 1" class="left-column" >
         <div class="image-item">
           <img [src]="item.imgUrl" alt="item image">
           <div class="image-details">
             <h3>{{ item.name }}</h3>
           </div>
           <div class="price-container">
-            <p>价格:{{ item.price }}</p>
-            <p>销量{{ item.sales }}</p>
+            <p class="price">¥{{ item.price }}</p>
+            <p class="sales">销量{{ item.sales }}</p>
           </div>
         </div>
       </div>
-      <div *ngIf="item.choice === 2" class="right-column">
+      <div *ngIf="item.choice === 2"class="right-column" >
         <div class="image-item">
           <img [src]="item.imgUrl" alt="item image">
           <div class="image-details">
             <h3>{{ item.name }}</h3>
           </div>
           <div class="price-container">
-            <p>价格:{{ item.price }}</p>
-            <p>销量{{ item.sales }}</p>
+            <p class="price">¥{{ item.price }}</p>
+            <p class="sales">销量{{ item.sales }}</p>
           </div>
         </div>
       </div>

+ 3 - 3
CraftsMart-angular/src/modules/craftsmart/page-cart/page-cart.component.scss

@@ -67,7 +67,7 @@
               font-size: 18px;
             }
             .sales{
-              margin:0 10px 5px 0 ;
+              margin:-2px 10px 5px 0 ;
               padding-top: 6px;
               color: #787878;
               font-size: 14px;
@@ -109,8 +109,8 @@
               font-size: 18px;
             }
             .sales{
-              margin:0 10px 5px 0 ;
-              padding-top: 6px;
+              margin:-2px 10px 5px 0 ;
+              padding-top: 4px;
               color: #787878;
               font-size: 14px;
             }

+ 50 - 0
CraftsMart-angular/src/modules/craftsmart/page-chat-panel/page-chat-panel.component.html

@@ -0,0 +1,50 @@
+<div class="navigation-bar">
+    <div>
+        <button class="back-button" (click)="backIconClicked()">
+            <svg t="1699446776660" class="back-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2306" width="128" height="128"><path d="M532.526499 904.817574L139.506311 511.797385 532.526499 118.777197c12.258185-12.258185 12.432147-32.892131-0.187265-45.51052-12.707416-12.707416-32.995485-12.703323-45.511543-0.187265L75.166957 484.739123c-7.120165 7.120165-10.163477 17.065677-8.990768 26.624381-1.500167 9.755178 1.5104 20.010753 8.990768 27.491121l411.660734 411.660734c12.258185 12.258185 32.892131 12.432147 45.511543-0.187265 12.707416-12.707416 12.7023-32.995485 0.187265-45.51052z" p-id="2307" fill="#2c2c2c"></path></svg>
+         </button>
+         <button class="share-button">
+            <svg t="1699446835212" class="share-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3541" width="128" height="128"><path d="M874.9 459.4c-18.8 0-34 15.2-34 34v355.7c0 18.6-15.5 33.7-34.5 33.7H181.5c-19 0-34.5-15.1-34.5-33.7V232.3c0-18.6 15.5-33.7 34.5-33.7H541c18.8 0 34-15.2 34-34s-15.2-34-34-34H181.5C125 130.6 79 176.2 79 232.3v616.8c0 56 46 101.7 102.5 101.7h624.9c56.5 0 102.5-45.6 102.5-101.7V493.4c0-18.8-15.2-34-34-34z" fill="#2c2c2c" p-id="3542"></path><path d="M885.5 82.7H657.1c-18.8 0-34 15.2-34 34s15.2 34 34 34h169.7L358.5 619.1c-13.3 13.3-13.3 34.8 0 48.1 6.6 6.6 15.3 10 24 10s17.4-3.3 24-10l470-470v169.7c0 18.8 15.2 34 34 34s34-15.2 34-34V141.5c0.1-32.4-26.4-58.8-59-58.8z" fill="#2c2c2c" p-id="3543"></path></svg>
+         </button>
+    </div>
+</div>
+
+<div class="page">
+    <div class="leftnav col" *ngIf="false">
+        <div class="avatar row">头像</div>
+
+        <div class="tablist row">
+            <div class="tab-button">消息</div>
+            <div class="tab-button">邮件</div>
+            <div class="tab-button">文档</div>
+        </div>
+
+        <div class="footer row">
+            <div class="tab-button">设置</div>
+        </div>
+
+    </div>
+
+    <div class="chatlist col" *ngIf="false">
+
+    </div>
+
+    <div class="chatbox col">
+        <div class="msglist">
+            <ng-container *ngFor="let msg of messageList">
+                <div class="msgbox">
+                    {{msg?.content}}
+                </div>
+            </ng-container>
+        </div>
+        <!-- 底部:用户输入 -->
+        <div class="footer">
+            <ion-item>
+                <ion-textarea  [(ngModel)]="userInput"
+                 labelPlacement="floating"
+                 label="请输入:" placeholder="提示词"></ion-textarea>
+                 <ion-button (click)="send()">发送</ion-button>
+            </ion-item>
+        </div>
+    </div>
+</div>

+ 106 - 0
CraftsMart-angular/src/modules/craftsmart/page-chat-panel/page-chat-panel.component.scss

@@ -0,0 +1,106 @@
+.navigation-bar {
+    align-items: center;
+    height: 50px;
+    padding: 10px;
+    justify-content: space-between; /* 使用 space-between 实现按钮左右对齐 */
+    border-bottom:1px solid #807b7b ;
+    
+  
+    button.back-button {
+      width: 30px;
+      height: 30px;
+      padding: 4px 0 4px 4px;
+      border: none;
+      background-color: transparent;
+      cursor: pointer;
+  
+      .back-icon {
+        width: auto;
+        height: 20px;
+        transform-origin: center;
+        transition: transform 0.3s ease, border-color 0.3s ease;
+      }
+    }
+  
+    button.share-button {
+      width: 30px;
+      float:right;
+      height: 30px;
+      padding: 4px 0 4px 0;
+      border: none;
+      background-color: transparent;
+      cursor: pointer;
+  
+      .share-icon {
+        width: auto;
+        height: 20px;
+        transform-origin: center;
+      }
+    }
+  }
+
+  .footer {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    padding: 10px;
+    background-color: #f1f1f1;
+  }
+  
+
+  .chatlist {
+    flex: 1;
+    background-color: #f1f1f1;
+  }
+  
+  .chatbox {
+    flex: 3;
+    background-color: #fff;
+    display: flex;
+    flex-direction: column;
+  }
+  
+  .msglist {
+    flex: 1;
+    padding: 10px;
+    overflow-y: auto;
+  }
+  
+  .msgbox {
+    background-color: #f1f1f1;
+    padding: 10px;
+    margin-bottom: 10px;
+  }
+
+  .page {
+    display: flex;
+    height: 100vh;
+  }
+  
+  .leftnav {
+    width: 250px;
+    background-color: #f1f1f1;
+    display: flex;
+    flex-direction: column;
+  }
+  
+  .avatar {
+    height: 100px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  
+  .tablist {
+    display: flex;
+    flex-direction: column;
+    margin-top: 20px;
+  }
+  
+  .tab-button {
+    padding: 10px;
+    background-color: #ccc;
+    margin-bottom: 10px;
+  }
+  

+ 21 - 0
CraftsMart-angular/src/modules/craftsmart/page-chat-panel/page-chat-panel.component.spec.ts

@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PageChatPanelComponent } from './page-chat-panel.component';
+
+describe('PageChatPanelComponent', () => {
+  let component: PageChatPanelComponent;
+  let fixture: ComponentFixture<PageChatPanelComponent>;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      declarations: [PageChatPanelComponent]
+    });
+    fixture = TestBed.createComponent(PageChatPanelComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 33 - 0
CraftsMart-angular/src/modules/craftsmart/page-chat-panel/page-chat-panel.component.ts

@@ -0,0 +1,33 @@
+import { Component } from '@angular/core';
+import { TestChatCompletion,TestChatMessage } from '../class-chat-completion';
+import { Router } from '@angular/router';
+
+@Component({
+  selector: 'app-page-chat-panel',
+  templateUrl: './page-chat-panel.component.html',
+  styleUrls: ['./page-chat-panel.component.scss']
+})
+export class PageChatPanelComponent {
+  messageList:Array<TestChatMessage> = []
+  userInput:string = " "
+
+  
+  
+  completion:TestChatCompletion
+  constructor(private router: Router){
+    this.completion = new TestChatCompletion(this.messageList);
+
+  }
+  send(){
+    this.messageList.push({
+      role:"user",
+      content: this.userInput
+    })
+    this.userInput = ""
+    this.completion.createCompletionByStream()
+  }
+
+  backIconClicked() {
+    this.router.navigate(['/discover']);
+}
+}

+ 2 - 2
CraftsMart-angular/src/modules/craftsmart/page-discover/page-discover.component.html

@@ -6,8 +6,8 @@
             <p>消息中心</p>
             <div class="lists"><svg t="1699961826176" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3157" width="128" height="128"><path d="M345.642667 822.592c12.629333 12.544 33.130667 12.544 45.76 0L678.613333 536.384c6.741333-6.698667 9.6-15.573333 9.173333-24.384 0.448-8.768-2.410667-17.664-9.173333-24.384L391.402667 201.429333c-12.629333-12.565333-33.130667-12.565333-45.76 0s-12.629333 32.981333 0 45.546667L611.648 512 345.642667 777.045333C333.013333 789.632 333.013333 810.005333 345.642667 822.592z" p-id="3158" fill="#2c2c2c"></path></svg></div>
         </div>
-    <div class="list" >
-            <p>AI咨询</p>
+    <div class="list" (click)="goToChatPanel()">
+            <p>AI咨询 (Active)</p>
             <div class="lists"><svg t="1699961826176" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3157" width="128" height="128"><path d="M345.642667 822.592c12.629333 12.544 33.130667 12.544 45.76 0L678.613333 536.384c6.741333-6.698667 9.6-15.573333 9.173333-24.384 0.448-8.768-2.410667-17.664-9.173333-24.384L391.402667 201.429333c-12.629333-12.565333-33.130667-12.565333-45.76 0s-12.629333 32.981333 0 45.546667L611.648 512 345.642667 777.045333C333.013333 789.632 333.013333 810.005333 345.642667 822.592z" p-id="3158" fill="#2c2c2c"></path></svg></div>
         </div>
     <div class="list">

+ 5 - 0
CraftsMart-angular/src/modules/craftsmart/page-discover/page-discover.component.ts

@@ -1,4 +1,5 @@
 import { Component } from '@angular/core';
+import { Router } from '@angular/router';
 
 @Component({
   selector: 'app-page-discover',
@@ -6,5 +7,9 @@ import { Component } from '@angular/core';
   styleUrls: ['./page-discover.component.scss']
 })
 export class PageDiscoverComponent {
+  constructor(private router: Router) {}
 
+  goToChatPanel() {
+    this.router.navigate(['/page-chat-panel']);
+  }
 }

+ 0 - 1
CraftsMart-angular/src/modules/craftsmart/page-mine/page-mine.component.html

@@ -11,7 +11,6 @@
   <ion-list [inset]="true">
     <!-- 其他代码 -->
   </ion-list>
-
   
   <ion-list [inset]="true"  class="zoom-list">
     <ion-item [button]="true">

+ 11 - 0
CraftsMart-angular/testthing.js

@@ -0,0 +1,11 @@
+const express = require('express')
+const app = express()
+const port = 3000
+
+app.get('/', (req, res) => {
+  res.send('Hello World!')
+})
+
+app.listen(port, () => {
+  console.log(`Example app listening on port ${port}`)
+})