Przeglądaj źródła

:recycle: 重构 `文件历史` 查询 https://github.com/siyuan-note/siyuan/issues/6504

Liang Ding 2 lat temu
rodzic
commit
24edac891e
4 zmienionych plików z 108 dodań i 0 usunięć
  1. 31 0
      kernel/api/history.go
  2. 1 0
      kernel/api/router.go
  3. 51 0
      kernel/model/history.go
  4. 25 0
      kernel/sql/history.go

+ 31 - 0
kernel/api/history.go

@@ -61,6 +61,37 @@ func searchHistory(c *gin.Context) {
 	}
 }
 
+func getHistoryItems(c *gin.Context) {
+	ret := gulu.Ret.NewResult()
+	defer c.JSON(http.StatusOK, ret)
+
+	arg, ok := util.JsonArg(c, ret)
+	if !ok {
+		return
+	}
+
+	created := arg["created"].(string)
+
+	notebook := ""
+	if nil != arg["notebook"] {
+		notebook = arg["notebook"].(string)
+	}
+	typ := model.HistoryTypeDoc
+	if nil != arg["type"] {
+		typ = int(arg["type"].(float64))
+	}
+
+	query := arg["query"].(string)
+	op := "all"
+	if nil != arg["op"] {
+		op = arg["op"].(string)
+	}
+	histories := model.FullTextSearchHistoryItems(created, query, notebook, op, typ)
+	ret.Data = map[string]interface{}{
+		"items": histories,
+	}
+}
+
 func reindexHistory(c *gin.Context) {
 	ret := gulu.Ret.NewResult()
 	defer c.JSON(http.StatusOK, ret)

+ 1 - 0
kernel/api/router.go

@@ -111,6 +111,7 @@ func ServeAPI(ginServer *gin.Engine) {
 	ginServer.Handle("POST", "/api/history/clearWorkspaceHistory", model.CheckAuth, model.CheckReadonly, clearWorkspaceHistory)
 	ginServer.Handle("POST", "/api/history/reindexHistory", model.CheckAuth, model.CheckReadonly, reindexHistory)
 	ginServer.Handle("POST", "/api/history/searchHistory", model.CheckAuth, model.CheckReadonly, searchHistory)
+	ginServer.Handle("POST", "/api/history/getHistoryItems", model.CheckAuth, model.CheckReadonly, getHistoryItems)
 
 	ginServer.Handle("POST", "/api/outline/getDocOutline", model.CheckAuth, getDocOutline)
 	ginServer.Handle("POST", "/api/bookmark/getBookmark", model.CheckAuth, getBookmark)

+ 51 - 0
kernel/model/history.go

@@ -360,6 +360,38 @@ func FullTextSearchHistory(query, box, op string, typ, page int) (ret []string,
 	return
 }
 
+func FullTextSearchHistoryItems(created, query, box, op string, typ int) (ret []*HistoryItem) {
+	query = gulu.Str.RemoveInvisible(query)
+	if "" != query {
+		query = stringQuery(query)
+	}
+
+	table := "histories_fts_case_insensitive"
+	stmt := "SELECT * FROM " + table + " WHERE "
+	if "" != query {
+		stmt += table + " MATCH '{title content}:(" + query + ")'"
+	} else {
+		stmt += "1=1"
+	}
+
+	if HistoryTypeDocName == typ {
+		stmt = strings.ReplaceAll(stmt, "{title content}", "{title}")
+	}
+
+	if HistoryTypeDocName == typ || HistoryTypeDoc == typ {
+		if "all" != op {
+			stmt += " AND op = '" + op + "'"
+		}
+		stmt += " AND path LIKE '%/" + box + "/%' AND path LIKE '%.sy'"
+	} else if HistoryTypeAsset == typ {
+		stmt += " AND path LIKE '%/assets/%'"
+	}
+	stmt += " AND created = '" + created + "' ORDER BY created DESC LIMIT " + fmt.Sprintf("%d", Conf.Search.Limit)
+	sqlHistories := sql.SelectHistoriesRawStmt(stmt)
+	ret = fromSQLHistories(sqlHistories)
+	return
+}
+
 func GetNotebookHistory() (ret []*History, err error) {
 	ret = []*History{}
 
@@ -656,3 +688,22 @@ func indexHistoryDir(name string, luteEngine *lute.Lute) {
 	}
 	return
 }
+
+func fromSQLHistories(sqlHistories []*sql.History) (ret []*HistoryItem) {
+	if 1 > len(sqlHistories) {
+		ret = []*HistoryItem{}
+		return
+	}
+
+	for _, sqlHistory := range sqlHistories {
+		item := &HistoryItem{
+			Title: sqlHistory.Title,
+			Path:  filepath.Join(util.HistoryDir, sqlHistory.Path),
+		}
+		if HistoryTypeAsset == sqlHistory.Type {
+			item.Path = filepath.ToSlash(strings.TrimPrefix(item.Path, util.WorkspaceDir))
+		}
+		ret = append(ret, item)
+	}
+	return
+}

+ 25 - 0
kernel/sql/history.go

@@ -69,6 +69,31 @@ func QueryHistory(stmt string) (ret []map[string]interface{}, err error) {
 	return
 }
 
+func SelectHistoriesRawStmt(stmt string) (ret []*History) {
+	rows, err := historyDB.Query(stmt)
+	if nil != err {
+		logging.LogWarnf("sql query [%s] failed: %s", stmt, err)
+		return
+	}
+	defer rows.Close()
+	for rows.Next() {
+		if history := scanHistoryRows(rows); nil != history {
+			ret = append(ret, history)
+		}
+	}
+	return
+}
+
+func scanHistoryRows(rows *sql.Rows) (ret *History) {
+	var history History
+	if err := rows.Scan(&history.Type, &history.Op, &history.Title, &history.Content, &history.Path, &history.Created); nil != err {
+		logging.LogErrorf("query scan field failed: %s\n%s", err, logging.ShortStack())
+		return
+	}
+	ret = &history
+	return
+}
+
 func queryHistory(query string, args ...interface{}) (*sql.Rows, error) {
 	query = strings.TrimSpace(query)
 	if "" == query {