2025-09-19 18:08:03 +08:00

509 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 视频编辑功能API接口
*/
import { post, get, put, del } from '@/api/request';
import { ApiResponse } from '@/api/common';
import {
EditPoint,
CreateEditPointRequest,
UpdateEditPointRequest,
DeleteEditPointRequest,
EditPointsResponse,
EditPointStatus
} from './types';
import { getVideoEditApiConfig, getApiEndpoint, debugLog, errorHandlingConfig } from './config';
// Mock数据存储使用localStorage持久化
let mockEditPoints: EditPoint[] = [];
let mockIdCounter = 1;
// 初始化Mock数据
function initializeMockData() {
try {
const stored = localStorage.getItem('video-edit-mock-data');
if (stored) {
const data = JSON.parse(stored);
mockEditPoints = data.editPoints || [];
mockIdCounter = data.idCounter || 1;
debugLog('Mock数据加载成功', { count: mockEditPoints.length, nextId: mockIdCounter });
}
} catch (error) {
debugLog('Mock数据加载失败使用默认数据', error);
mockEditPoints = [];
mockIdCounter = 1;
}
}
// 保存Mock数据
function saveMockData() {
try {
const data = {
editPoints: mockEditPoints,
idCounter: mockIdCounter,
timestamp: new Date().toISOString()
};
localStorage.setItem('video-edit-mock-data', JSON.stringify(data));
debugLog('Mock数据保存成功', { count: mockEditPoints.length });
} catch (error) {
debugLog('Mock数据保存失败', error);
}
}
// 初始化数据
initializeMockData();
/**
* Mock API函数
*/
function createMockEditPoint(request: CreateEditPointRequest): EditPoint {
const editPoint: EditPoint = {
id: `edit-point-${mockIdCounter++}`,
videoId: request.videoId,
projectId: request.projectId,
userId: 1, // Mock用户ID
position: request.position,
timestamp: request.timestamp,
description: request.description || '',
status: EditPointStatus.PENDING,
createdAt: Date.now(),
updatedAt: Date.now(),
showInput: true, // 新创建的编辑点应该显示输入框
connectionDirection: 'auto'
};
mockEditPoints.push(editPoint);
saveMockData(); // 持久化保存
debugLog('Mock编辑点创建', editPoint);
return editPoint;
}
/**
* 创建编辑点
*/
export async function createEditPoint(request: CreateEditPointRequest): Promise<EditPoint | null> {
try {
const config = getVideoEditApiConfig();
debugLog('创建编辑点请求', request);
// 使用Mock API
if (config.useMockApi) {
debugLog('使用Mock API创建编辑点');
await new Promise(resolve => setTimeout(resolve, 500)); // 模拟网络延迟
const editPoint = createMockEditPoint(request);
debugLog('Mock编辑点创建成功', editPoint);
return editPoint;
}
// 获取API端点
const apiUrl = getApiEndpoint('/edit-points');
const response = await post<ApiResponse<EditPoint>>(apiUrl, {
video_id: request.videoId,
project_id: request.projectId,
position_x: request.position.x,
position_y: request.position.y,
timestamp: request.timestamp,
description: request.description || '',
status: EditPointStatus.PENDING
});
if (response.successful && response.data) {
// 转换API响应格式为前端数据格式
const editPoint: EditPoint = {
id: response.data.id,
videoId: response.data.videoId,
projectId: response.data.projectId,
userId: response.data.userId,
position: {
x: response.data.position.x,
y: response.data.position.y
},
timestamp: response.data.timestamp,
description: response.data.description,
status: response.data.status,
createdAt: response.data.createdAt,
updatedAt: response.data.updatedAt,
showInput: false,
connectionDirection: 'auto'
};
console.log('编辑点创建成功:', editPoint);
return editPoint;
} else {
console.error('创建编辑点失败:', response.message);
return null;
}
} catch (error) {
console.error('创建编辑点API调用失败:', error);
// 如果真实API失败回退到Mock
const config = getVideoEditApiConfig();
if (!config.useMockApi) {
console.log('🔄 API失败回退到Mock模式');
const editPoint = createMockEditPoint(request);
return editPoint;
}
return null;
}
}
/**
* 更新编辑点
*/
export async function updateEditPoint(request: UpdateEditPointRequest): Promise<boolean> {
try {
console.log('更新编辑点请求:', request);
const config = getVideoEditApiConfig();
// 使用Mock API
if (config.useMockApi) {
debugLog('使用Mock API更新编辑点');
await new Promise(resolve => setTimeout(resolve, 300)); // 模拟网络延迟
const editPointIndex = mockEditPoints.findIndex(point => point.id === request.id);
if (editPointIndex !== -1) {
const editPoint = mockEditPoints[editPointIndex];
if (request.description !== undefined) {
editPoint.description = request.description;
}
if (request.status !== undefined) {
editPoint.status = request.status;
}
if (request.position !== undefined) {
editPoint.position = request.position;
}
editPoint.updatedAt = Date.now();
saveMockData(); // 持久化保存
debugLog('Mock编辑点更新成功', editPoint);
return true;
} else {
debugLog('Mock编辑点不存在', request.id);
return false;
}
}
const updateData: any = {};
if (request.description !== undefined) {
updateData.description = request.description;
}
if (request.status !== undefined) {
updateData.status = request.status;
}
if (request.position !== undefined) {
updateData.position_x = request.position.x;
updateData.position_y = request.position.y;
}
// 选择API端点
const apiUrl = config.useLocalApi ? `/api/video-edit/edit-points/${request.id}` : `/video-edit/edit-points/${request.id}`;
const response = await put<ApiResponse<EditPoint>>(apiUrl, updateData);
if (response.successful) {
console.log('编辑点更新成功');
return true;
} else {
console.error('更新编辑点失败:', response.message);
return false;
}
} catch (error) {
console.error('更新编辑点API调用失败:', error);
// 如果真实API失败回退到Mock
const config = getVideoEditApiConfig();
if (!config.useMockApi) {
console.log('🔄 API失败回退到Mock模式');
const editPointIndex = mockEditPoints.findIndex(point => point.id === request.id);
if (editPointIndex !== -1) {
const editPoint = mockEditPoints[editPointIndex];
if (request.description !== undefined) editPoint.description = request.description;
if (request.status !== undefined) editPoint.status = request.status;
if (request.position !== undefined) editPoint.position = request.position;
editPoint.updatedAt = Date.now();
return true;
}
}
return false;
}
}
/**
* 删除编辑点
*/
export async function deleteEditPoint(request: DeleteEditPointRequest): Promise<boolean> {
try {
console.log('删除编辑点请求:', request);
// 获取配置
const config = getVideoEditApiConfig();
// 使用Mock API
if (config.useMockApi) {
console.log('🔧 使用Mock API删除编辑点');
await new Promise(resolve => setTimeout(resolve, 200)); // 模拟网络延迟
const editPointIndex = mockEditPoints.findIndex(point => point.id === request.id);
if (editPointIndex !== -1) {
mockEditPoints.splice(editPointIndex, 1);
console.log('✅ Mock编辑点删除成功');
return true;
} else {
console.error('❌ Mock编辑点不存在:', request.id);
return false;
}
}
// 选择API端点
const apiUrl = config.useLocalApi ? `/api/video-edit/edit-points/${request.id}` : `/video-edit/edit-points/${request.id}`;
const response = await del<ApiResponse<void>>(apiUrl);
if (response.successful) {
console.log('编辑点删除成功');
return true;
} else {
console.error('删除编辑点失败:', response.message);
return false;
}
} catch (error) {
console.error('删除编辑点API调用失败:', error);
// 如果真实API失败回退到Mock
const config = getVideoEditApiConfig();
if (!config.useMockApi) {
console.log('🔄 API失败回退到Mock模式');
const editPointIndex = mockEditPoints.findIndex(point => point.id === request.id);
if (editPointIndex !== -1) {
mockEditPoints.splice(editPointIndex, 1);
return true;
}
}
return false;
}
}
/**
* 获取编辑点列表
*/
export async function getEditPoints(params: {
videoId: string;
projectId: string;
offset?: number;
limit?: number;
}): Promise<EditPointsResponse | null> {
try {
console.log('获取编辑点列表请求:', params);
// 获取配置
const config = getVideoEditApiConfig();
// 使用Mock API
if (config.useMockApi) {
console.log('🔧 使用Mock API获取编辑点列表');
await new Promise(resolve => setTimeout(resolve, 300)); // 模拟网络延迟
// 过滤匹配的编辑点
const filteredPoints = mockEditPoints.filter(point =>
point.videoId === params.videoId && point.projectId === params.projectId
);
const offset = params.offset || 0;
const limit = params.limit || 50;
const paginatedPoints = filteredPoints.slice(offset, offset + limit);
const result: EditPointsResponse = {
editPoints: paginatedPoints,
totalCount: filteredPoints.length,
hasMore: offset + limit < filteredPoints.length
};
console.log('✅ Mock编辑点列表获取成功:', result);
return result;
}
const queryParams = new URLSearchParams({
video_id: params.videoId,
project_id: params.projectId,
offset: (params.offset || 0).toString(),
limit: (params.limit || 50).toString()
});
// 选择API端点
const apiUrl = config.useLocalApi ? `/api/video-edit/edit-points?${queryParams}` : `/video-edit/edit-points?${queryParams}`;
const response = await get<ApiResponse<{
edit_points: any[];
total_count: number;
has_more: boolean;
}>>(apiUrl);
if (response.successful && response.data) {
// 转换API响应格式为前端数据格式
const editPoints: EditPoint[] = response.data.edit_points.map((item: any) => ({
id: item.id,
videoId: item.video_id,
projectId: item.project_id,
userId: item.user_id,
position: {
x: item.position_x,
y: item.position_y
},
timestamp: item.timestamp,
description: item.description,
status: item.status,
createdAt: item.created_at,
updatedAt: item.updated_at,
showInput: false,
connectionDirection: 'auto'
}));
const result: EditPointsResponse = {
editPoints,
totalCount: response.data.total_count,
hasMore: response.data.has_more
};
console.log('编辑点列表获取成功:', result);
return result;
} else {
console.error('获取编辑点列表失败:', response.message);
return null;
}
} catch (error) {
console.error('获取编辑点列表API调用失败:', error);
return null;
}
}
/**
* 批量删除编辑点
*/
export async function batchDeleteEditPoints(editPointIds: string[]): Promise<boolean> {
try {
console.log('批量删除编辑点请求:', editPointIds);
const response = await post<ApiResponse<void>>('/video-edit/edit-points/batch-delete', {
edit_point_ids: editPointIds
});
if (response.successful) {
console.log('批量删除编辑点成功');
return true;
} else {
console.error('批量删除编辑点失败:', response.message);
return false;
}
} catch (error) {
console.error('批量删除编辑点API调用失败:', error);
return false;
}
}
/**
* 获取编辑点统计信息
*/
export async function getEditPointStats(params: {
videoId?: string;
projectId: string;
userId?: number;
}): Promise<{
totalCount: number;
statusCounts: Record<EditPointStatus, number>;
recentActivity: EditPoint[];
} | null> {
try {
console.log('获取编辑点统计请求:', params);
const queryParams = new URLSearchParams({
project_id: params.projectId
});
if (params.videoId) {
queryParams.append('video_id', params.videoId);
}
if (params.userId) {
queryParams.append('user_id', params.userId.toString());
}
const response = await get<ApiResponse<{
total_count: number;
status_counts: Record<string, number>;
recent_activity: any[];
}>>(`/video-edit/edit-points/stats?${queryParams}`);
if (response.successful && response.data) {
// 转换状态计数格式
const statusCounts: Record<EditPointStatus, number> = {
[EditPointStatus.PENDING]: response.data.status_counts.pending || 0,
[EditPointStatus.EDITED]: response.data.status_counts.edited || 0,
[EditPointStatus.PROCESSING]: response.data.status_counts.processing || 0,
[EditPointStatus.COMPLETED]: response.data.status_counts.completed || 0,
[EditPointStatus.FAILED]: response.data.status_counts.failed || 0
};
// 转换最近活动数据
const recentActivity: EditPoint[] = response.data.recent_activity.map((item: any) => ({
id: item.id,
videoId: item.video_id,
projectId: item.project_id,
userId: item.user_id,
position: {
x: item.position_x,
y: item.position_y
},
timestamp: item.timestamp,
description: item.description,
status: item.status,
createdAt: item.created_at,
updatedAt: item.updated_at,
showInput: false,
connectionDirection: 'auto'
}));
const result = {
totalCount: response.data.total_count,
statusCounts,
recentActivity
};
console.log('编辑点统计获取成功:', result);
return result;
} else {
console.error('获取编辑点统计失败:', response.message);
return null;
}
} catch (error) {
console.error('获取编辑点统计API调用失败:', error);
return null;
}
}
/**
* 提交编辑请求到处理队列
*/
export async function submitEditRequest(editPointId: string): Promise<boolean> {
try {
console.log('提交编辑请求:', editPointId);
const response = await post<ApiResponse<void>>(`/video-edit/edit-points/${editPointId}/submit`, {});
if (response.successful) {
console.log('编辑请求提交成功');
return true;
} else {
console.error('提交编辑请求失败:', response.message);
return false;
}
} catch (error) {
console.error('提交编辑请求API调用失败:', error);
return false;
}
}