mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-05-03 00:12:42 +08:00
🎨 支持基于文档复习闪卡 https://github.com/siyuan-note/siyuan/issues/7057
This commit is contained in:
parent
86a62879ea
commit
26e62e1eda
@ -66,6 +66,33 @@ func reviewRiffCard(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTreeRiffDueCards(c *gin.Context) {
|
||||||
|
ret := gulu.Ret.NewResult()
|
||||||
|
defer c.JSON(http.StatusOK, ret)
|
||||||
|
|
||||||
|
arg, ok := util.JsonArg(c, ret)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rootID := arg["rootID"].(string)
|
||||||
|
err := model.AddTreeFlashcards(rootID)
|
||||||
|
if nil != err {
|
||||||
|
ret.Code = -1
|
||||||
|
ret.Msg = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cards, err := model.GetTreeDueFlashcards(rootID)
|
||||||
|
if nil != err {
|
||||||
|
ret.Code = -1
|
||||||
|
ret.Msg = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.Data = cards
|
||||||
|
}
|
||||||
|
|
||||||
func getRiffDueCards(c *gin.Context) {
|
func getRiffDueCards(c *gin.Context) {
|
||||||
ret := gulu.Ret.NewResult()
|
ret := gulu.Ret.NewResult()
|
||||||
defer c.JSON(http.StatusOK, ret)
|
defer c.JSON(http.StatusOK, ret)
|
||||||
|
@ -311,6 +311,7 @@ func ServeAPI(ginServer *gin.Engine) {
|
|||||||
ginServer.Handle("POST", "/api/riff/addRiffCards", model.CheckAuth, addRiffCards)
|
ginServer.Handle("POST", "/api/riff/addRiffCards", model.CheckAuth, addRiffCards)
|
||||||
ginServer.Handle("POST", "/api/riff/removeRiffCards", model.CheckAuth, removeRiffCards)
|
ginServer.Handle("POST", "/api/riff/removeRiffCards", model.CheckAuth, removeRiffCards)
|
||||||
ginServer.Handle("POST", "/api/riff/getRiffDueCards", model.CheckAuth, getRiffDueCards)
|
ginServer.Handle("POST", "/api/riff/getRiffDueCards", model.CheckAuth, getRiffDueCards)
|
||||||
|
ginServer.Handle("POST", "/api/riff/getTreeRiffDueCards", model.CheckAuth, getTreeRiffDueCards)
|
||||||
ginServer.Handle("POST", "/api/riff/reviewRiffCard", model.CheckAuth, reviewRiffCard)
|
ginServer.Handle("POST", "/api/riff/reviewRiffCard", model.CheckAuth, reviewRiffCard)
|
||||||
ginServer.Handle("POST", "/api/riff/getRiffCards", model.CheckAuth, getRiffCards)
|
ginServer.Handle("POST", "/api/riff/getRiffCards", model.CheckAuth, getRiffCards)
|
||||||
|
|
||||||
|
@ -122,6 +122,56 @@ type Flashcard struct {
|
|||||||
NextDues map[riff.Rating]string `json:"nextDues"`
|
NextDues map[riff.Rating]string `json:"nextDues"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetTreeDueFlashcards(rootID string) (ret []*Flashcard, err error) {
|
||||||
|
deckLock.Lock()
|
||||||
|
defer deckLock.Unlock()
|
||||||
|
|
||||||
|
if syncingStorages {
|
||||||
|
err = errors.New(Conf.Language(81))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
deck := Decks[builtinDeckID]
|
||||||
|
if nil == deck {
|
||||||
|
logging.LogWarnf("builtin deck not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tree, err := loadTreeByBlockID(rootID)
|
||||||
|
if nil != err {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
blockIDs := map[string]bool{}
|
||||||
|
for n := tree.Root.FirstChild; nil != n; n = n.Next {
|
||||||
|
blockIDs[n.ID] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
cards := deck.Dues()
|
||||||
|
now := time.Now()
|
||||||
|
for _, card := range cards {
|
||||||
|
blockID := card.BlockID()
|
||||||
|
if !blockIDs[blockID] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
nextDues := map[riff.Rating]string{}
|
||||||
|
for rating, due := range card.NextDues() {
|
||||||
|
nextDues[rating] = strings.TrimSpace(humanize.RelTime(due, now, "", ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, &Flashcard{
|
||||||
|
DeckID: builtinDeckID,
|
||||||
|
BlockID: blockID,
|
||||||
|
NextDues: nextDues,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if 1 > len(ret) {
|
||||||
|
ret = []*Flashcard{}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func GetDueFlashcards(deckID string) (ret []*Flashcard, err error) {
|
func GetDueFlashcards(deckID string) (ret []*Flashcard, err error) {
|
||||||
deckLock.Lock()
|
deckLock.Lock()
|
||||||
defer deckLock.Unlock()
|
defer deckLock.Unlock()
|
||||||
@ -286,6 +336,19 @@ func RemoveFlashcards(deckID string, blockIDs []string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AddTreeFlashcards(rootID string) (err error) {
|
||||||
|
tree, err := loadTreeByBlockID(rootID)
|
||||||
|
if nil != err {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var blockIDs []string
|
||||||
|
for n := tree.Root.FirstChild; nil != n; n = n.Next {
|
||||||
|
blockIDs = append(blockIDs, n.ID)
|
||||||
|
}
|
||||||
|
return AddFlashcards(builtinDeckID, blockIDs)
|
||||||
|
}
|
||||||
|
|
||||||
func AddFlashcards(deckID string, blockIDs []string) (err error) {
|
func AddFlashcards(deckID string, blockIDs []string) (err error) {
|
||||||
deckLock.Lock()
|
deckLock.Lock()
|
||||||
defer deckLock.Unlock()
|
defer deckLock.Unlock()
|
||||||
@ -295,7 +358,6 @@ func AddFlashcards(deckID string, blockIDs []string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var rootIDs []string
|
|
||||||
blockRoots := map[string]string{}
|
blockRoots := map[string]string{}
|
||||||
for _, blockID := range blockIDs {
|
for _, blockID := range blockIDs {
|
||||||
bt := treenode.GetBlockTree(blockID)
|
bt := treenode.GetBlockTree(blockID)
|
||||||
@ -303,10 +365,8 @@ func AddFlashcards(deckID string, blockIDs []string) (err error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
rootIDs = append(rootIDs, bt.RootID)
|
|
||||||
blockRoots[blockID] = bt.RootID
|
blockRoots[blockID] = bt.RootID
|
||||||
}
|
}
|
||||||
rootIDs = gulu.Str.RemoveDuplicatedElem(rootIDs)
|
|
||||||
|
|
||||||
trees := map[string]*parse.Tree{}
|
trees := map[string]*parse.Tree{}
|
||||||
for _, blockID := range blockIDs {
|
for _, blockID := range blockIDs {
|
||||||
@ -353,16 +413,19 @@ func AddFlashcards(deckID string, blockIDs []string) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deck := Decks[deckID]
|
deck := Decks[deckID]
|
||||||
if nil != deck {
|
if nil == deck {
|
||||||
for _, blockID := range blockIDs {
|
logging.LogWarnf("deck [%s] not found", deckID)
|
||||||
cardID := ast.NewNodeID()
|
return
|
||||||
deck.AddCard(cardID, blockID)
|
}
|
||||||
}
|
|
||||||
err = deck.Save()
|
for _, blockID := range blockIDs {
|
||||||
if nil != err {
|
cardID := ast.NewNodeID()
|
||||||
logging.LogErrorf("save deck [%s] failed: %s", deckID, err)
|
deck.AddCard(cardID, blockID)
|
||||||
return
|
}
|
||||||
}
|
err = deck.Save()
|
||||||
|
if nil != err {
|
||||||
|
logging.LogErrorf("save deck [%s] failed: %s", deckID, err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -408,8 +471,25 @@ func LoadFlashcards() {
|
|||||||
Decks[deck.ID] = deck
|
Decks[deck.ID] = deck
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 支持基于文档复习闪卡 https://github.com/siyuan-note/siyuan/issues/7057
|
||||||
|
foudBuiltinDeck := false
|
||||||
|
for _, deck := range Decks {
|
||||||
|
if builtinDeckID == deck.ID {
|
||||||
|
foudBuiltinDeck = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !foudBuiltinDeck {
|
||||||
|
deck, createErr := createDeck0("Built-in Deck", builtinDeckID)
|
||||||
|
if nil == createErr {
|
||||||
|
Decks[deck.ID] = deck
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const builtinDeckID = "20230218211946-2kw8jgx"
|
||||||
|
|
||||||
func RenameDeck(deckID, name string) (err error) {
|
func RenameDeck(deckID, name string) (err error) {
|
||||||
deckLock.Lock()
|
deckLock.Lock()
|
||||||
defer deckLock.Unlock()
|
defer deckLock.Unlock()
|
||||||
@ -469,8 +549,13 @@ func createDeck(name string) (deck *riff.Deck, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
riffSavePath := getRiffDir()
|
|
||||||
deckID := ast.NewNodeID()
|
deckID := ast.NewNodeID()
|
||||||
|
deck, err = createDeck0(name, deckID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDeck0(name string, deckID string) (deck *riff.Deck, err error) {
|
||||||
|
riffSavePath := getRiffDir()
|
||||||
deck, err = riff.LoadDeck(riffSavePath, deckID)
|
deck, err = riff.LoadDeck(riffSavePath, deckID)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
logging.LogErrorf("load deck [%s] failed: %s", deckID, err)
|
logging.LogErrorf("load deck [%s] failed: %s", deckID, err)
|
||||||
@ -491,6 +576,10 @@ func GetDecks() (decks []*riff.Deck) {
|
|||||||
defer deckLock.Unlock()
|
defer deckLock.Unlock()
|
||||||
|
|
||||||
for _, deck := range Decks {
|
for _, deck := range Decks {
|
||||||
|
if deck.ID == builtinDeckID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
decks = append(decks, deck)
|
decks = append(decks, deck)
|
||||||
}
|
}
|
||||||
if 1 > len(decks) {
|
if 1 > len(decks) {
|
||||||
|
Loading…
Reference in New Issue
Block a user