15270821319 7 miesięcy temu
rodzic
commit
687b0629ce

Plik diff jest za duży
+ 639 - 15
AiStudy-app/package-lock.json


+ 2 - 0
AiStudy-app/package.json

@@ -27,7 +27,9 @@
     "@capacitor/keyboard": "6.0.3",
     "@capacitor/status-bar": "6.0.2",
     "@ionic/angular": "^8.0.0",
+    "fmode-ng": "^0.0.62",
     "ionicons": "^7.2.1",
+    "parse": "^5.3.0",
     "rxjs": "~7.8.0",
     "tslib": "^2.3.0",
     "zone.js": "~0.14.2"

+ 13 - 0
AiStudy-app/src/app/app.config.ts

@@ -0,0 +1,13 @@
+import { ApplicationConfig } from '@angular/core';
+import { provideRouter } from '@angular/router';
+import { routes } from './app.routes';
+import { IonicModule } from '@ionic/angular';
+import { provideHttpClient } from '@angular/common/http';
+
+export const appConfig: ApplicationConfig = {
+  providers: [
+    provideRouter(routes),
+    provideHttpClient(),
+    { provide: IonicModule, useFactory: () => IonicModule.forRoot() }
+  ]
+}; 

+ 33 - 0
AiStudy-app/src/app/services/api.service.ts

@@ -0,0 +1,33 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable } from 'rxjs';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class ApiService {
+  // API基础URL
+  private baseUrl = 'http://your-api-base-url';
+
+  constructor(private http: HttpClient) { }
+
+  // GET请求示例
+  getData(): Observable<any> {
+    return this.http.get(`${this.baseUrl}/endpoint`);
+  }
+
+  // POST请求示例
+  postData(data: any): Observable<any> {
+    return this.http.post(`${this.baseUrl}/endpoint`, data);
+  }
+
+  // PUT请求示例
+  updateData(id: string, data: any): Observable<any> {
+    return this.http.put(`${this.baseUrl}/endpoint/${id}`, data);
+  }
+
+  // DELETE请求示例
+  deleteData(id: string): Observable<any> {
+    return this.http.delete(`${this.baseUrl}/endpoint/${id}`);
+  }
+}

+ 26 - 11
AiStudy-app/src/app/tab1/tab1.page.html

@@ -1,17 +1,32 @@
 <ion-header [translucent]="true">
   <ion-toolbar>
-    <ion-title>
-      对话
-    </ion-title>
+    <ion-title>对话</ion-title>
   </ion-toolbar>
 </ion-header>
 
-<ion-content [fullscreen]="true">
-  <ion-header collapse="condense">
-    <ion-toolbar>
-      <ion-title size="large">Tab 1</ion-title>
-    </ion-toolbar>
-  </ion-header>
-
-  <app-explore-container name="Tab 1 page"></app-explore-container>
+<ion-content [fullscreen]="true" class="ion-padding">
+  <!-- 聊天消息区域 -->
+  <div class="chat-container">
+    <div *ngFor="let message of messages" [ngClass]="{'user-message': message.isUser, 'ai-message': !message.isUser}" class="message-wrapper">
+      <div class="message-bubble">
+        {{ message.content }}
+      </div>
+    </div>
+  </div>
 </ion-content>
+
+<!-- 底部输入区域 -->
+<ion-footer>
+  <ion-toolbar>
+    <ion-item>
+      <ion-input 
+        [(ngModel)]="userInput" 
+        placeholder="请输入消息..." 
+        (keyup.enter)="sendMessage()"
+      ></ion-input>
+      <ion-button slot="end" (click)="sendMessage()" [disabled]="!userInput">
+        <ion-icon name="send"></ion-icon>
+      </ion-button>
+    </ion-item>
+  </ion-toolbar>
+</ion-footer>

+ 82 - 0
AiStudy-app/src/app/tab1/tab1.page.scss

@@ -0,0 +1,82 @@
+.chat-container {
+  display: flex;
+  flex-direction: column;
+  padding: 10px;
+  padding-bottom: 60px;
+  height: 100%;
+  overflow-y: auto;
+  scroll-behavior: smooth;
+}
+
+.message-wrapper {
+  display: flex;
+  margin: 5px 0;
+  
+  &.user-message {
+    justify-content: flex-end;
+  }
+  
+  &.ai-message {
+    justify-content: flex-start;
+  }
+}
+
+.message-bubble {
+  max-width: 70%;
+  padding: 10px 15px;
+  border-radius: 15px;
+  word-wrap: break-word;
+}
+
+.user-message .message-bubble {
+  background-color: #007aff;
+  color: white;
+}
+
+.ai-message .message-bubble {
+  background-color: #e5e5ea;
+  color: black;
+}
+
+ion-split-pane {
+  --side-width: 300px;
+  --side-max-width: 300px;
+}
+
+ion-menu {
+  --width: 300px;
+  --max-width: 300px;
+}
+
+ion-item.selected {
+  --background: var(--ion-color-light);
+}
+
+ion-item {
+  --padding-start: 16px;
+  --padding-end: 16px;
+  --padding-top: 8px;
+  --padding-bottom: 8px;
+  
+  h3 {
+    font-size: 16px;
+    font-weight: 500;
+    margin-bottom: 4px;
+  }
+  
+  p {
+    color: var(--ion-color-medium);
+    font-size: 14px;
+    margin: 0;
+  }
+  
+  small {
+    color: var(--ion-color-medium);
+    font-size: 12px;
+  }
+}
+
+// 确保消息不会被输入框遮挡
+ion-content {
+  --padding-bottom: 70px;
+}

+ 94 - 5
AiStudy-app/src/app/tab1/tab1.page.ts

@@ -1,14 +1,103 @@
 import { Component } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/angular/standalone';
-import { ExploreContainerComponent } from '../explore-container/explore-container.component';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonFooter, IonItem, IonInput, IonButton, IonIcon, IonSpinner } from '@ionic/angular/standalone';
+import { FormsModule } from '@angular/forms';
+import { NgClass, NgFor, NgIf } from '@angular/common';
+import { addIcons } from 'ionicons';
+import { send } from 'ionicons/icons';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import Parse from 'parse';
+
+// 定义API响应类型
+interface ChatResponse {
+  reply: string;
+  [key: string]: any;
+}
+
+interface ChatMessage {
+  content: string;
+  isUser: boolean;
+}
 
 @Component({
   selector: 'app-tab1',
   templateUrl: 'tab1.page.html',
   styleUrls: ['tab1.page.scss'],
   standalone: true,
-  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent],
+  imports: [
+    IonHeader, 
+    IonToolbar, 
+    IonTitle, 
+    IonContent, 
+    IonFooter,
+    IonItem,
+    IonInput,
+    IonButton,
+    IonIcon,
+    IonSpinner,
+    FormsModule,
+    NgClass,
+    NgFor,
+    NgIf
+  ],
 })
 export class Tab1Page {
-  constructor() {}
-}
+  messages: ChatMessage[] = [];
+  userInput: string = '';
+  isLoading: boolean = false;
+
+  constructor(private http: HttpClient) {
+    addIcons({ send });
+  }
+
+  async sendMessage() {
+    if (this.userInput.trim() && !this.isLoading) {
+      this.isLoading = true;
+
+      // 添加用户消息
+      this.messages.push({
+        content: this.userInput,
+        isUser: true
+      });
+
+      // 准备AI回复占位
+      this.messages.push({
+        content: '',
+        isUser: false
+      });
+
+      try {
+        // 使用直接的HTTP请求
+        const headers = new HttpHeaders({
+          'X-Parse-Application-Id': 'ncloudmaster',
+          'X-Parse-Session-Token': Parse.User.current()?.getSessionToken() || '',
+          'Content-Type': 'application/json'
+        });
+
+        const response = await this.http.post<ChatResponse>(
+          'https://server.fmode.cn/api/apig/chat',
+          { message: this.userInput },
+          { headers }
+        ).toPromise();
+
+        console.log('API Response:', response);
+
+        // 更新AI回复
+        if (this.messages.length > 0 && response) {
+          const aiMessage = this.messages[this.messages.length - 1];
+          aiMessage.content = response.reply || '抱歉,我没有收到有效的回复。';
+        }
+
+      } catch (error) {
+        console.error('Chat Error:', error);
+        
+        // 显示错误消息
+        if (this.messages.length > 0) {
+          this.messages[this.messages.length - 1].content = '抱歉,发生了一些错误,请稍后再试。';
+        }
+      } finally {
+        this.isLoading = false;
+        this.userInput = ''; // 清空输入框
+      }
+    }
+  }
+}

+ 75 - 7
AiStudy-app/src/app/tab2/tab2.page.html

@@ -6,12 +6,80 @@
   </ion-toolbar>
 </ion-header>
 
-<ion-content [fullscreen]="true">
-  <ion-header collapse="condense">
-    <ion-toolbar>
-      <ion-title size="large">Tab 2</ion-title>
-    </ion-toolbar>
-  </ion-header>
+<ion-content [fullscreen]="true" class="ion-padding">
+  <!-- 通知中心 -->
+  <ion-card class="notification-card">
+    <ion-item lines="none">
+      <ion-icon name="notifications" slot="start" color="primary"></ion-icon>
+      <ion-label>
+        <h2>通知中心</h2>
+        <p *ngIf="notifications.length > 0">{{notifications[0].content}}</p>
+        <p *ngIf="notifications.length === 0">暂无新通知</p>
+      </ion-label>
+      <ion-badge slot="end" *ngIf="notifications.length > 0">{{notifications.length}}</ion-badge>
+    </ion-item>
+  </ion-card>
 
-  <app-explore-container name="Tab 2 page"></app-explore-container>
+  <!-- 主要功能网格 -->
+  <ion-grid>
+    <ion-row>
+      <!-- 个性化学习设计 -->
+      <ion-col size="6">
+        <ion-card class="feature-card" (click)="navigateToFeature('learning-design')">
+          <ion-card-content class="ion-text-center">
+            <ion-icon name="bulb" color="warning"></ion-icon>
+            <h3>个性化学习设计</h3>
+            <p>定制你的学习风格</p>
+          </ion-card-content>
+        </ion-card>
+      </ion-col>
+      
+      <!-- 学习概览 -->
+      <ion-col size="6">
+        <ion-card class="feature-card" (click)="navigateToFeature('learning-overview')">
+          <ion-card-content class="ion-text-center">
+            <ion-icon name="bar-chart" color="success"></ion-icon>
+            <h3>学习概览</h3>
+            <p>查看学习进度</p>
+          </ion-card-content>
+        </ion-card>
+      </ion-col>
+      
+      <!-- 互动练习 -->
+      <ion-col size="6">
+        <ion-card class="feature-card" (click)="navigateToFeature('interactive-practice')">
+          <ion-card-content class="ion-text-center">
+            <ion-icon name="people" color="tertiary"></ion-icon>
+            <h3>互动练习</h3>
+            <p>与AI互动学习</p>
+          </ion-card-content>
+        </ion-card>
+      </ion-col>
+      
+      <!-- 收藏题库 -->
+      <ion-col size="6">
+        <ion-card class="feature-card" (click)="navigateToFeature('favorites')">
+          <ion-card-content class="ion-text-center">
+            <ion-icon name="star" color="warning"></ion-icon>
+            <h3>收藏题库</h3>
+            <p>复习重点内容</p>
+          </ion-card-content>
+        </ion-card>
+      </ion-col>
+    </ion-row>
+  </ion-grid>
+
+  <!-- 学习进度概览 -->
+  <ion-card class="progress-card">
+    <ion-card-header>
+      <ion-card-title>今日学习进度</ion-card-title>
+    </ion-card-header>
+    <ion-card-content>
+      <ion-progress-bar [value]="dailyProgress"></ion-progress-bar>
+      <div class="progress-stats">
+        <span>已完成: {{completedTasks}}/{{totalTasks}}</span>
+        <span>{{(dailyProgress * 100).toFixed(0)}}%</span>
+      </div>
+    </ion-card-content>
+  </ion-card>
 </ion-content>

+ 73 - 0
AiStudy-app/src/app/tab2/tab2.page.scss

@@ -0,0 +1,73 @@
+.notification-card {
+  margin-bottom: 16px;
+  border-radius: 12px;
+  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+  
+  ion-item {
+    --padding-start: 16px;
+    --padding-end: 16px;
+  }
+}
+
+.feature-card {
+  height: 100%;
+  margin: 0;
+  border-radius: 12px;
+  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+  cursor: pointer;
+  transition: transform 0.2s;
+
+  &:active {
+    transform: scale(0.98);
+  }
+
+  ion-card-content {
+    padding: 16px;
+    
+    ion-icon {
+      font-size: 32px;
+      margin-bottom: 8px;
+    }
+
+    h3 {
+      margin: 8px 0;
+      font-size: 16px;
+      font-weight: 500;
+    }
+
+    p {
+      margin: 0;
+      font-size: 12px;
+      color: var(--ion-color-medium);
+    }
+  }
+}
+
+.progress-card {
+  margin-top: 16px;
+  border-radius: 12px;
+  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+
+  ion-card-header {
+    padding: 16px;
+  }
+
+  ion-card-content {
+    padding: 16px;
+  }
+
+  .progress-stats {
+    display: flex;
+    justify-content: space-between;
+    margin-top: 8px;
+    font-size: 14px;
+    color: var(--ion-color-medium);
+  }
+}
+
+ion-progress-bar {
+  height: 8px;
+  border-radius: 4px;
+  --progress-background: var(--ion-color-primary);
+  --buffer-background: rgba(var(--ion-color-primary-rgb), 0.2);
+}

+ 84 - 6
AiStudy-app/src/app/tab2/tab2.page.ts

@@ -1,16 +1,94 @@
-import { Component } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/angular/standalone';
-import { ExploreContainerComponent } from '../explore-container/explore-container.component';
+import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import { 
+  IonHeader, 
+  IonToolbar, 
+  IonTitle, 
+  IonContent,
+  IonCard,
+  IonCardContent,
+  IonCardHeader,
+  IonCardTitle,
+  IonGrid,
+  IonRow,
+  IonCol,
+  IonIcon,
+  IonItem,
+  IonLabel,
+  IonBadge,
+  IonProgressBar
+} from '@ionic/angular/standalone';
+import { NgIf } from '@angular/common';
+import { addIcons } from 'ionicons';
+import { 
+  notifications, 
+  bulb, 
+  barChart, 
+  people, 
+  star 
+} from 'ionicons/icons';
+
+interface Notification {
+  id: number;
+  content: string;
+  date: Date;
+}
 
 @Component({
   selector: 'app-tab2',
   templateUrl: 'tab2.page.html',
   styleUrls: ['tab2.page.scss'],
   standalone: true,
-  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent]
+  imports: [
+    IonHeader, 
+    IonToolbar, 
+    IonTitle, 
+    IonContent,
+    IonCard,
+    IonCardContent,
+    IonCardHeader,
+    IonCardTitle,
+    IonGrid,
+    IonRow,
+    IonCol,
+    IonIcon,
+    IonItem,
+    IonLabel,
+    IonBadge,
+    IonProgressBar,
+    NgIf
+  ]
 })
-export class Tab2Page {
+export class Tab2Page implements OnInit {
+  notifications: Notification[] = [];
+  dailyProgress: number = 0.65; // 示例进度
+  completedTasks: number = 13;
+  totalTasks: number = 20;
+
+  constructor(private router: Router) {
+    addIcons({ 
+      notifications, 
+      bulb, 
+      barChart, 
+      people, 
+      star 
+    });
+  }
 
-  constructor() {}
+  ngOnInit() {
+    // 模拟获取通知数据
+    this.notifications = [
+      {
+        id: 1,
+        content: '你有一个新的学习任务待完成',
+        date: new Date()
+      }
+    ];
+  }
 
+  navigateToFeature(feature: string) {
+    // 处理导航逻辑
+    console.log(`Navigating to ${feature}`);
+    // this.router.navigate([`/tabs/tab2/${feature}`]);
+  }
 }

+ 21 - 0
AiStudy-app/src/main.ts

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

+ 1 - 0
AiStudy-app/tsconfig.json

@@ -2,6 +2,7 @@
 {
   "compileOnSave": false,
   "compilerOptions": {
+    "allowSyntheticDefaultImports":true,
     "baseUrl": "./",
     "outDir": "./dist/out-tsc",
     "forceConsistentCasingInFileNames": true,

BIN
AiStudy-prod/4.png


BIN
AiStudy-prod/5.png


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików