From 21fe55510e4ab515ffb71cd684bee0431855d63b Mon Sep 17 00:00:00 2001 From: liufree Date: Tue, 14 Oct 2025 23:21:14 +0800 Subject: [PATCH] feat: support mermorycard view --- src/pages/bases/DashMemoryCardView.tsx | 90 ++++++++++++++++++++------ 1 file changed, 69 insertions(+), 21 deletions(-) diff --git a/src/pages/bases/DashMemoryCardView.tsx b/src/pages/bases/DashMemoryCardView.tsx index d4bf549..86c9107 100644 --- a/src/pages/bases/DashMemoryCardView.tsx +++ b/src/pages/bases/DashMemoryCardView.tsx @@ -3,12 +3,16 @@ import React, {useEffect, useRef, useState} from 'react'; import {createRoot} from 'react-dom/client'; import {Button, Space, Card, Modal, notification} from 'antd'; import dayjs from 'dayjs'; +import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'; +dayjs.extend(isSameOrBefore); export const MemoryCardViewType = 'dash-memory-card-view'; export class DashMemoryCardView extends BasesView { readonly type = MemoryCardViewType; private containerEl: HTMLElement; + private sortedCards: any[] = []; + private currentIndex: number = 0; constructor(controller: QueryController, parentEl: HTMLElement) { super(controller); @@ -18,16 +22,33 @@ export class DashMemoryCardView extends BasesView { public async onDataUpdated(): Promise { this.containerEl.empty(); const allCards = this.data.data; - let cardData = allCards[0]; - if (allCards.length > 1) { - const sorted = allCards - .map(card => ({card, due: card.getValue('properties.sr-due')})) - .filter(item => item.due) - .sort((a, b) => dayjs(a.due).valueOf() - dayjs(b.due).valueOf()); - if (sorted.length > 0) { - cardData = sorted[0].card; + // 按 sr-due 升序排序 + this.sortedCards = [...allCards] + .map(card => ({card, due: card.getValue('properties.sr-due')})) + .sort((a, b) => { + if (!a.due && !b.due) return 0; + if (!a.due) return 1; + if (!b.due) return -1; + return dayjs(a.due).valueOf() - dayjs(b.due).valueOf(); + }) + .map(item => item.card); + // 找到 sr-due 最近的卡片 + let idx = 0; + const now = dayjs(); + for (let i = 0; i < this.sortedCards.length; i++) { + const due = this.sortedCards[i].getValue('properties.sr-due'); + if (due && dayjs(due).isSameOrBefore(now, 'day')) { + idx = i; + break; } } + this.currentIndex = idx; + this.renderMemoryCard(); + } + + private async renderMemoryCard() { + const cardData = this.sortedCards[this.currentIndex]; + if (!cardData) return; const filePath = cardData?.getValue('file.path'); const filePathStr = typeof filePath === 'string' ? filePath : filePath?.toString() || ''; let markdownStr = ''; @@ -46,9 +67,36 @@ export class DashMemoryCardView extends BasesView { } const container = this.containerEl.createDiv(); const root = createRoot(container); - root.render(); + root.render( + + ); } + + private handlePrev = () => { + if (this.currentIndex > 0) { + this.currentIndex--; + this.containerEl.empty(); + this.renderMemoryCard(); + } + }; + + private handleNext = () => { + if (this.currentIndex < this.sortedCards.length - 1) { + this.currentIndex++; + this.containerEl.empty(); + this.renderMemoryCard(); + } + }; } interface MemoryCardProps { @@ -57,6 +105,10 @@ interface MemoryCardProps { filePath: string; title: string; frontmatter?: Record; + onPrev: () => void; + onNext: () => void; + isPrevDisabled: boolean; + isNextDisabled: boolean; } const updateSRFrontmatter = async ( @@ -107,7 +159,7 @@ const updateSRFrontmatter = async ( return false; }; -const MemoryCard: React.FC = ({markdown, app, filePath, title, frontmatter}) => { +const MemoryCard: React.FC = ({markdown, app, filePath, title, frontmatter, onPrev, onNext, isPrevDisabled, isNextDisabled}) => { const mdRef = useRef(null); const [rendered, setRendered] = useState(false); const [fm, setFM] = useState(frontmatter); @@ -156,22 +208,20 @@ const MemoryCard: React.FC = ({markdown, app, filePath, title, <>
- {/* 左侧箭头按钮 */}