diff --git a/.memory/worklog.json b/.memory/worklog.json index 28071e9..0366640 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -1,17 +1,5 @@ { "entries": [ - { - "files_changed": 1, - "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:docs: record subject pack deployment", - "ts": "2026-05-20T03:03:56Z", - "type": "session-heartbeat" - }, - { - "files_changed": 1, - "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:docs: record subject pack deployment", - "ts": "2026-05-20T03:13:56Z", - "type": "session-heartbeat" - }, { "files_changed": 1, "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:docs: record subject pack deployment", @@ -3226,6 +3214,19 @@ "message": "auto-save 2026-05-26 00:07 (+1, ~3)", "hash": "089a30d", "files_changed": 4 + }, + { + "ts": "2026-05-26T00:13:17+08:00", + "type": "commit", + "message": "auto-save 2026-05-26 00:13 (~8)", + "hash": "544087c", + "files_changed": 8 + }, + { + "ts": "2026-05-25T16:14:43Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 5 项未提交变更 · 最近提交:auto-save 2026-05-26 00:13 (~8)", + "files_changed": 5 } ] } diff --git a/scripts/deploy-prod-safe.sh b/scripts/deploy-prod-safe.sh index 13b8821..6cea61a 100755 --- a/scripts/deploy-prod-safe.sh +++ b/scripts/deploy-prod-safe.sh @@ -29,7 +29,12 @@ ssh "$HOST" "set -euo pipefail cat /tmp/skg-backup-warnings.log >&2 || true exit 1 } + if docker ps --format '{{.Names}}' | grep -qx skg-marketing-postgres; then + docker exec skg-marketing-postgres sh -lc 'pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB"' \ + | gzip > '$BACKUP_DIR/skg-marketing-postgres-'\$stamp'.sql.gz' + fi find '$BACKUP_DIR' -name 'skg-marketing-preserve-*.tgz' -type f -printf '%T@ %p\n' | sort -nr | tail -n +8 | cut -d' ' -f2- | xargs -r rm -f + find '$BACKUP_DIR' -name 'skg-marketing-postgres-*.sql.gz' -type f -printf '%T@ %p\n' | sort -nr | tail -n +8 | cut -d' ' -f2- | xargs -r rm -f echo backup:\$(ls -t '$BACKUP_DIR'/skg-marketing-preserve-*.tgz | head -1) " diff --git a/scripts/verify-prod-docker.sh b/scripts/verify-prod-docker.sh index 7c35610..0df93c9 100755 --- a/scripts/verify-prod-docker.sh +++ b/scripts/verify-prod-docker.sh @@ -25,5 +25,5 @@ ssh "$HOST" "cd '$APP_DIR' && \ set -e test ! -f /app/.env || { echo \"ERROR: /app/.env leaked into API image\" >&2; exit 1; } python -c \"import main; assert main.YTDLP_COOKIES_FROM_BROWSER == \\\"\\\", main.YTDLP_COOKIES_FROM_BROWSER; print(\\\"api:ytdlp_cookie_args\\\", main.ytdlp_cookie_args())\" - curl -sS http://127.0.0.1:4291/health | python -c \"import json,sys; d=json.load(sys.stdin); assert d[\\\"ok\\\"] is True; assert d[\\\"auth_configured\\\"] is True; print(\\\"api:health ok\\\")\" + curl -sS http://127.0.0.1:4291/health | python -c \"import json,sys; d=json.load(sys.stdin); assert d[\\\"ok\\\"] is True; assert d[\\\"auth_configured\\\"] is True; assert d.get(\\\"database\\\",{}).get(\\\"connected\\\") is True; print(\\\"api:health ok db connected\\\")\" '" diff --git a/web/canvas-app/src/stores/projects.js b/web/canvas-app/src/stores/projects.js index f1580d5..4373f5e 100644 --- a/web/canvas-app/src/stores/projects.js +++ b/web/canvas-app/src/stores/projects.js @@ -170,8 +170,7 @@ export const loadRemoteProjects = async () => { const response = await requestJson('/canvas-projects') remoteAvailable = true const remoteItems = (response.items || []).map(projectFromApi) - const missingLocal = localItems.filter(local => !remoteItems.some(remote => remote.id === local.id)) - const importedItems = await importLocalProjectsToServer(missingLocal) + const importedItems = await importLocalProjectsToServer(localItems) const merged = mergeProjectLists(localItems, [...remoteItems, ...importedItems]) projects.value = merged saveProjects({ remote: false }) diff --git a/web/canvas-app/src/views/Canvas.vue b/web/canvas-app/src/views/Canvas.vue index 4bec2a0..05db26d 100644 --- a/web/canvas-app/src/views/Canvas.vue +++ b/web/canvas-app/src/views/Canvas.vue @@ -833,12 +833,12 @@ watch( ) // Initialize | 初始化 -onMounted(() => { +onMounted(async () => { checkMobile() window.addEventListener('resize', checkMobile) // Initialize projects store | 初始化项目存储 - initProjectsStore() + await initProjectsStore() // Load project data | 加载项目数据 loadProjectById(route.params.id)