feat: 三栏比例缩放 + SeedanceContent视频上传 + 本地存储基建 (0.0.22)
三栏布局 - ResizeObserver 等比例分配替代固定默认值恢复 - 修复拖拽+窗口调整竞态卡死(needsRecalcRef 延迟补算) - containerRef.current 动态读取 DOM 替代闭包 el Seedance2Content - 从占位文本重构为内容编排控件(文本+图片/视频/音频上传) - 根据 spec.image_files/video_files/audio_files 动态渲染上传区域 - 值 JSON 序列化 → 提交时转 ContentItem[](text/image_url/video_url/audio_url) 图片上传兼容视频文件 - buildAccept 根据 file_filter 区分 image/video 前缀 - createMediaBeforeUpload 动态放行 video/* MIME - 公共模块 media-upload-utils.ts 本地存储基建 - sql.js (WASM SQLite) + safeStorage 加密持久化 - 8个IPC文件操作通道 + resolveSafe 路径穿越防护 - <userData>/heixiu-data/ 沙箱 + JWT用户隔离 - 7表DDL + 游标分页 + LRU媒体淘汰 其他 - 修复 errorMessageRef 渲染期写入警告 - 媒体预览回退直接URL(<img>无CORS限制)+ output_type类型补充 - CSP wasm-unsafe-eval + https: CDN媒体源
This commit is contained in:
90
src/pages/settings/sections/data-sync.ts
Normal file
90
src/pages/settings/sections/data-sync.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
// ============================================================
|
||||
// data-sync.ts — 数据同步辅助函数
|
||||
//
|
||||
// 供设置页 [加载历史数据] 和列表页 [下一页] 共用。
|
||||
// 职责:
|
||||
// - 调用 API 拉取分页数据
|
||||
// - 同步到本地 sql.js 缓存
|
||||
// - 更新分页游标
|
||||
// - 返回是否还有更多数据
|
||||
// ============================================================
|
||||
|
||||
import {
|
||||
syncTasks, syncRechargeOrders, syncVipOrders,
|
||||
hasMore, nextPage, updateCursor,
|
||||
} from '@/infrastructure/storage';
|
||||
import { TaskAPI } from '@/services/modules/task';
|
||||
import { PaymentAPI } from '@/services/modules/payments';
|
||||
import { VipAPI } from '@/services/modules/vip-api';
|
||||
import { logger } from '@/utils/logger';
|
||||
|
||||
const PAGE_SIZE = 100;
|
||||
|
||||
// ======== 任务 ========
|
||||
|
||||
export async function fetchAndSyncTasks(): Promise<{ count: number; hasMore: boolean }> {
|
||||
if (!hasMore('tasks')) return { count: 0, hasMore: false };
|
||||
const page = nextPage('tasks');
|
||||
try {
|
||||
const res = await TaskAPI.getTaskList({ page, page_size: PAGE_SIZE });
|
||||
const sorted = [...res.items].sort(
|
||||
(a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
|
||||
);
|
||||
syncTasks(sorted);
|
||||
updateCursor('tasks', page, res.total);
|
||||
logger.info('storage', `任务同步:第 ${page} 页,${sorted.length} 条,共 ${res.total} 条`);
|
||||
return { count: sorted.length, hasMore: page * PAGE_SIZE < res.total };
|
||||
} catch (err) {
|
||||
logger.error('storage', '任务同步失败', err instanceof Error ? err : undefined);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export function hasMoreTasks(): boolean {
|
||||
return hasMore('tasks');
|
||||
}
|
||||
|
||||
// ======== 充值订单 ========
|
||||
|
||||
export async function fetchAndSyncRechargeOrders(): Promise<{ count: number; hasMore: boolean }> {
|
||||
if (!hasMore('recharge_orders')) return { count: 0, hasMore: false };
|
||||
const page = nextPage('recharge_orders');
|
||||
try {
|
||||
const res = await PaymentAPI.getOrdersListInfo({ page, page_size: PAGE_SIZE });
|
||||
syncRechargeOrders(res);
|
||||
// API 未返回 total → 用返回条数推算
|
||||
const total = res.length >= PAGE_SIZE ? (page * PAGE_SIZE) + PAGE_SIZE : page * PAGE_SIZE;
|
||||
updateCursor('recharge_orders', page, total);
|
||||
logger.info('storage', `充值订单同步:第 ${page} 页,${res.length} 条`);
|
||||
return { count: res.length, hasMore: res.length >= PAGE_SIZE };
|
||||
} catch (err) {
|
||||
logger.error('storage', '充值订单同步失败', err instanceof Error ? err : undefined);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export function hasMoreRechargeOrders(): boolean {
|
||||
return hasMore('recharge_orders');
|
||||
}
|
||||
|
||||
// ======== VIP 订单 ========
|
||||
|
||||
export async function fetchAndSyncVipOrders(): Promise<{ count: number; hasMore: boolean }> {
|
||||
if (!hasMore('vip_orders')) return { count: 0, hasMore: false };
|
||||
const page = nextPage('vip_orders');
|
||||
try {
|
||||
const res = await VipAPI.getVipOrders({ page, page_size: PAGE_SIZE });
|
||||
syncVipOrders(res);
|
||||
const total = res.length >= PAGE_SIZE ? (page * PAGE_SIZE) + PAGE_SIZE : page * PAGE_SIZE;
|
||||
updateCursor('vip_orders', page, total);
|
||||
logger.info('storage', `VIP 订单同步:第 ${page} 页,${res.length} 条`);
|
||||
return { count: res.length, hasMore: res.length >= PAGE_SIZE };
|
||||
} catch (err) {
|
||||
logger.error('storage', 'VIP 订单同步失败', err instanceof Error ? err : undefined);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export function hasMoreVipOrders(): boolean {
|
||||
return hasMore('vip_orders');
|
||||
}
|
||||
Reference in New Issue
Block a user