|
|
@@ -7,9 +7,14 @@ import { IonHeader, IonToolbar, IonTitle, IonContent,
|
|
|
import { ExploreContainerComponent } from '../explore-container/explore-container.component';
|
|
|
import { CommonModule } from '@angular/common';
|
|
|
import { Router } from '@angular/router';
|
|
|
-import { CloudObject, CloudUser } from 'src/lib/ncloud';
|
|
|
+import { CloudObject, CloudUser, CloudQuery } from 'src/lib/ncloud';
|
|
|
import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
|
|
|
+import { FmodeChatCompletion, MarkdownPreviewModule } from 'fmode-ng';
|
|
|
|
|
|
+interface DialogueItem {
|
|
|
+ role: string;
|
|
|
+ content: string;
|
|
|
+}
|
|
|
@Component({
|
|
|
selector: 'app-tab2',
|
|
|
templateUrl: 'tab2.page.html',
|
|
|
@@ -42,24 +47,143 @@ export class Tab2Page {
|
|
|
private modalCtrl:ModalController,
|
|
|
private router: Router) {}
|
|
|
|
|
|
- goToPage(){
|
|
|
- this.router.navigate(['/tabs/AIimagery'])
|
|
|
- }
|
|
|
-
|
|
|
- recommendedMovies = [
|
|
|
- {
|
|
|
- title: '某某剧名1',
|
|
|
- rating: '9.0',
|
|
|
- description: '这是一部精彩的剧集,讲述了...',
|
|
|
- coverImage: 'assets/movie1.jpg',
|
|
|
- },
|
|
|
- {
|
|
|
- title: '某某剧名2',
|
|
|
- rating: '8.5',
|
|
|
- description: '这部剧集以其独特的视角吸引了观众...',
|
|
|
- coverImage: 'assets/movie2.jpg',
|
|
|
- },
|
|
|
- // 其他推荐影视剧...
|
|
|
- ];
|
|
|
+ filmList:Array<CloudObject> = []
|
|
|
+ async loadFilmList(){
|
|
|
+ let query = new CloudQuery("FilmRecommendation");
|
|
|
+ this.filmList = await query.find()
|
|
|
+ }
|
|
|
|
|
|
+ async ngOnInit() {
|
|
|
+ await this.ChatList();
|
|
|
+ this.loadFilmList()
|
|
|
+ }
|
|
|
+
|
|
|
+ responseMsg: any = "";
|
|
|
+ isComplete: boolean = false; // 定义完成状态属性,用来标记是否补全完成
|
|
|
+ chatList: Array<CloudObject> = [];
|
|
|
+
|
|
|
+ async ChatList() {
|
|
|
+ const currentUser = new CloudUser();
|
|
|
+ await currentUser.current(); // 确保用户信息已加载
|
|
|
+ const userId = currentUser.id; // 获取当前用户的 ObjectId
|
|
|
+
|
|
|
+ let query = new CloudQuery("FilmChat");
|
|
|
+ query.equalTo("user", currentUser.toPointer()); // 只获取当前用户的记录
|
|
|
+
|
|
|
+ this.chatList = await query.find();
|
|
|
+
|
|
|
+ this.chatList.forEach(chat => {
|
|
|
+ const dialogueArray = chat.get('dialogue');
|
|
|
+ if (dialogueArray && dialogueArray.length > 0) {
|
|
|
+ const userIndex = dialogueArray.findIndex((item: DialogueItem) => item.role === 'user');
|
|
|
+ if (userIndex !== -1) {
|
|
|
+ dialogueArray.splice(userIndex, 1); // 移除第一条 user 内容
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ sendMessage() {
|
|
|
+ console.log("create");
|
|
|
+
|
|
|
+ let dialogues = this.chatList.map(chat => {
|
|
|
+ const dialogueArray = chat.get('dialogue');
|
|
|
+ return dialogueArray.map((item: DialogueItem) => `${item.role}: ${item.content}`).join('\n');
|
|
|
+ }).join('\n');
|
|
|
+
|
|
|
+ let PromptTemplate = `
|
|
|
+ 请根据以下的用户聊天记录生成该用户的影视剧推荐列表。
|
|
|
+
|
|
|
+ ${dialogues}
|
|
|
+
|
|
|
+ 请生成推荐列表,包括剧名、题材、评分和描述。
|
|
|
+ 严格按照下面的格式生成:
|
|
|
+ 剧名:
|
|
|
+ 题材:
|
|
|
+ 评分:
|
|
|
+ 描述:
|
|
|
+ `;
|
|
|
+
|
|
|
+ let completion = new FmodeChatCompletion([
|
|
|
+ { role: "system", content: "" },
|
|
|
+ { role: "user", content: PromptTemplate }
|
|
|
+ ]);
|
|
|
+
|
|
|
+ completion.sendCompletion().subscribe(async (message: any) => {
|
|
|
+ console.log(message.content);
|
|
|
+ this.responseMsg = message.content;
|
|
|
+
|
|
|
+ if (message?.complete) {
|
|
|
+ this.isComplete = true;
|
|
|
+
|
|
|
+ // 假设 message.content 是自然语言文本而不是 JSON
|
|
|
+ try {
|
|
|
+ // 这里假设 AI 返回的内容是以某种格式列出推荐
|
|
|
+ // 例如,"推荐1: 剧名1, 题材1, 评分1, 描述1\n推荐2: 剧名2, 题材2, 评分2, 描述2"
|
|
|
+
|
|
|
+ const recommendations = this.parseRecommendations(message.content);
|
|
|
+
|
|
|
+ // 获取当前用户的 ObjectId
|
|
|
+ const currentUser = new CloudUser();
|
|
|
+ await currentUser.current(); // 确保用户信息已加载
|
|
|
+
|
|
|
+ // 遍历推荐列表并保存到 FilmRecommendation 表
|
|
|
+ for (const rec of recommendations) {
|
|
|
+ const recommendation = new CloudObject("FilmRecommendation");
|
|
|
+ recommendation.set({
|
|
|
+ user: currentUser.toPointer(), // 设置用户指针
|
|
|
+ title: rec.title,
|
|
|
+ genre: rec.genre,
|
|
|
+ grade: rec.grade,
|
|
|
+ desc: rec.desc
|
|
|
+ });
|
|
|
+
|
|
|
+ try {
|
|
|
+ await recommendation.save(); // 保存推荐到数据库
|
|
|
+ console.log('推荐已保存:', recommendation);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('保存推荐失败:', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('解析推荐内容失败:', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析推荐内容的辅助方法
|
|
|
+ private parseRecommendations(content: string): Array<{ title: string, genre: string, grade: string, desc: string }> {
|
|
|
+ const recommendations: Array<{ title: string, genre: string, grade: string, desc: string }> = [];
|
|
|
+
|
|
|
+ // 按照空行分割每条推荐
|
|
|
+ const blocks = content.split('\n\n');
|
|
|
+ for (const block of blocks) {
|
|
|
+ const lines = block.split('\n').map(line => line.trim()).filter(line => line.length > 0);
|
|
|
+
|
|
|
+ if (lines.length >= 4) {
|
|
|
+ const titleLine = lines[0];
|
|
|
+ const genreLine = lines[1];
|
|
|
+ const gradeLine = lines[2];
|
|
|
+ const descLine = lines[3];
|
|
|
+
|
|
|
+ // 提取信息并去掉前缀和冒号
|
|
|
+ const title = titleLine.replace(/.*?剧名:\s*《(.*?)》$/, '$1').trim(); // 提取剧名
|
|
|
+ const genre = genreLine.replace(/.*?题材:\s*/, '').trim(); // 提取题材
|
|
|
+ const grade = gradeLine.replace(/.*?评分:\s*/, '').trim(); // 提取评分
|
|
|
+ const desc = descLine.replace(/.*?描述:\s*/, '').trim(); // 提取描述
|
|
|
+
|
|
|
+ recommendations.push({
|
|
|
+ title: title,
|
|
|
+ genre: genre,
|
|
|
+ grade: grade,
|
|
|
+ desc: desc
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ console.warn('推荐内容格式不正确:', block); // 打印格式不正确的块
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return recommendations;
|
|
|
+ }
|
|
|
}
|