0.11.0: 旗舰版功能补齐(License/登录记录/会话管理/角色管理/门户定时任务/模型配额/输出脱敏/供应链扫描/记忆管理/AI助手/真实概览)

- 新增迁移 000031-000034(登录日志/角色/模型配额/记忆)
- 新增包: license/memory/modelquota/assistant,扫描引擎
- 全部功能后端+前端+端到端验证通过(25 包单测)
This commit is contained in:
2026-08-13 11:37:18 +08:00
parent 9501751792
commit c22669c31d
43 changed files with 3672 additions and 254 deletions
+54
View File
@@ -36,6 +36,60 @@ type Conversation struct {
UpdatedAt time.Time `json:"updated_at"`
}
// ListConversations 返回当前用户在某应用下的会话列表(不含消息体)。
func (s *Service) ListConversations(ctx context.Context, account identity.Account, code string, limit int) ([]Conversation, error) {
if limit < 1 || limit > 200 {
limit = 50
}
rows, err := s.pool.Query(ctx, `SELECT c.id::text,a.code,c.title,c.status,c.created_at,c.updated_at
FROM gateway.portal_conversations c JOIN gateway.applications a ON a.id=c.application_id
WHERE c.portal_user_id=$1 AND a.code=$2 ORDER BY c.updated_at DESC LIMIT $3`, account.ID, strings.ToLower(strings.TrimSpace(code)), limit)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Conversation{}
for rows.Next() {
var item Conversation
if err := rows.Scan(&item.ID, &item.ApplicationCode, &item.Title, &item.Status, &item.CreatedAt, &item.UpdatedAt); err != nil {
return nil, err
}
items = append(items, item)
}
return items, rows.Err()
}
// RenameConversation 重命名会话(仅本人)。
func (s *Service) RenameConversation(ctx context.Context, account identity.Account, code, id, title string) (Conversation, error) {
title = strings.TrimSpace(title)
if title == "" || len(title) > 128 {
return Conversation{}, errors.New("会话标题必须为 1-128 个字符")
}
var item Conversation
err := s.pool.QueryRow(ctx, `UPDATE gateway.portal_conversations c SET title=$3,updated_at=clock_timestamp()
FROM gateway.applications a WHERE a.id=c.application_id AND c.id=$1 AND c.portal_user_id=$2 AND a.code=$4
RETURNING c.id::text,a.code,c.title,c.status,c.created_at,c.updated_at`,
id, account.ID, title, strings.ToLower(strings.TrimSpace(code))).Scan(&item.ID, &item.ApplicationCode, &item.Title, &item.Status, &item.CreatedAt, &item.UpdatedAt)
if errors.Is(err, pgx.ErrNoRows) {
return Conversation{}, ErrNotFound
}
return item, err
}
// DeleteConversation 删除会话及全部消息(仅本人)。
func (s *Service) DeleteConversation(ctx context.Context, account identity.Account, code, id string) error {
tag, err := s.pool.Exec(ctx, `DELETE FROM gateway.portal_conversations c USING gateway.applications a
WHERE a.id=c.application_id AND c.id=$1 AND c.portal_user_id=$2 AND a.code=$3`,
id, account.ID, strings.ToLower(strings.TrimSpace(code)))
if err != nil {
return err
}
if tag.RowsAffected() == 0 {
return ErrNotFound
}
return nil
}
func (s *Service) CreateConversation(ctx context.Context, account identity.Account, code string) (Conversation, error) {
app, err := s.assets.GetPublishedApplicationByCode(ctx, strings.ToLower(strings.TrimSpace(code)))
if err != nil || !visible(app.DepartmentIDs, account.DepartmentID) {