56 lines
1.7 KiB
Go
56 lines
1.7 KiB
Go
|
|
package main
|
|||
|
|
|
|||
|
|
// search.go 全局搜索(Ctrl+K 命令面板):项目 / 待办 / 工单 / AI 会话各取前 8 条。
|
|||
|
|
|
|||
|
|
import "strings"
|
|||
|
|
|
|||
|
|
// escapeLike 转义 LIKE 通配符,配合 ESCAPE '\' 使用。
|
|||
|
|
func escapeLike(s string) string {
|
|||
|
|
r := strings.NewReplacer(`\`, `\\`, `%`, `\%`, `_`, `\_`)
|
|||
|
|
return r.Replace(s)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (a *App) GlobalSearch(q string) ([]SearchHit, error) {
|
|||
|
|
if e := a.ready(); e != nil {
|
|||
|
|
return nil, e
|
|||
|
|
}
|
|||
|
|
q = strings.TrimSpace(q)
|
|||
|
|
out := []SearchHit{}
|
|||
|
|
if q == "" {
|
|||
|
|
return out, nil
|
|||
|
|
}
|
|||
|
|
pat := "%" + escapeLike(q) + "%"
|
|||
|
|
type src struct {
|
|||
|
|
kind, query string
|
|||
|
|
args int // pat 占位数量
|
|||
|
|
}
|
|||
|
|
for _, s := range []src{
|
|||
|
|
{"project", `SELECT id,name,path,'' FROM projects WHERE name LIKE ? ESCAPE '\' OR path LIKE ? ESCAPE '\' ORDER BY updated_at DESC LIMIT 8`, 2},
|
|||
|
|
{"todo", `SELECT id,title,status,priority FROM todos WHERE deleted=0 AND (title LIKE ? ESCAPE '\' OR content LIKE ? ESCAPE '\') ORDER BY updated_at DESC LIMIT 8`, 2},
|
|||
|
|
{"ticket", `SELECT id,title,status,priority FROM tickets WHERE deleted=0 AND (title LIKE ? ESCAPE '\' OR description LIKE ? ESCAPE '\') ORDER BY updated_at DESC LIMIT 8`, 2},
|
|||
|
|
{"conversation", `SELECT id,title,provider,'' FROM ai_conversations WHERE title LIKE ? ESCAPE '\' ORDER BY updated_at DESC LIMIT 8`, 1},
|
|||
|
|
} {
|
|||
|
|
args := make([]any, s.args)
|
|||
|
|
for i := range args {
|
|||
|
|
args[i] = pat
|
|||
|
|
}
|
|||
|
|
rows, e := a.store.db.Query(s.query, args...)
|
|||
|
|
if e != nil {
|
|||
|
|
return nil, e
|
|||
|
|
}
|
|||
|
|
for rows.Next() {
|
|||
|
|
h := SearchHit{Kind: s.kind}
|
|||
|
|
if e := rows.Scan(&h.ID, &h.Title, &h.Sub, &h.Extra); e != nil {
|
|||
|
|
rows.Close()
|
|||
|
|
return nil, e
|
|||
|
|
}
|
|||
|
|
out = append(out, h)
|
|||
|
|
}
|
|||
|
|
rows.Close()
|
|||
|
|
if e := rows.Err(); e != nil {
|
|||
|
|
return nil, e
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return out, nil
|
|||
|
|
}
|