tab2.page.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import { Component, CUSTOM_ELEMENTS_SCHEMA, ViewChild } from '@angular/core';
  2. import { IonHeader, IonToolbar, IonTitle, IonContent, IonSearchbar, IonIcon, IonTabs, IonLabel, IonTabButton, IonTabBar, IonCard, IonCardHeader, IonCardContent, IonCardTitle, IonCardSubtitle, IonButton, IonTextarea, AlertController } from '@ionic/angular/standalone';
  3. import { FormsModule } from '@angular/forms';
  4. import { ExploreContainerComponent } from '../explore-container/explore-container.component';
  5. import { EditTagComponent } from '../edit-tag/edit-tag.component'
  6. import { EditRatingStarComponent } from '../edit-rating-star/edit-rating-star.component';
  7. import { CompMarkmapComponent } from '../comp-markmap/comp-markmap.component';
  8. import { CloudQuery } from 'src/lib/ncloud';
  9. @Component({
  10. selector: 'app-tab2',
  11. templateUrl: 'tab2.page.html',
  12. styleUrls: ['tab2.page.scss'],
  13. standalone: true,
  14. schemas: [CUSTOM_ELEMENTS_SCHEMA],
  15. imports: [
  16. IonHeader,
  17. IonToolbar,
  18. IonTitle,
  19. IonContent,
  20. ExploreContainerComponent,
  21. EditTagComponent,
  22. EditRatingStarComponent,
  23. IonSearchbar,
  24. IonIcon,
  25. IonTabs,
  26. IonLabel,
  27. IonTabButton,
  28. IonTabBar,
  29. CompMarkmapComponent,
  30. IonCardSubtitle,
  31. IonCard,
  32. IonCardHeader,
  33. IonCardContent,
  34. IonCardTitle,
  35. IonButton,
  36. IonTextarea,
  37. FormsModule
  38. ]
  39. })
  40. export class Tab2Page {
  41. async loadMapList() {
  42. let query = new CloudQuery("GoPlan");
  43. this.mapListOnline = await query.find();
  44. if (this.mapListOnline.length > 0) {
  45. this.currentIndex = 0;
  46. this.refreshMarkmap();
  47. }
  48. }
  49. mapListOnline: any = []
  50. mapList = [
  51. {
  52. title: "demo", content: ` ---
  53. markmap:
  54. maxWidth: 300
  55. colorFreezeLevel: 2
  56. ---
  57. # markmap
  58. ## Links
  59. - <https://markmap.js.org/>
  60. - [GitHub](https://github.com/markmap/markmap)
  61. ## Related
  62. - [coc-markmap](https://github.com/markmap/coc-markmap)
  63. - [gatsby-remark-markmap](https://github.com/markmap/gatsby-remark-markmap)
  64. ## Features
  65. - links
  66. - **inline** ~~text~~ *styles*
  67. - multiline
  68. text
  69. - inline code
  70. - Katex - $x = {-b \pm \sqrt{b^2-4ac} \over 2a}$
  71. - This is a very very very very very very very very very very very very very very very long line.`},
  72. {
  73. title: "每日学习计划", content: `# 每日学习计划
  74. ## 时间
  75. ## 计划
  76. ## 总结
  77. `},
  78. {
  79. title: "每周学习计划", content: `# 每周学习计划
  80. ## 时间
  81. ## 计划
  82. ## 总结
  83. `}
  84. ]
  85. constructor(
  86. private alertController: AlertController
  87. ) {
  88. this.loadMapList();
  89. }
  90. currentScore: number = 0; // 初始分值
  91. handleScoreChange(newScore: number) {
  92. this.currentScore = newScore;
  93. console.log('新分值:', newScore); // 处理分值变化
  94. }
  95. currentIndex: number = 0;
  96. nextPlan() {
  97. if (this.currentIndex < this.mapListOnline.length - 1) {
  98. this.currentIndex++;
  99. this.refreshMarkmap();
  100. }
  101. }
  102. previousPlan() {
  103. if (this.currentIndex > 0) {
  104. this.currentIndex--;
  105. this.refreshMarkmap();
  106. }
  107. }
  108. @ViewChild(CompMarkmapComponent) markmapComponent?: CompMarkmapComponent;
  109. currentTitle: string = '';
  110. onTitleExtracted(title: string) {
  111. this.currentTitle = title;
  112. }
  113. refreshMarkmap() {
  114. setTimeout(() => {
  115. if (this.markmapComponent) {
  116. const markdown = this.mapListOnline[this.currentIndex].get('markmap');
  117. this.nodeStates = this.mapListOnline[this.currentIndex].get('nodeStates') || {};
  118. this.markmapComponent.markdown = markdown;
  119. this.markmapComponent.loadMarkMap();
  120. this.currentTitle = this.markmapComponent.extractTitle(markdown);
  121. }
  122. }, 100);
  123. }
  124. isEditing = false;
  125. editingMarkdown = '';
  126. editPlan() {
  127. this.isEditing = true;
  128. this.editingMarkdown = this.mapListOnline[this.currentIndex].get('markmap');
  129. }
  130. cancelEdit() {
  131. this.isEditing = false;
  132. this.editingMarkdown = '';
  133. }
  134. async savePlan() {
  135. try {
  136. const currentPlan = this.mapListOnline[this.currentIndex];
  137. await currentPlan.set('markmap', this.editingMarkdown);
  138. await currentPlan.save();
  139. this.isEditing = false;
  140. this.refreshMarkmap();
  141. // 显示成功提示
  142. const toast = document.createElement('ion-toast');
  143. toast.message = '计划已保存';
  144. toast.duration = 2000;
  145. toast.position = 'bottom';
  146. document.body.appendChild(toast);
  147. await toast.present();
  148. } catch (error) {
  149. console.error('Error saving plan:', error);
  150. // 显示错误提示
  151. const toast = document.createElement('ion-toast');
  152. toast.message = '保存失败,请重试';
  153. toast.duration = 2000;
  154. toast.position = 'bottom';
  155. toast.color = 'danger';
  156. document.body.appendChild(toast);
  157. await toast.present();
  158. }
  159. }
  160. async confirmDelete() {
  161. const alert = await this.alertController.create({
  162. header: '确认删除',
  163. message: '是否删除该计划?删除后将无法恢复。',
  164. buttons: [
  165. {
  166. text: '取消',
  167. role: 'cancel',
  168. cssClass: 'secondary'
  169. },
  170. {
  171. text: '删除',
  172. role: 'destructive',
  173. handler: () => {
  174. this.deletePlan();
  175. }
  176. }
  177. ]
  178. });
  179. await alert.present();
  180. }
  181. async deletePlan() {
  182. try {
  183. const currentPlan = this.mapListOnline[this.currentIndex];
  184. if (!currentPlan) return;
  185. // 删除计划
  186. await currentPlan['destroy']();
  187. // 重新加载计划列表
  188. await this.loadMapList();
  189. // 显示成功提示
  190. const toast = document.createElement('ion-toast');
  191. toast.message = '计划已删除';
  192. toast.duration = 2000;
  193. toast.position = 'bottom';
  194. document.body.appendChild(toast);
  195. await toast.present();
  196. } catch (error) {
  197. console.error('Error deleting plan:', error);
  198. // 显示错误提示
  199. const toast = document.createElement('ion-toast');
  200. toast.message = '删除失败,请重试';
  201. toast.duration = 2000;
  202. toast.position = 'bottom';
  203. toast.color = 'danger';
  204. document.body.appendChild(toast);
  205. await toast.present();
  206. }
  207. }
  208. // 存储节点状态
  209. nodeStates: { [key: string]: boolean } = {};
  210. // 处理节点状态变化
  211. async onNodeStateChange(event: { nodeId: string, checked: boolean }) {
  212. this.nodeStates[event.nodeId] = event.checked;
  213. // 保存状态到数据库
  214. try {
  215. const currentPlan = this.mapListOnline[this.currentIndex];
  216. await currentPlan.set('nodeStates', this.nodeStates);
  217. await currentPlan.save();
  218. } catch (error) {
  219. console.error('Error saving node states:', error);
  220. }
  221. }
  222. }