feat: индикатор присутствия в конфигурациях (иконка глаза)

Открытые конфигурации фиксируются в локальном SQLite (app_settings) и
передаются на сервер через qt_client_schema_state.open_config_uuids при
каждом цикле синхронизации. Списки конфигураций обогащаются полем viewers,
в таблицах отображается иконка глаза с подсказкой при наличии других
пользователей, открывших эту конфигурацию.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-06-30 00:56:06 +03:00
parent 9601619d1b
commit 50f0e4f76f
7 changed files with 208 additions and 4 deletions

View File

@@ -630,6 +630,56 @@ func (s *Service) backfillUsedPricelistItemCategories(pricelistRepo *repository.
}
}
// ListActiveViewersByConfigUUIDs returns a map of configUUID → []username for users
// who currently have those configs open (based on the last two sync cycles).
func (s *Service) ListActiveViewersByConfigUUIDs(uuids []string) (map[string][]string, error) {
if len(uuids) == 0 {
return map[string][]string{}, nil
}
mariaDB, err := s.getDB()
if err != nil || mariaDB == nil {
return map[string][]string{}, nil
}
selfUsername := strings.ToLower(strings.TrimSpace(s.localDB.GetDBUser()))
type row struct {
Username string `gorm:"column:username"`
OpenConfigJSON string `gorm:"column:open_config_uuids"`
}
var rows []row
if err := mariaDB.Raw(`
SELECT username, open_config_uuids
FROM qt_client_schema_state
WHERE open_config_uuids IS NOT NULL
AND open_config_uuids != '[]'
AND last_checked_at > NOW() - INTERVAL 10 MINUTE
`).Scan(&rows).Error; err != nil {
return map[string][]string{}, nil
}
wantSet := make(map[string]struct{}, len(uuids))
for _, u := range uuids {
wantSet[u] = struct{}{}
}
result := make(map[string][]string)
for _, r := range rows {
if strings.ToLower(strings.TrimSpace(r.Username)) == selfUsername {
continue
}
var openUUIDs []string
if err := json.Unmarshal([]byte(r.OpenConfigJSON), &openUUIDs); err != nil {
continue
}
for _, ou := range openUUIDs {
if _, ok := wantSet[ou]; ok {
result[ou] = append(result[ou], r.Username)
}
}
}
return result, nil
}
// ListUserSyncStatuses returns users who have recorded a client schema state check.
func (s *Service) ListUserSyncStatuses(onlineThreshold time.Duration) ([]UserSyncStatus, error) {
mariaDB, err := s.getDB()