api.js 3.37 KB
import { getH3Base, getToken, setToken } from './utils';

export async function apiFetch(path, options = {}) {
  const base = getH3Base();
  const url = path.startsWith('http') ? path : `${base}${path}`;
  const token = getToken();

  const headers = { ...(options.headers || {}) };
  if (token) {
    headers['Authorization'] = `Bearer ${token}`;
  }

  const res = await fetch(url, { ...options, headers });
  if (res.status === 401) {
    setToken('');
    const newToken = window.prompt('H3 访问令牌 (Token) 已过期或无效,请输入新令牌:');
    if (newToken) {
      setToken(newToken);
      headers['Authorization'] = `Bearer ${newToken}`;
      return fetch(url, { ...options, headers });
    }
  }
  return res;
}

export async function fetchJobs({ page = 1, limit = 20, q = '', status = '', kind = '', sort = 'desc', trash = false } = {}) {
  const params = new URLSearchParams();
  if (trash) {
    params.set('trash', 'true');
    params.set('limit', '50');
  } else {
    // 服务端分页参数是 offset 不是 page,传 page 会被忽略(永远返回第一页)
    params.set('offset', String((page - 1) * limit));
    params.set('limit', String(limit));
    if (q) params.set('q', q);
    if (status) params.set('status', status);
    if (kind) params.set('kind', kind);
    if (sort) params.set('sort', sort);
  }

  const res = await apiFetch(`/v1/videos?${params.toString()}`);
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

export async function fetchJobDetail(id) {
  const res = await apiFetch(`/v1/videos/${id}`);
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

export async function createJob(body) {
  const res = await apiFetch('/v1/videos', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  });
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

export async function uploadAsset(file) {
  const fd = new FormData();
  fd.append('file', file);
  const res = await apiFetch('/v1/assets', {
    method: 'POST',
    body: fd,
  });
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

export async function prioritizeJob(id) {
  const res = await apiFetch(`/v1/videos/${id}/prioritize`, { method: 'POST' });
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

export async function deleteJob(id) {
  const res = await apiFetch(`/v1/videos/${id}`, { method: 'DELETE' });
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

export async function restoreJob(id) {
  const res = await apiFetch(`/v1/videos/${id}/restore`, { method: 'POST' });
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

export async function cancelJob(id) {
  const res = await apiFetch(`/v1/videos/${id}/cancel`, { method: 'POST' });
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

export async function resetGpu() {
  const res = await apiFetch('/v1/admin/reset-gpu', { method: 'POST' });
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

export async function fetchBackends() {
  const res = await apiFetch('/v1/backends');
  if (!res.ok) return null;
  return res.json();
}

export async function fetchComfyHistory(id) {
  const res = await apiFetch(`/v1/videos/${id}/comfy_history`);
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}