Selaa lähdekoodia

feat: comp-markmap and GoPlan generate

ryanemax 3 kuukautta sitten
vanhempi
commit
f1a3b4997d
77 muutettua tiedostoa jossa 1550 lisäystä ja 109 poistoa
  1. 899 99
      AIart-app/package-lock.json
  2. 5 0
      AIart-app/package.json
  3. 1 0
      AIart-app/src/app/comp-markmap/comp-markmap.component.html
  4. 7 0
      AIart-app/src/app/comp-markmap/comp-markmap.component.scss
  5. 22 0
      AIart-app/src/app/comp-markmap/comp-markmap.component.spec.ts
  6. 79 0
      AIart-app/src/app/comp-markmap/comp-markmap.component.ts
  7. 408 0
      AIart-app/src/app/lib/ncloud.ts
  8. 17 0
      AIart-app/src/app/tab2/tab2.page.html
  9. 54 3
      AIart-app/src/app/tab2/tab2.page.ts
  10. 6 0
      AIart-app/src/app/tab4/tab4.page.html
  11. 32 5
      AIart-app/src/app/tab4/tab4.page.ts
  12. 9 0
      AIart-app/src/assets/markmap/default.min.css
  13. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_AMS-Regular.ttf
  14. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_AMS-Regular.woff
  15. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_AMS-Regular.woff2
  16. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Bold.ttf
  17. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Bold.woff
  18. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Bold.woff2
  19. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Regular.ttf
  20. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Regular.woff
  21. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Regular.woff2
  22. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Bold.ttf
  23. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Bold.woff
  24. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Bold.woff2
  25. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Regular.ttf
  26. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Regular.woff
  27. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Regular.woff2
  28. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-Bold.ttf
  29. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-Bold.woff
  30. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-Bold.woff2
  31. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-BoldItalic.ttf
  32. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-BoldItalic.woff
  33. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-BoldItalic.woff2
  34. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-Italic.ttf
  35. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-Italic.woff
  36. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-Italic.woff2
  37. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-Regular.ttf
  38. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-Regular.woff
  39. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Main-Regular.woff2
  40. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Math-BoldItalic.ttf
  41. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Math-BoldItalic.woff
  42. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Math-BoldItalic.woff2
  43. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Math-Italic.ttf
  44. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Math-Italic.woff
  45. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Math-Italic.woff2
  46. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Bold.ttf
  47. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Bold.woff
  48. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Bold.woff2
  49. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Italic.ttf
  50. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Italic.woff
  51. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Italic.woff2
  52. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Regular.ttf
  53. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Regular.woff
  54. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Regular.woff2
  55. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Script-Regular.ttf
  56. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Script-Regular.woff
  57. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Script-Regular.woff2
  58. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size1-Regular.ttf
  59. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size1-Regular.woff
  60. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size1-Regular.woff2
  61. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size2-Regular.ttf
  62. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size2-Regular.woff
  63. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size2-Regular.woff2
  64. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size3-Regular.ttf
  65. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size3-Regular.woff
  66. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size3-Regular.woff2
  67. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size4-Regular.ttf
  68. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size4-Regular.woff
  69. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Size4-Regular.woff2
  70. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Typewriter-Regular.ttf
  71. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Typewriter-Regular.woff
  72. BIN
      AIart-app/src/assets/markmap/fonts/KaTeX_Typewriter-Regular.woff2
  73. 0 0
      AIart-app/src/assets/markmap/katex.min.css
  74. 4 0
      AIart-app/src/assets/markmap/webfontloader.js
  75. 5 0
      AIart-app/src/index.html
  76. 2 2
      AIart-app/tsconfig.json
  77. 0 0
      node_modules/katex/dist/katex.min.css

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 899 - 99
AIart-app/package-lock.json


+ 5 - 0
AIart-app/package.json

@@ -29,9 +29,12 @@
     "@ionic/angular": "^8.0.0",
     "fmode-ng": "^0.0.63",
     "ionicons": "^7.2.1",
+    "markmap-lib": "^0.17.2",
+    "markmap-view": "^0.17.2",
     "rxjs": "~7.8.0",
     "swiper": "^11.1.15",
     "tslib": "^2.3.0",
+    "webfontloader": "^1.6.28",
     "zone.js": "~0.14.2"
   },
   "devDependencies": {
@@ -46,7 +49,9 @@
     "@angular/language-service": "^18.0.0",
     "@capacitor/cli": "6.2.0",
     "@ionic/angular-toolkit": "^11.0.1",
+    "@types/d3-flextree": "^2.1.4",
     "@types/jasmine": "~5.1.0",
+    "@types/markdown-it": "^14.1.2",
     "@typescript-eslint/eslint-plugin": "^6.0.0",
     "@typescript-eslint/parser": "^6.0.0",
     "eslint": "^8.57.0",

+ 1 - 0
AIart-app/src/app/comp-markmap/comp-markmap.component.html

@@ -0,0 +1 @@
+<svg #mapView class="maparea" [style.height]="height"></svg>

+ 7 - 0
AIart-app/src/app/comp-markmap/comp-markmap.component.scss

@@ -0,0 +1,7 @@
+// @import "../../../node_modules/katex/dist/katex.min.css";
+// @import "../../../node_modules/highlight.js/styles/default.min.css";
+
+.maparea{
+    width:100%;
+    // height:100%;
+}

+ 22 - 0
AIart-app/src/app/comp-markmap/comp-markmap.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { CompMarkmapComponent } from './comp-markmap.component';
+
+describe('CompMarkmapComponent', () => {
+  let component: CompMarkmapComponent;
+  let fixture: ComponentFixture<CompMarkmapComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [CompMarkmapComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(CompMarkmapComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 79 - 0
AIart-app/src/app/comp-markmap/comp-markmap.component.ts

@@ -0,0 +1,79 @@
+import { Component, ElementRef, Input, AfterViewInit, ViewChild } from '@angular/core';
+
+import * as markmap from 'markmap-view';
+import { Markmap, loadCSS, loadJS } from 'markmap-view';
+
+import { Transformer, builtInPlugins } from 'markmap-lib';
+// import "../../../node_modules/webfontloader/webfontloader.js";
+
+
+@Component({
+  selector: 'comp-markmap',
+  templateUrl: './comp-markmap.component.html',
+  styleUrls: ['./comp-markmap.component.scss'],
+  standalone: true,
+})
+export class CompMarkmapComponent  implements AfterViewInit {
+
+  @ViewChild("mapView") mapView:ElementRef | undefined
+  @Input() markdown:string = ""
+  @Input() height:string = "350px";
+  constructor() { }
+
+  ngAfterViewInit() {
+    setTimeout(() => {
+      
+      this.loadMarkMap();
+    }, 500);
+  }
+
+  loadMarkMap(){
+    // 通过markmap-lib 解析markdown提取所需的结构和素材
+    // With additional plugins
+    const transformer = new Transformer([...builtInPlugins]);
+    // 1. transform Markdown
+    const { root, features } = transformer.transform(this.markdown);
+    // 2. get assets
+    // or get all possible assets that could be used later
+    let assets = transformer.getAssets();
+
+    assets.scripts?.forEach((item:any)=>{
+      console.log(item)
+      if(item.data?.src?.endsWith("webfontloader.js")){
+        item.data.src = "assets/markmap/webfontloader.js"
+      }
+    })
+    assets.styles?.forEach((item:any)=>{
+
+      if(item.data?.src?.endsWith("katex.min.css")){
+        item.data.src = "assets/markmap/katex.min.css"
+      }
+      if(item.data?.src?.endsWith("default.min.css")){
+        item.data.src = "assets/markmap/default.min.css"
+      }
+    })
+    console.log(assets)
+    if(assets.styles){
+     // 通过markmap-view 渲染svg效果图
+      // 1. load assets
+      if (assets.styles) loadCSS(assets.styles);
+      if (assets.scripts) {
+          loadJS(assets.scripts, {
+            getMarkmap: () => markmap,
+          }).then(()=>{
+              // 向页面Dom渲染svg图
+              // 2. create markmap
+              // `options` is optional, i.e. `undefined` can be passed here
+              setTimeout(() => {
+                const svgEl = this.mapView?.nativeElement;
+                console.log(svgEl,root)
+                Markmap.create(svgEl, undefined, root); // -> returns a Markmap instance
+              }, 1000);
+          })
+        }
+    } 
+
+     
+    }
+
+}

+ 408 - 0
AIart-app/src/app/lib/ncloud.ts

@@ -0,0 +1,408 @@
+// CloudObject.ts
+export class CloudObject {
+    className: string;
+    id: string | null = null;
+    createdAt:any;
+    updatedAt:any;
+    data: Record<string, any> = {};
+
+    constructor(className: string) {
+        this.className = className;
+    }
+
+    toPointer() {
+        return { "__type": "Pointer", "className": this.className, "objectId": this.id };
+    }
+
+    set(json: Record<string, any>) {
+        Object.keys(json).forEach(key => {
+            if (["objectId", "id", "createdAt", "updatedAt"].indexOf(key) > -1) {
+                return;
+            }
+            this.data[key] = json[key];
+        });
+    }
+
+    get(key: string) {
+        return this.data[key] || null;
+    }
+
+    async save() {
+        let method = "POST";
+        let url = `https://dev.fmode.cn/parse/classes/${this.className}`;
+
+        // 更新
+        if (this.id) {
+            url += `/${this.id}`;
+            method = "PUT";
+        }
+
+        const body = JSON.stringify(this.data);
+        const response = await fetch(url, {
+            headers: {
+                "content-type": "application/json;charset=UTF-8",
+                "x-parse-application-id": "dev"
+            },
+            body: body,
+            method: method,
+            mode: "cors",
+            credentials: "omit"
+        });
+
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+        }
+        if (result?.objectId) {
+            this.id = result?.objectId;
+        }
+        return this;
+    }
+
+    async destroy() {
+        if (!this.id) return;
+        const response = await fetch(`https://dev.fmode.cn/parse/classes/${this.className}/${this.id}`, {
+            headers: {
+                "x-parse-application-id": "dev"
+            },
+            body: null,
+            method: "DELETE",
+            mode: "cors",
+            credentials: "omit"
+        });
+
+        const result = await response?.json();
+        if (result) {
+            this.id = null;
+        }
+        return true;
+    }
+}
+
+// CloudQuery.ts
+export class CloudQuery {
+    className: string;
+    queryParams: Record<string, any> = {};
+
+    constructor(className: string) {
+        this.className = className;
+    }
+
+    include(...fileds:string[]) {
+        this.queryParams["include"] = fileds;
+    }
+    greaterThan(key: string, value: any) {
+        if (!this.queryParams["where"][key]) this.queryParams["where"][key] = {};
+        this.queryParams["where"][key]["$gt"] = value;
+    }
+
+    greaterThanAndEqualTo(key: string, value: any) {
+        if (!this.queryParams["where"][key]) this.queryParams["where"][key] = {};
+        this.queryParams["where"][key]["$gte"] = value;
+    }
+
+    lessThan(key: string, value: any) {
+        if (!this.queryParams["where"][key]) this.queryParams["where"][key] = {};
+        this.queryParams["where"][key]["$lt"] = value;
+    }
+
+    lessThanAndEqualTo(key: string, value: any) {
+        if (!this.queryParams["where"][key]) this.queryParams["where"][key] = {};
+        this.queryParams["where"][key]["$lte"] = value;
+    }
+
+    equalTo(key: string, value: any) {
+        if (!this.queryParams["where"]) this.queryParams["where"] = {};
+        this.queryParams["where"][key] = value;
+    }
+
+    async get(id: string) {
+        const url = `https://dev.fmode.cn/parse/classes/${this.className}/${id}?`;
+
+        const response = await fetch(url, {
+            headers: {
+                "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
+                "x-parse-application-id": "dev"
+            },
+            body: null,
+            method: "GET",
+            mode: "cors",
+            credentials: "omit"
+        });
+
+        const json = await response?.json();
+        return json || {};
+    }
+
+    async find():Promise<Array<CloudObject>> {
+        let url = `https://dev.fmode.cn/parse/classes/${this.className}?`;
+
+        let queryStr = ``
+        Object.keys(this.queryParams).forEach(key=>{
+            let paramStr = JSON.stringify(this.queryParams[key]);
+            if(key=="include"){
+                paramStr = this.queryParams[key]?.join(",")
+            }
+            if(queryStr) {
+                url += `${key}=${paramStr}`;
+            }else{
+                url += `&${key}=${paramStr}`;
+            }
+        })
+        // if (Object.keys(this.queryParams["where"]).length) {
+            
+        // }
+
+        const response = await fetch(url, {
+            headers: {
+                "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
+                "x-parse-application-id": "dev"
+            },
+            body: null,
+            method: "GET",
+            mode: "cors",
+            credentials: "omit"
+        });
+
+        const json = await response?.json();
+        let list = json?.results || []
+        let objList = list.map((item:any)=>this.dataToObj(item))
+        return objList || [];
+    }
+
+
+    async first() {
+        let url = `https://dev.fmode.cn/parse/classes/${this.className}?`;
+
+        if (Object.keys(this.queryParams["where"]).length) {
+            const whereStr = JSON.stringify(this.queryParams["where"]);
+            url += `where=${whereStr}`;
+        }
+
+        const response = await fetch(url, {
+            headers: {
+                "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
+                "x-parse-application-id": "dev"
+            },
+            body: null,
+            method: "GET",
+            mode: "cors",
+            credentials: "omit"
+        });
+
+        const json = await response?.json();
+        const exists = json?.results?.[0] || null;
+        if (exists) {
+            let existsObject = this.dataToObj(exists)
+            return existsObject;
+        }
+        return null
+    }
+
+    dataToObj(exists:any):CloudObject{
+        let existsObject = new CloudObject(this.className);
+        existsObject.set(exists);
+        existsObject.id = exists.objectId;
+        existsObject.createdAt = exists.createdAt;
+        existsObject.updatedAt = exists.updatedAt;
+        return existsObject;
+    }
+}
+
+// CloudUser.ts
+export class CloudUser extends CloudObject {
+    constructor() {
+        super("_User"); // 假设用户类在Parse中是"_User"
+        // 读取用户缓存信息
+        let userCacheStr = localStorage.getItem("NCloud/dev/User")
+        if(userCacheStr){
+            let userData = JSON.parse(userCacheStr)
+            // 设置用户信息
+            this.id = userData?.objectId;
+            this.sessionToken = userData?.sessionToken;
+            this.data = userData; // 保存用户数据
+        }
+    }
+
+    sessionToken:string|null = ""
+    /** 获取当前用户信息 */
+    async current() {
+        if (!this.sessionToken) {
+            console.error("用户未登录");
+            return null;
+        }
+        return this;
+        // const response = await fetch(`https://dev.fmode.cn/parse/users/me`, {
+        //     headers: {
+        //         "x-parse-application-id": "dev",
+        //         "x-parse-session-token": this.sessionToken // 使用sessionToken进行身份验证
+        //     },
+        //     method: "GET"
+        // });
+
+        // const result = await response?.json();
+        // if (result?.error) {
+        //     console.error(result?.error);
+        //     return null;
+        // }
+        // return result;
+    }
+
+    /** 登录 */
+    async login(username: string, password: string):Promise<CloudUser|null> {
+        const response = await fetch(`https://dev.fmode.cn/parse/login`, {
+            headers: {
+                "x-parse-application-id": "dev",
+                "Content-Type": "application/json"
+            },
+            body: JSON.stringify({ username, password }),
+            method: "POST"
+        });
+
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+            return null;
+        }
+        
+        // 设置用户信息
+        this.id = result?.objectId;
+        this.sessionToken = result?.sessionToken;
+        this.data = result; // 保存用户数据
+        // 缓存用户信息
+        console.log(result)
+        localStorage.setItem("NCloud/dev/User",JSON.stringify(result))
+        return this;
+    }
+
+    /** 登出 */
+    async logout() {
+        if (!this.sessionToken) {
+            console.error("用户未登录");
+            return;
+        }
+
+        const response = await fetch(`https://dev.fmode.cn/parse/logout`, {
+            headers: {
+                "x-parse-application-id": "dev",
+                "x-parse-session-token": this.sessionToken
+            },
+            method: "POST"
+        });
+
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+            return false;
+        }
+
+        // 清除用户信息
+        localStorage.removeItem("NCloud/dev/User")
+        this.id = null;
+        this.sessionToken = null;
+        this.data = {};
+        return true;
+    }
+
+    /** 注册 */
+    async signUp(username: string, password: string, additionalData: Record<string, any> = {}) {
+        const userData = {
+            username,
+            password,
+            ...additionalData // 合并额外的用户数据
+        };
+
+        const response = await fetch(`https://dev.fmode.cn/parse/users`, {
+            headers: {
+                "x-parse-application-id": "dev",
+                "Content-Type": "application/json"
+            },
+            body: JSON.stringify(userData),
+            method: "POST"
+        });
+
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+            return null;
+        }
+
+        // 设置用户信息
+        // 缓存用户信息
+        console.log(result)
+        localStorage.setItem("NCloud/dev/User",JSON.stringify(result))
+        this.id = result?.objectId;
+        this.sessionToken = result?.sessionToken;
+        this.data = result; // 保存用户数据
+        return this;
+    }
+
+    override async save() {
+        let method = "POST";
+        let url = `https://dev.fmode.cn/parse/users`;
+    
+        // 更新用户信息
+        if (this.id) {
+            url += `/${this.id}`;
+            method = "PUT";
+        }
+    
+        let data:any = JSON.parse(JSON.stringify(this.data))
+        delete data.createdAt
+        delete data.updatedAt
+        delete data.ACL
+        delete data.objectId
+        const body = JSON.stringify(data);
+        let headersOptions:any = {
+            "content-type": "application/json;charset=UTF-8",
+            "x-parse-application-id": "dev",
+            "x-parse-session-token": this.sessionToken, // 添加sessionToken以进行身份验证
+        }
+        const response = await fetch(url, {
+            headers: headersOptions,
+            body: body,
+            method: method,
+            mode: "cors",
+            credentials: "omit"
+        });
+    
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+        }
+        if (result?.objectId) {
+            this.id = result?.objectId;
+        }
+        localStorage.setItem("NCloud/dev/User",JSON.stringify(this.data))
+        return this;
+    }
+}
+
+export class CloudApi{
+    async fetch(path:string,body:any,options?:{
+        method:string
+        body:any
+    }){
+
+        let reqOpts:any =  {
+            headers: {
+                "x-parse-application-id": "dev",
+                "Content-Type": "application/json"
+            },
+            method: options?.method || "POST",
+            mode: "cors",
+            credentials: "omit"
+        }
+        if(body||options?.body){
+            reqOpts.body = JSON.stringify(body || options?.body);
+            reqOpts.json = true;
+        }
+        let host = `https://dev.fmode.cn`
+        // host = `http://127.0.0.1:1337`
+        let url = `${host}/api/`+path
+        console.log(url,reqOpts)
+        const response = await fetch(url,reqOpts);
+        let json = await response.json();
+        return json
+    }
+}

+ 17 - 0
AIart-app/src/app/tab2/tab2.page.html

@@ -19,6 +19,23 @@
       <ion-icon name="options-outline" style="height: 25px;width: 25px;"></ion-icon>
     </div>
   </ion-toolbar>
+
+  
+  @for(item of mapListOnline;track item.id){
+    <ion-card>
+      <ion-card-header>
+        <ion-card-title>
+          {{item?.get("title")}}
+        </ion-card-title>
+      </ion-card-header>
+      <ion-card-content>
+        <comp-markmap [height]="'600px'" [markdown]="item.get('markmap')"></comp-markmap>
+      </ion-card-content>
+    </ion-card>
+  }
+  @for(item of mapList;track item){
+    <comp-markmap [markdown]="item.content"></comp-markmap>
+  }
 </ion-content>
 
 

+ 54 - 3
AIart-app/src/app/tab2/tab2.page.ts

@@ -1,8 +1,10 @@
 import { Component } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent, IonSearchbar, IonIcon, IonTabs, IonLabel, IonTabButton, IonTabBar } from '@ionic/angular/standalone';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonSearchbar, IonIcon, IonTabs, IonLabel, IonTabButton, IonTabBar, IonCard, IonCardHeader, IonCardContent, IonCardTitle } from '@ionic/angular/standalone';
 import { ExploreContainerComponent } from '../explore-container/explore-container.component';
 import { EditTagComponent } from '../edit-tag/edit-tag.component'
 import { EditRatingStarComponent } from '../edit-rating-star/edit-rating-star.component';
+import { CompMarkmapComponent } from '../comp-markmap/comp-markmap.component';
+import { CloudQuery } from 'src/lib/ncloud';
 
 @Component({
   selector: 'app-tab2',
@@ -10,11 +12,60 @@ import { EditRatingStarComponent } from '../edit-rating-star/edit-rating-star.co
   styleUrls: ['tab2.page.scss'],
   standalone: true,
   imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent,
-    EditTagComponent, EditRatingStarComponent, IonSearchbar, IonIcon, IonTabs, IonLabel, IonTabButton, IonTabBar]
+    EditTagComponent, EditRatingStarComponent, IonSearchbar, IonIcon, IonTabs, IonLabel, IonTabButton, IonTabBar,
+    CompMarkmapComponent,
+    IonCard,IonCardHeader,IonCardContent,IonCardTitle
+  ]
 })
 export class Tab2Page {
 
-  constructor() { }
+  async loadMapList(){
+    let query = new CloudQuery("GoPlan");
+    this.mapListOnline = await query.find();
+  }
+  mapListOnline:any = []
+  mapList = [
+    {title:"demo",content:` ---
+markmap:
+  maxWidth: 300
+  colorFreezeLevel: 2
+---
+
+# markmap
+
+## Links
+
+- <https://markmap.js.org/>
+- [GitHub](https://github.com/markmap/markmap)
+
+## Related
+
+- [coc-markmap](https://github.com/markmap/coc-markmap)
+- [gatsby-remark-markmap](https://github.com/markmap/gatsby-remark-markmap)
+
+## Features
+
+- links
+- **inline** ~~text~~ *styles*
+- multiline
+  text
+- inline code
+- Katex - $x = {-b \pm \sqrt{b^2-4ac} \over 2a}$
+- This is a very very very very very very very very very very very very very very very long line.`},
+    {title:"每日学习计划",content:`# 每日学习计划
+## 时间
+## 计划
+## 总结      
+      `},
+      {title:"每周学习计划",content:`# 每周学习计划
+## 时间
+## 计划
+## 总结        
+        `}
+  ]
+  constructor() { 
+    this.loadMapList();
+  }
 
   currentScore: number = 0; // 初始分值
 

+ 6 - 0
AIart-app/src/app/tab4/tab4.page.html

@@ -16,4 +16,10 @@
   <h1>示例:兴趣分析的智能体示例(ChatPanel组件)</h1>
   <ion-button (click)="openInquiry()">进入兴趣分析</ion-button>
 
+  @if(!planMessage?.complete){
+    <div>{{planMessage?.content}}</div>
+  }
+  @if(planMessage?.complete){
+    <comp-markmap [markdown]="markmapResult"></comp-markmap>
+  }
 </ion-content>

+ 32 - 5
AIart-app/src/app/tab4/tab4.page.ts

@@ -3,24 +3,34 @@ import { IonHeader, IonToolbar, IonTitle, IonContent, ModalController, IonButton
 import { ExploreContainerComponent } from '../explore-container/explore-container.component';
 import { Router } from '@angular/router';
 import { ChatPanelOptions, FmChatModalInput, FmodeChat, FmodeChatMessage, openChatPanelModal } from 'fmode-ng';
+import { CompMarkmapComponent } from '../comp-markmap/comp-markmap.component';
+import { CloudObject } from 'src/lib/ncloud';
 
 @Component({
   selector: 'app-tab4',
   templateUrl: 'tab4.page.html',
   styleUrls: ['tab4.page.scss'],
   standalone: true,
-  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent, IonButton, FmChatModalInput,],
+  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent, IonButton, FmChatModalInput,
+    CompMarkmapComponent
+  ],
 })
 export class tab4Page {
 
   constructor(
     private modalCtrl: ModalController,
     private router: Router,
+
   ) {
 
   }
   title: string = "123"
-  /** 示例:问诊ChatPanel面板 */
+
+  /** 展示计划结果Markdown文件 */
+  isComplete:boolean = false;
+  planMessage:any
+  markmapResult:string = "";
+  /** 示例:兴趣规划聊天ChatPanel面板 */
   openInquiry() {
     localStorage.setItem("company", "E4KpGvTEto")
     let options: ChatPanelOptions = {
@@ -49,7 +59,14 @@ export class tab4Page {
 - 等待学生反馈意见,进入下一阶段
 3. 规划调整与完善
 根据反馈对学习规划进行调整优化,并给出最终的详细规划方案。
-- 完成规划方案时,请在消息结尾附带: [完成]
+- 完成规划方案时,请直接用markmap格式编写方案,具体格式严格按照
+\`\`\` markdown
+# XXX计划
+## 二级
+- 三级
+- 三级
+\`\`\`
+请直接返回markdown内生成的方案内容,不用有其他的赘述。并且返回的内容结尾要有[完成]
 
 # 开始话语
 当您准备好了,可以以一个兴趣学习规划师的身份,向来访的学生打招呼。`);
@@ -58,8 +75,18 @@ export class tab4Page {
         console.log("onMessage", message)
         let content: any = message?.content
         if (typeof content == "string") {
-          if (content?.indexOf("[完成]") > -1) {
-            console.log("兴趣分析已完成")
+          if (content?.indexOf("```") > -1) {
+            console.log("兴趣分析已完成");
+            let markMapContent = content.split("```")[1].slice(9)
+            this.markmapResult = markMapContent
+            let plan = new CloudObject("GoPlan");
+            let now = new Date();
+            plan.set({
+              title:"计划"+now.getFullYear()+"-"+now.getMonth()+1+"-"+now.getDate()+"-"+now.getTime(),
+              markmap:markMapContent
+            })
+            plan.save();
+            this.planMessage = message
           }
         }
       },

+ 9 - 0
AIart-app/src/assets/markmap/default.min.css

@@ -0,0 +1,9 @@
+/*!
+  Theme: Default
+  Description: Original highlight.js style
+  Author: (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
+  Maintainer: @highlightjs/core-team
+  Website: https://highlightjs.org/
+  License: see project LICENSE
+  Touched: 2021
+*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:#444a}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}

BIN
AIart-app/src/assets/markmap/fonts/KaTeX_AMS-Regular.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_AMS-Regular.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_AMS-Regular.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Bold.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Bold.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Bold.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Regular.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Regular.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Caligraphic-Regular.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Bold.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Bold.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Bold.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Regular.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Regular.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Fraktur-Regular.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-Bold.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-Bold.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-Bold.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-BoldItalic.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-BoldItalic.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-BoldItalic.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-Italic.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-Italic.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-Italic.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-Regular.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-Regular.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Main-Regular.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Math-BoldItalic.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Math-BoldItalic.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Math-BoldItalic.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Math-Italic.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Math-Italic.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Math-Italic.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Bold.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Bold.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Bold.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Italic.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Italic.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Italic.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Regular.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Regular.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_SansSerif-Regular.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Script-Regular.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Script-Regular.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Script-Regular.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size1-Regular.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size1-Regular.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size1-Regular.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size2-Regular.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size2-Regular.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size2-Regular.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size3-Regular.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size3-Regular.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size3-Regular.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size4-Regular.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size4-Regular.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Size4-Regular.woff2


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Typewriter-Regular.ttf


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Typewriter-Regular.woff


BIN
AIart-app/src/assets/markmap/fonts/KaTeX_Typewriter-Regular.woff2


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
AIart-app/src/assets/markmap/katex.min.css


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 4 - 0
AIart-app/src/assets/markmap/webfontloader.js


+ 5 - 0
AIart-app/src/index.html

@@ -17,6 +17,11 @@
   <!-- add to homescreen for ios -->
   <meta name="apple-mobile-web-app-capable" content="yes" />
   <meta name="apple-mobile-web-app-status-bar-style" content="black" />
+
+  <!-- MarkMap Assets -->
+   <!-- <link rel="stylesheet" href="assets/markmap/default.min.css">
+   <link rel="stylesheet" href="assets/markmap/katex.min.css">
+   <script src="assets/markmap/webfontloader.js"></script> -->
 </head>
 
 <body>

+ 2 - 2
AIart-app/tsconfig.json

@@ -18,9 +18,9 @@
     "moduleResolution": "node",
     "importHelpers": true,
     "target": "es2022",
-    "module": "es2020",
+    "module": "es2022",
     "lib": [
-      "es2018",
+      "es2022",
       "dom"
     ],
     "useDefineForClassFields": false

+ 0 - 0
node_modules/katex/dist/katex.min.css


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä