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
+61
View File
@@ -1235,6 +1235,67 @@ func (l *LocalDB) GetLastComponentSyncError() string {
}
const openConfigUUIDsKey = "open_config_uuids"
// GetOpenConfigUUIDs returns UUIDs of all configurations currently open in the configurator.
func (l *LocalDB) GetOpenConfigUUIDs() []string {
value, ok := l.getAppSettingValue(openConfigUUIDsKey)
if !ok || value == "" {
return nil
}
var uuids []string
if err := json.Unmarshal([]byte(value), &uuids); err != nil {
return nil
}
return uuids
}
// AddOpenConfigUUID records that a configuration is open in the configurator.
func (l *LocalDB) AddOpenConfigUUID(uuid string) error {
uuids := l.GetOpenConfigUUIDs()
for _, u := range uuids {
if u == uuid {
return nil
}
}
uuids = append(uuids, uuid)
raw, err := json.Marshal(uuids)
if err != nil {
return err
}
return l.db.Exec(`
INSERT INTO app_settings (key, value, updated_at)
VALUES (?, ?, ?)
ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at
`, openConfigUUIDsKey, string(raw), time.Now().Format(time.RFC3339)).Error
}
// RemoveOpenConfigUUID records that a configuration is no longer open in the configurator.
func (l *LocalDB) RemoveOpenConfigUUID(uuid string) error {
uuids := l.GetOpenConfigUUIDs()
filtered := uuids[:0]
for _, u := range uuids {
if u != uuid {
filtered = append(filtered, u)
}
}
var raw []byte
var err error
if len(filtered) == 0 {
raw = []byte("[]")
} else {
raw, err = json.Marshal(filtered)
if err != nil {
return err
}
}
return l.db.Exec(`
INSERT INTO app_settings (key, value, updated_at)
VALUES (?, ?, ?)
ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at
`, openConfigUUIDsKey, string(raw), time.Now().Format(time.RFC3339)).Error
}
// CountLocalPricelists returns the number of local pricelists
func (l *LocalDB) CountLocalPricelists() int64 {
var count int64