import { axiosInstance } from '@halo-dev/api-client'; import type { DownloadResource, DownloadResourceList, DownloadResourceSpec, DownloadRecord, LinkVisitRecord, ListResult, ProtectedLink, ProtectedLinkList, ProtectedLinkSpec, ReferencesMap, } from '@/types'; export const API_BASE = '/apis/console.api.sharelink.halo.run/v1alpha1'; // 后端资源 VO 为扁平结构,这里统一归一化为 Halo 风格结构供组件使用 interface ResourceVo { name: string; slug: string; displayName: string; description?: string; attachmentName?: string; requireEmailVerify?: boolean; enabled?: boolean; downloadUrl?: string; creationTimestamp?: string; stats?: { downloadCount?: number; downloaderCount?: number; referenceCount?: number; }; } function normalizeResource(vo: ResourceVo): DownloadResource { return { metadata: { name: vo.name, creationTimestamp: vo.creationTimestamp }, spec: { slug: vo.slug, displayName: vo.displayName, description: vo.description, attachmentName: vo.attachmentName, requireEmailVerify: vo.requireEmailVerify, enabled: vo.enabled, }, status: { downloadCount: vo.stats?.downloadCount ?? 0 }, stats: { downloaderCount: vo.stats?.downloaderCount ?? 0, referenceCount: vo.stats?.referenceCount ?? 0, }, }; } export async function listResources(): Promise { const { data } = await axiosInstance.get( `${API_BASE}/download-resources` ); const items = (data ?? []).map(normalizeResource); return { items, total: items.length }; } // 后端创建/更新均接收扁平的 spec 字段(ResourceRequest) export async function createResource( spec: DownloadResourceSpec ): Promise { const { data } = await axiosInstance.post( `${API_BASE}/download-resources`, spec ); return normalizeResource(data); } export async function getResource(name: string): Promise { const { data } = await axiosInstance.get( `${API_BASE}/download-resources/${name}` ); return normalizeResource(data); } export async function updateResource( name: string, spec: DownloadResourceSpec ): Promise { const { data } = await axiosInstance.put( `${API_BASE}/download-resources/${name}`, spec ); return normalizeResource(data); } export async function deleteResource(name: string): Promise { await axiosInstance.delete(`${API_BASE}/download-resources/${name}`); } export async function listRecords(params: { resourceSlug?: string; page?: number; size?: number; }): Promise> { const { data } = await axiosInstance.get>( `${API_BASE}/download-records`, { params } ); return data; } export async function deleteRecord(name: string): Promise { await axiosInstance.delete(`${API_BASE}/download-records/${name}`); } // CSV 导出走浏览器直接导航(console 端点接受 session cookie) export function recordsExportUrl(resourceSlug?: string): string { const query = resourceSlug ? `?resourceSlug=${encodeURIComponent(resourceSlug)}` : ''; return `${API_BASE}/download-records/-/export${query}`; } export async function getReferences(): Promise { const { data } = await axiosInstance.get( `${API_BASE}/references` ); return data; } export async function refreshReferences(): Promise { const { data } = await axiosInstance.post( `${API_BASE}/references/-/refresh` ); return data; } // ---------- 受保护链接 ---------- interface LinkVo { name: string; slug: string; displayName: string; description?: string; targetUrl?: string; requireEmailVerify?: boolean; enabled?: boolean; visitUrl?: string; creationTimestamp?: string; stats?: { visitCount?: number; visitorCount?: number; referenceCount?: number; }; } function normalizeLink(vo: LinkVo): ProtectedLink { return { metadata: { name: vo.name, creationTimestamp: vo.creationTimestamp }, spec: { slug: vo.slug, displayName: vo.displayName, description: vo.description, targetUrl: vo.targetUrl, requireEmailVerify: vo.requireEmailVerify, enabled: vo.enabled, }, status: { visitCount: vo.stats?.visitCount ?? 0 }, stats: { visitorCount: vo.stats?.visitorCount ?? 0, referenceCount: vo.stats?.referenceCount ?? 0, }, }; } export async function listLinks(): Promise { const { data } = await axiosInstance.get( `${API_BASE}/protected-links` ); const items = (data ?? []).map(normalizeLink); return { items, total: items.length }; } export async function createLink(spec: ProtectedLinkSpec): Promise { const { data } = await axiosInstance.post( `${API_BASE}/protected-links`, spec ); return normalizeLink(data); } export async function getLink(name: string): Promise { const { data } = await axiosInstance.get( `${API_BASE}/protected-links/${name}` ); return normalizeLink(data); } export async function updateLink( name: string, spec: ProtectedLinkSpec ): Promise { const { data } = await axiosInstance.put( `${API_BASE}/protected-links/${name}`, spec ); return normalizeLink(data); } export async function deleteLink(name: string): Promise { await axiosInstance.delete(`${API_BASE}/protected-links/${name}`); } export async function listLinkRecords(params: { linkSlug?: string; page?: number; size?: number; }): Promise> { const { data } = await axiosInstance.get>( `${API_BASE}/link-visit-records`, { params } ); return data; } export async function deleteLinkRecord(name: string): Promise { await axiosInstance.delete(`${API_BASE}/link-visit-records/${name}`); } // CSV 导出走浏览器直接导航(console 端点接受 session cookie) export function linkRecordsExportUrl(linkSlug?: string): string { const query = linkSlug ? `?linkSlug=${encodeURIComponent(linkSlug)}` : ''; return `${API_BASE}/link-visit-records/-/export${query}`; } export async function getLinkReferences(): Promise { const { data } = await axiosInstance.get( `${API_BASE}/link-references` ); return data; } export async function refreshLinkReferences(): Promise { const { data } = await axiosInstance.post( `${API_BASE}/link-references/-/refresh` ); return data; }