flowaaa пре 1 година
родитељ
комит
d270e79b9b

+ 2 - 2
app-angular/src/app/app.component.html

@@ -10,9 +10,9 @@
             <ion-icon name="footsteps"></ion-icon>
             AI
         </ion-tab-button>
-      <ion-tab-button routerLink="/lesson/near">
+      <ion-tab-button routerLink="/lesson/lesson">
             <ion-icon name="chatbubbles"></ion-icon>
-            附近
+            禁忌
         </ion-tab-button>
         <ion-tab-button routerLink="/lesson/me">
             <ion-icon name="person-circle"></ion-icon>

+ 2 - 0
app-angular/src/modules/lesson/community/community-routing.module.ts

@@ -4,12 +4,14 @@ import { ShareComponent } from '../share/share.component';
 import { RecommendDetailComponent } from '../recommend-detail/recommend-detail.component';
 import { AttentionDetailComponent } from '../attention-detail/attention-detail.component';
 import { ScienceDetailComponent } from '../science-detail/science-detail.component';
+import { PageLessonDetailComponent } from '../page-lesson-detail/page-lesson-detail.component';
 
 const routes: Routes = [
     { path: "share", component: ShareComponent }, // 当路径为 "share" 时,加载 ShareComponent 组件
     { path: "recommend", component: RecommendDetailComponent }, // 当路径为 "recommend" 时,加载 RecommendDetailComponent 组件
     { path: "attention", component: AttentionDetailComponent }, // 当路径为 "attention" 时,加载 AttentionDetailComponent 组件
     { path: "science", component: ScienceDetailComponent }, // 当路径为 "science" 时,加载 ScienceDetailComponent 组件
+    { path: "lesson", component: PageLessonDetailComponent },
 ]
 
 @NgModule({

+ 2 - 4
app-angular/src/modules/lesson/community/community.module.ts

@@ -5,16 +5,14 @@ import { IonicModule } from '@ionic/angular';
 
 import { CommunityRoutingModule } from './community-routing.module';
 import { ScienceDetailComponent } from '../science-detail/science-detail.component';
-import { AttentionDetailComponent } from '../attention-detail/attention-detail.component';
-import { RecommendDetailComponent } from '../recommend-detail/recommend-detail.component';
+
 
 @NgModule({
 
     declarations: [
        
         ScienceDetailComponent,
-        // RecommendDetailComponent,
-        AttentionDetailComponent
+
     ],
     imports: [
         CommonModule,

+ 7 - 2
app-angular/src/modules/lesson/lesson-routing.module.ts

@@ -13,14 +13,19 @@ import { UserFollowComponent } from './user-follow/user-follow.component';
 import { UserTagComponent } from './user-tag/user-tag.component';
 import { UserCollectionComponent } from './user-collection/user-collection.component';
 import { PageChatComponent } from './page-chat/page-chat.component';
+import { authGuard } from '../user/guard-auth/auth.guard';
+import { PageLessonComponent } from './page-lesson/page-lesson.component';
+import { PageLessonDetailComponent } from './page-lesson-detail/page-lesson-detail.component';
 
 
 const routes: Routes = [
-  { path: 'me', component: MeComponent },
+  { path: 'me', component: MeComponent , canActivate: [authGuard]},
   { path: 'they', component: TheyComponent },
   { path: 'community', component: CommunityComponent },
   { path: 'near', component: NearComponent },
-  { path: 'page-chat', component: PageChatComponent },
+  { path: 'lesson', component: PageLessonComponent },
+  { path: 'lesson/detail', component: PageLessonDetailComponent },
+  { path: 'page-chat', component: PageChatComponent, canActivate: [authGuard] },
   { path: 'they/detail', component: TheyDetailComponent },
   { path: 'community/scienceDetail', component: ScienceDetailComponent },
   { path: 'community/share', component: ShareComponent },

+ 5 - 0
app-angular/src/modules/lesson/lesson.module.ts

@@ -17,6 +17,8 @@ import { UserFollowComponent } from './user-follow/user-follow.component';
 import { UserTagComponent } from './user-tag/user-tag.component';
 import { UserCollectionComponent } from './user-collection/user-collection.component';
 import { PageChatComponent } from './page-chat/page-chat.component';
+import { PageLessonDetailComponent } from './page-lesson-detail/page-lesson-detail.component';
+import { PageLessonComponent } from './page-lesson/page-lesson.component';
 
 @NgModule({
   declarations: [
@@ -33,6 +35,9 @@ import { PageChatComponent } from './page-chat/page-chat.component';
     UserTagComponent,
     UserCollectionComponent,
     PageChatComponent,
+    PageLessonDetailComponent,
+    PageLessonComponent,
+
 
 
 

+ 1 - 1
app-angular/src/modules/lesson/page-chat/page-chat.component.scss

@@ -1,4 +1,4 @@
-// AI菜谱
+// AI禁忌事项
 .page {
     background-color: #f2f2f2;
     height: calc(100% - 114px);

+ 111 - 0
app-angular/src/modules/lesson/page-lesson-detail/page-lesson-detail.component.html

@@ -0,0 +1,111 @@
+<div class="ion-page">
+    <ion-header>
+        <ion-toolbar>
+            <ion-buttons slot="start">
+                <ion-button routerLink="/cook/lesson">&lt;返回</ion-button>
+            </ion-buttons>
+            <ion-title>课程</ion-title>
+        </ion-toolbar>
+    </ion-header>
+    <ion-content>
+
+
+        <ion-img [src]="course?.get('courseImg')" alt="图片加载不出来"></ion-img>
+
+        <ion-item>
+            <ion-avatar slot="start">
+                <img alt="Silhouette of a person's head"
+                    [src]="course?.get('courseAuthor')?.get('avatar')||'https://ionicframework.com/docs/img/demos/avatar.svg'" />
+            </ion-avatar>
+            <ion-label>{{course?.get('courseAuthor')?.get('name')}}</ion-label>
+            <ion-button fill="outline" color="danger">关注</ion-button>
+            <!-- <div>{{course?.get('courseStore') | tok}}人收藏</div> -->
+        </ion-item>
+
+        <ion-card>
+            <ion-card-header>
+                <ion-card-title>{{course?.get('courseName')}}</ion-card-title>
+                <ion-card-subtitle class="custom-subtitle">{{course?.get('courseScore')}}<span
+                        style="color: rgb(196, 194, 194); font-size: 10px;">
+                        评分</span></ion-card-subtitle>
+            </ion-card-header>
+
+            <ion-card-content>
+                {{course?.get('courseDescript')}}
+            </ion-card-content>
+
+            <ion-button fill="clear">收藏</ion-button>
+            <ion-button fill="clear">购买</ion-button>
+        </ion-card>
+
+        <!-- <ion-list *ngIf="lesson.videocourse?.length"> -->
+        <ion-list>
+            <ion-list-header>
+                <ion-label>视频</ion-label>
+            </ion-list-header>
+            <!-- <ion-item *ngFor="let video of lesson.videocourse"> -->
+            <ion-item>
+                <svg class="icon"
+                    style="width: 4em;height: 2em;vertical-align: middle;fill: currentColor;overflow: hidden;"
+                    viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3934">
+                    <path
+                        d="M607.9232 227.84a144.4864 144.4864 0 0 1 143.744 137.728l0.0768 3.2768 52.48-36.6592a61.2352 61.2352 0 0 1 76.8256 8.2688l3.0976 3.328 2.7648 3.4816c5.1712 8.6016 8.8832 17.9968 11.0336 28.032l1.1008 6.0672v276.5824a58.8032 58.8032 0 0 1-58.9056 58.7008c-10.496 0-20.7616-2.7136-29.8496-7.8336l-4.4288-2.7648-54.528-37.0176-0.1792 1.5872a144.3584 144.3584 0 0 1-131.3792 125.0816l-5.9904 0.3584-5.888 0.1024H268.8512a144.4864 144.4864 0 0 1-143.744-137.728l-0.1536-5.632V371.1744a144.4864 144.4864 0 0 1 138.2656-143.2064l5.632-0.128h339.072z m0 61.2608H268.8256a82.56 82.56 0 0 0-82.2528 77.44l-0.1536 4.6592v281.5744A82.56 82.56 0 0 0 264.192 734.72l4.6592 0.1536h338.2016a82.56 82.56 0 0 0 82.2528-77.44l0.1792-4.6592 0.8192-0.8704V371.2a82.56 82.56 0 0 0-77.7472-81.9456l-4.6592-0.1536z m227.0976 96.9728l-84.0448 57.1904-1.1008 149.5808 85.1456 59.2384V386.0736z"
+                        fill="#FB553C" p-id="3935"></path>
+                    <path
+                        d="M529.0752 534.1184l-128.2816 74.624a25.6 25.6 0 0 1-38.4768-22.1184v-149.248a25.6 25.6 0 0 1 38.4768-22.1184l128.256 74.624a25.6 25.6 0 0 1 0 44.2368z"
+                        fill="#FB553C" p-id="3936"></path>
+                </svg>
+                <!-- <ion-label>{{video}}</ion-label> -->
+            </ion-item>
+        </ion-list>
+
+        <!-- <ion-list *ngIf="lesson.test?.length">
+        <ion-item *ngFor="let questionAndAnswer of lesson.test; let i = index">
+            <div>
+                <h2>{{ questionAndAnswer[0] }}</h2>
+            </div>
+            <div>
+                <img [src]="questionAndAnswer[1]" alt="Answer">
+            </div>
+        </ion-item>
+    </ion-list> -->
+        <div>
+            <h5 style="padding-left: 12px;">留下你的评论{{commentCount}}</h5>
+            <!-- <ion-item lines="none">
+                <ion-avatar slot="start">
+                    <img alt="Silhouette of a person's head"
+                        src="https://ionicframework.com/docs/img/demos/avatar.svg" />
+                </ion-avatar>
+                <ion-label><input type="text" class="input-box" placeholder="留下评论,分享你的想法!"></ion-label>
+            </ion-item> -->
+            <ng-container *ngIf="commentList">
+                <ng-container *ngFor="let comment of commentList; let i = index">
+                    <div class="commentbox">
+                        <ion-item lines="none">
+                            <ion-avatar slot="start">
+                                <img alt="Silhouette of a person's head"
+                                    [src]="comment.get('user').get('avatar')||'https://ionicframework.com/docs/img/demos/avatar.svg'" />
+                            </ion-avatar>
+                            <ion-label>{{ comment.get("user").get("name") }}</ion-label>
+
+                            <ion-icon name="heart-outline"></ion-icon>
+                            <div class="likes">27</div>
+
+                        </ion-item>
+                        <p style="font-size: 15px;">{{comment?.get("commentContent")}}</p>
+                        <p style="color: grey;">{{comment?.get("createdAt")|date:'short'}}</p>
+                    </div>
+                </ng-container>
+            </ng-container>
+        </div>
+
+        <div class="footer">
+            <div class="send-container">
+                <input type="text" [(ngModel)]="commentContent" class="message-input" placeholder="输入消息...">
+                <button class="send-button" (click)="saveComment()">发送</button>
+            </div>
+
+        </div>
+        <div class="navfooter"></div>
+    </ion-content>
+</div>

+ 87 - 0
app-angular/src/modules/lesson/page-lesson-detail/page-lesson-detail.component.scss

@@ -0,0 +1,87 @@
+/* 全局样式文件(styles.css)或组件样式文件 */
+
+ion-img {
+    width: 100%;
+    /* 设置为你想要的宽度 */
+    height: 350px;
+    /* 设置为你想要的高度 */
+    object-fit: cover;
+    /* 调整适应方式,保持原始比例并填充容器 */
+}
+
+.custom-subtitle {
+    color: red;
+    font-size: 22px;
+    font-style: italic;
+    text-align: right;
+    display: inline-block;
+
+}
+
+.navfooter {
+    width: 100%;
+    height: 120px;
+}
+
+.material-label {
+    display: block;
+}
+
+.input-box {
+    width: 300px;
+    height: 40px;
+    border-radius: 20px;
+    background-color: #f2f2f2;
+    padding: 10px;
+    border: none;
+    outline: none;
+    font-size: 16px;
+    color: #333;
+    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
+}
+
+//评论区
+.commentbox {
+    p {
+        padding-left: 70px;
+        padding-right: 30px;
+    }
+
+    .icon-container {
+        color: grey;
+    }
+}
+
+//固定评论输入框
+.footer {
+    position: fixed;
+    bottom: 60px;
+    width: 100vw;
+}
+
+.send-container {
+    display: flex;
+    align-items: center;
+    padding: 10px;
+    background-color: #f2f2f2;
+
+}
+
+.message-input {
+    flex: 1;
+    padding: 8px;
+    border: none;
+    border-radius: 20px;
+    background-color: #fff;
+}
+
+.send-button {
+    padding: 8px 15px;
+    border: none;
+    border-radius: 20px;
+    background-color: #38c1f5;
+    color: white;
+    font-weight: bold;
+    cursor: pointer;
+    margin-left: 10px;
+}

+ 21 - 0
app-angular/src/modules/lesson/page-lesson-detail/page-lesson-detail.component.spec.ts

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

+ 71 - 0
app-angular/src/modules/lesson/page-lesson-detail/page-lesson-detail.component.ts

@@ -0,0 +1,71 @@
+import { Component } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+// 引入Parse第三方库
+import * as Parse from "parse"
+
+@Component({
+  selector: 'app-page-lesson-detail',
+  templateUrl: './page-lesson-detail.component.html',
+  styleUrls: ['./page-lesson-detail.component.scss']
+})
+
+export class PageLessonDetailComponent {
+  course: any = {}
+  constructor(private route: ActivatedRoute) {
+    this.route.queryParams.subscribe(params => {
+      this.initPage(params["id"]);
+    });
+  }
+  lessonPointer: any;//获取当前指针
+  async getCourseById(id: string) {
+    let query = new Parse.Query("PetCourse")
+    query.include('courseAuthor')//查询指针
+    this.course = await query.get(id);
+    // this.name = this.course?.get('courseAuthor')?.get('name')
+    this.lessonPointer = {
+      __type: 'Pointer',
+      className: 'PetCourse',
+      objectId: this.course.id
+    };
+  }
+  //用户输入评论保存到数据库
+  currentUser = Parse.User.current()
+  commentContent = ''//用户评论,双向绑定commentCoutent实现保存该评论
+  async saveComment() {
+    let CourseComment = Parse.Object.extend('CourseComment')
+    let courseComment = new CourseComment()
+    courseComment.set('user', { __type: 'Pointer', className: '_User', objectId: this.currentUser?.id })
+    courseComment.set('commentContent', this.commentContent)
+    courseComment.set('lesson', this.lessonPointer); // 设置指向QwlMenu表的指针类型字段
+    this.commentContent = '';
+    return courseComment.save().then((saveObject: any) => {
+      // 处理Promise成功的情况
+      console.log(saveObject);
+      //评论立即刷新到页面上
+      this.getCommentData().then((commentList: Array<Parse.Object>) => {
+        this.commentList = commentList;
+        this.commentCount = this.commentList.length; // 更新评论数量
+      });
+    },
+      (error: string) => {
+        // 处理Promise失败的情况
+        console.log("失败:" + error);
+      })
+  }
+  // 评论数据加载相关函数
+  commentCount: number = 0
+  commentList: Array<Parse.Object> = []
+  async initPage(id: string) {
+    await this.getCourseById(id);
+    this.commentList = await this.getCommentData()
+    this.commentCount = this.commentList.length;
+  }
+
+  async getCommentData() {
+    let query = new Parse.Query("CourseComment");
+    query.equalTo("lesson", this.lessonPointer);
+    query.descending('createdAt')
+    let list = await query.find();
+    return list
+  }
+}

+ 61 - 0
app-angular/src/modules/lesson/page-lesson/page-lesson.component.html

@@ -0,0 +1,61 @@
+<!--侧边栏-->
+<ion-menu contentId="main-content">
+    <ion-header>
+        <ion-toolbar>
+            <ion-title>Menu Content</ion-title>
+        </ion-toolbar>
+    </ion-header>
+    <ion-content class="ion-padding">This is the menu content.</ion-content>
+</ion-menu>
+<!--主页面-->
+<div class="ion-page" id="main-content">
+    <!--搜索栏-->
+    <ion-header>
+        <ion-toolbar>
+            <ion-buttons slot="start">
+                <ion-menu-button></ion-menu-button>
+            </ion-buttons>
+            <ion-searchbar [(ngModel)]="searchInput" (ionChange)="search()" (ionClear)="search()"
+                placeholder="今天想学什么呢?"></ion-searchbar>
+        </ion-toolbar>
+    </ion-header>
+    <!--课程卡片区-->
+    <ion-content>
+        <ion-grid>
+            <ion-row>
+                <ng-container *ngFor="let course of courseList; let i = index">
+                    <ng-container *ngIf="i % 2 === 0">
+                        <ion-col size="5.5">
+                            <ion-card (click)="goLessonDetail(course)">
+                                <img alt="Silhouette of mountains" [src]="course?.get('courseImg')" />
+                                <ion-card-header>
+                                    <ion-card-title>{{course?.get("courseName")}}</ion-card-title>
+                                    <ion-card-subtitle>评分:{{course?.get("courseScore")}}</ion-card-subtitle>
+                                </ion-card-header>
+
+                            </ion-card>
+                        </ion-col>
+                        <ion-col size="5.5" *ngIf="i + 1 < courseList.length">
+                            <ion-card (click)="goLessonDetail(courseList[i+1])">
+                                <img alt="Silhouette of mountains" [src]="courseList[i + 1].get('courseImg')" />
+                                <ion-card-header>
+                                    <ion-card-title>{{courseList[i +
+                                        1].get("courseName")}}</ion-card-title>
+                                    <ion-card-subtitle>评分:{{courseList[i+1].get("courseScore")}}</ion-card-subtitle>
+                                </ion-card-header>
+
+                            </ion-card>
+
+                        </ion-col>
+                    </ng-container>
+                </ng-container>
+            </ion-row>
+        </ion-grid>
+    </ion-content>
+    <!-- 触底控制区域 -->
+    <ion-infinite-scroll #infiScroll (ionInfinite)="onBottomLoad($event,infiScroll)">
+        <ion-infinite-scroll-content loadingText="Please wait..."
+            loadingSpinner="bubbles"></ion-infinite-scroll-content>
+    </ion-infinite-scroll>
+    <!-- <div class="navfooter"> </div> -->
+</div>

+ 34 - 0
app-angular/src/modules/lesson/page-lesson/page-lesson.component.scss

@@ -0,0 +1,34 @@
+ion-searchbar {
+    margin-top: 10px;
+}
+
+ion-buttons {
+    margin-top: 10px;
+}
+
+ion-card {
+    width: 100%;
+    margin-bottom: 1px;
+
+    // height: 100%;
+    img {
+        width: 100%;
+        height: 200px;
+        object-fit: cover;
+    }
+
+    ion-card-title {
+        font-size: 18px;
+        white-space: nowrap;
+        /* 防止文字换行 */
+        overflow: hidden;
+        /* 隐藏溢出部分的文字 */
+        text-overflow: ellipsis;
+        /* 显示省略号 */
+    }
+}
+
+.navfooter {
+    width: 100%;
+    height: 60px;
+}

+ 21 - 0
app-angular/src/modules/lesson/page-lesson/page-lesson.component.spec.ts

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

+ 66 - 0
app-angular/src/modules/lesson/page-lesson/page-lesson.component.ts

@@ -0,0 +1,66 @@
+import { Component } from '@angular/core';
+import { Router } from '@angular/router';
+// import { DetailComponent } from '../detail/detail.component';
+import { MenuController } from '@ionic/angular';
+
+// 引入服务
+import { ActivatedRoute } from '@angular/router';
+
+// 引入Parse第三方库
+import * as Parse from "parse"
+(Parse as any).serverURL = "http://metapunk.cn:9999/parse"
+Parse.initialize("dev")
+
+@Component({
+  selector: 'app-page-lesson',
+  templateUrl: './page-lesson.component.html',
+  styleUrls: ['./page-lesson.component.scss']
+})
+export class PageLessonComponent {
+
+  constructor(private router: Router) { this.initPage(); }
+  courseList: Array<Parse.Object> = []
+  // 首次进入页面,默认加载首批数据
+  async initPage() {
+    this.courseList = await this.getMenuData()
+  }
+  // 数据加载相关函数
+  async getMenuData() {
+    let query = new Parse.Query("PetCourse");
+    query.limit(this.pageSize);
+    query.include('courseAuthor')
+    if (this.searchInput) {
+      query.contains(this.searchType, this.searchInput)
+    }
+    if (this.skip) {
+      query.skip(this.skip)
+    }
+    query.addAscending("no")
+    let list = await query.find();
+    console.log(list);
+
+    return list
+  }
+  // 搜索功能相关函数与属性
+  searchInput: string = ``
+  searchType: string = `courseName`
+  async search() {
+    this.skip = 0; // 每次搜索条件变化,从第一条重新加载
+    this.courseList = await this.getMenuData();
+  }
+  // 触底加载函数逻辑
+  pageSize = 5
+  skip: number = 0 // 跳过多少条进行加载
+  async onBottomLoad(event: any, infiScroll: any) {
+    console.log("onBottomLoad", this.courseList.length)
+    this.skip = this.courseList.length;
+    let list = await this.getMenuData();
+    this.courseList = this.courseList.concat(list)
+    infiScroll?.complete();
+  }
+
+
+  goLessonDetail(lesson: any) {
+    this.router.navigate(["/lesson/lesson/detail"], { queryParams: lesson })
+  }
+}