mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-09-25 10:51:16 +02:00
Add files via upload
This commit is contained in:
@@ -361,6 +361,27 @@ func (db *DB) GetConversationLite(id string) (*Conversation, error) {
|
|||||||
return &conv, nil
|
return &conv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountConversations 统计对话数量。
|
||||||
|
func (db *DB) CountConversations(search string) (int, error) {
|
||||||
|
var count int
|
||||||
|
var err error
|
||||||
|
if search != "" {
|
||||||
|
searchPattern := "%" + search + "%"
|
||||||
|
err = db.QueryRow(
|
||||||
|
`SELECT COUNT(*) FROM conversations c
|
||||||
|
WHERE c.title LIKE ?
|
||||||
|
OR EXISTS (SELECT 1 FROM messages m WHERE m.conversation_id = c.id AND m.content LIKE ?)`,
|
||||||
|
searchPattern, searchPattern,
|
||||||
|
).Scan(&count)
|
||||||
|
} else {
|
||||||
|
err = db.QueryRow(`SELECT COUNT(*) FROM conversations`).Scan(&count)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("统计对话失败: %w", err)
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ListConversations 列出所有对话
|
// ListConversations 列出所有对话
|
||||||
func (db *DB) ListConversations(limit, offset int, search string) ([]*Conversation, error) {
|
func (db *DB) ListConversations(limit, offset int, search string) ([]*Conversation, error) {
|
||||||
var rows *sql.Rows
|
var rows *sql.Rows
|
||||||
@@ -430,6 +451,73 @@ func (db *DB) ListConversations(limit, offset int, search string) ([]*Conversati
|
|||||||
return conversations, nil
|
return conversations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ungroupedConversationsSQL = `
|
||||||
|
FROM conversations c
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM conversation_group_mappings cgm WHERE cgm.conversation_id = c.id
|
||||||
|
)`
|
||||||
|
|
||||||
|
// CountUngroupedConversations 统计不在任何分组中的对话数量。
|
||||||
|
func (db *DB) CountUngroupedConversations() (int, error) {
|
||||||
|
var count int
|
||||||
|
if err := db.QueryRow(`SELECT COUNT(*) ` + ungroupedConversationsSQL).Scan(&count); err != nil {
|
||||||
|
return 0, fmt.Errorf("统计未分组对话失败: %w", err)
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListUngroupedConversations 列出不在任何分组中的对话(最近对话侧栏)。
|
||||||
|
func (db *DB) ListUngroupedConversations(limit, offset int) ([]*Conversation, error) {
|
||||||
|
rows, err := db.Query(
|
||||||
|
`SELECT c.id, c.title, COALESCE(c.pinned, 0), c.created_at, c.updated_at, c.project_id `+
|
||||||
|
ungroupedConversationsSQL+`
|
||||||
|
ORDER BY c.updated_at DESC
|
||||||
|
LIMIT ? OFFSET ?`,
|
||||||
|
limit, offset,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("查询未分组对话失败: %w", err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var conversations []*Conversation
|
||||||
|
for rows.Next() {
|
||||||
|
var conv Conversation
|
||||||
|
var createdAt, updatedAt string
|
||||||
|
var pinned int
|
||||||
|
var projectID sql.NullString
|
||||||
|
|
||||||
|
if err := rows.Scan(&conv.ID, &conv.Title, &pinned, &createdAt, &updatedAt, &projectID); err != nil {
|
||||||
|
return nil, fmt.Errorf("扫描对话失败: %w", err)
|
||||||
|
}
|
||||||
|
if projectID.Valid {
|
||||||
|
conv.ProjectID = strings.TrimSpace(projectID.String)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err1, err2 error
|
||||||
|
conv.CreatedAt, err1 = time.Parse("2006-01-02 15:04:05.999999999-07:00", createdAt)
|
||||||
|
if err1 != nil {
|
||||||
|
conv.CreatedAt, err1 = time.Parse("2006-01-02 15:04:05", createdAt)
|
||||||
|
}
|
||||||
|
if err1 != nil {
|
||||||
|
conv.CreatedAt, _ = time.Parse(time.RFC3339, createdAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
conv.UpdatedAt, err2 = time.Parse("2006-01-02 15:04:05.999999999-07:00", updatedAt)
|
||||||
|
if err2 != nil {
|
||||||
|
conv.UpdatedAt, err2 = time.Parse("2006-01-02 15:04:05", updatedAt)
|
||||||
|
}
|
||||||
|
if err2 != nil {
|
||||||
|
conv.UpdatedAt, _ = time.Parse(time.RFC3339, updatedAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
conv.Pinned = pinned != 0
|
||||||
|
conversations = append(conversations, &conv)
|
||||||
|
}
|
||||||
|
|
||||||
|
return conversations, rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateConversationTitle 更新对话标题
|
// UpdateConversationTitle 更新对话标题
|
||||||
func (db *DB) UpdateConversationTitle(id, title string) error {
|
func (db *DB) UpdateConversationTitle(id, title string) error {
|
||||||
// 注意:不更新 updated_at,因为重命名操作不应该改变对话的更新时间
|
// 注意:不更新 updated_at,因为重命名操作不应该改变对话的更新时间
|
||||||
|
|||||||
@@ -112,10 +112,30 @@ func (db *DB) GetProject(id string) (*Project, error) {
|
|||||||
return &p, nil
|
return &p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountProjects 统计项目数量。
|
||||||
|
func (db *DB) CountProjects(status, search string) (int, error) {
|
||||||
|
query := `SELECT COUNT(*) FROM projects WHERE 1=1`
|
||||||
|
args := []interface{}{}
|
||||||
|
if s := strings.TrimSpace(status); s != "" {
|
||||||
|
query += " AND status = ?"
|
||||||
|
args = append(args, s)
|
||||||
|
}
|
||||||
|
if q := strings.TrimSpace(search); q != "" {
|
||||||
|
pattern := "%" + q + "%"
|
||||||
|
query += " AND (name LIKE ? OR COALESCE(description,'') LIKE ?)"
|
||||||
|
args = append(args, pattern, pattern)
|
||||||
|
}
|
||||||
|
var count int
|
||||||
|
if err := db.QueryRow(query, args...).Scan(&count); err != nil {
|
||||||
|
return 0, fmt.Errorf("统计项目失败: %w", err)
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ListProjects 列出项目。
|
// ListProjects 列出项目。
|
||||||
func (db *DB) ListProjects(status string, limit, offset int) ([]*Project, error) {
|
func (db *DB) ListProjects(status, search string, limit, offset int) ([]*Project, error) {
|
||||||
if limit <= 0 {
|
if limit <= 0 {
|
||||||
limit = 200
|
limit = 50
|
||||||
}
|
}
|
||||||
query := `SELECT id, name, COALESCE(description,''), COALESCE(scope_json,''), status, pinned, created_at, updated_at
|
query := `SELECT id, name, COALESCE(description,''), COALESCE(scope_json,''), status, pinned, created_at, updated_at
|
||||||
FROM projects WHERE 1=1`
|
FROM projects WHERE 1=1`
|
||||||
@@ -124,6 +144,11 @@ func (db *DB) ListProjects(status string, limit, offset int) ([]*Project, error)
|
|||||||
query += " AND status = ?"
|
query += " AND status = ?"
|
||||||
args = append(args, s)
|
args = append(args, s)
|
||||||
}
|
}
|
||||||
|
if q := strings.TrimSpace(search); q != "" {
|
||||||
|
pattern := "%" + q + "%"
|
||||||
|
query += " AND (name LIKE ? OR COALESCE(description,'') LIKE ?)"
|
||||||
|
args = append(args, pattern, pattern)
|
||||||
|
}
|
||||||
query += " ORDER BY pinned DESC, updated_at DESC LIMIT ? OFFSET ?"
|
query += " ORDER BY pinned DESC, updated_at DESC LIMIT ? OFFSET ?"
|
||||||
args = append(args, limit, offset)
|
args = append(args, limit, offset)
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func TestListProjectFacts_updatedAtJSON(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
projects, err := db.ListProjects("", 1, 0)
|
projects, err := db.ListProjects("", "", 1, 0)
|
||||||
if err != nil || len(projects) == 0 {
|
if err != nil || len(projects) == 0 {
|
||||||
t.Skip("no projects")
|
t.Skip("no projects")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user