3 Commits

Author SHA1 Message Date
1dd59f7caa feat(tags): multi-select tag list + dedup create + tag_sync endpoint
- tag_form.dspy: rewrite as multi-select checkbox list (clickable rows with toggle)
  + input field for new tag with + button (calls /api/tag/create with dedup)
  + submit button calls /api/tag/sync to sync media_tags
  + dynamically add new tag row to list after creation
- media_cards.dspy: read tags from media_tags table instead of metadata
- init.py: tag_create_handler adds dedup (check existing by kb_id+name)
- init.py: new tag_sync_handler (full sync: delete old + insert selected)
- config.json: add /api/tag/sync route
2026-08-05 15:36:44 +08:00
267fd276c5 fix: escape literal % in LIKE patterns (aiomysql %-format conflict -> TypeError) 2026-08-05 11:55:18 +08:00
3cb591ed92 feat: detail.ui face/voiceprint media card popups (DynamicColumn, image/audio playback) + tag buttons on cards and file list rows (tag_form.dspy -> add_tag.dspy, refresh media panel) 2026-08-05 10:55:50 +08:00