feat: Lsky/COS gateway - attachments upload direct to object storage (remote_url/remote_thumb), preview loads from COS, graceful local fallback

This commit is contained in:
root
2026-10-17 01:16:59 +08:00
parent a94c1f6e25
commit 2bba3be08e
23 changed files with 174 additions and 51 deletions
+14 -1
View File
@@ -125,7 +125,7 @@ function preMigrateColumns(d) {
}
};
for (const t of SYNC_TABLES) addCols(t, SYNC_COLS);
addCols('attachment', [['sha256', 'TEXT'], ['thumb_rel_path', 'TEXT']]);
addCols('attachment', [['sha256', 'TEXT'], ['thumb_rel_path', 'TEXT'], ['remote_url', 'TEXT'], ['remote_thumb', 'TEXT']]);
}
export function migrateSync(d) {
@@ -1078,6 +1078,19 @@ function listFootprints(d, query) {
return { data_b64: data.toString('base64'), mime: row.thumb_rel_path ? 'image/webp' : row.mime, file_name: row.file_name };
}
case 'attachment_set_remote': {
// 图床(Lsky/COS)直传成功后回填远程地址;同步到所有端
const row = d.prepare('SELECT * FROM attachment WHERE id=?').get(payload.id);
if (!row) throw new Error('附件不存在');
withTx(d, () => {
const h = hlcNext(d);
d.prepare('UPDATE attachment SET remote_url=?, remote_thumb=?, hlc=? WHERE id=?')
.run(payload.remote_url ?? null, payload.remote_thumb ?? null, h, row.id);
touchOplog(d, 'attachment', row.uuid, 'upsert', h);
});
return { ok: true };
}
case 'view_list':
return { items: d.prepare('SELECT * FROM saved_view WHERE deleted_at IS NULL ORDER BY id').all().map(v => ({
...v, filter: JSON.parse(v.filter || '{}'), sort: JSON.parse(v.sort || '{}'), is_default: !!v.is_default