feat: 新增受保护链接并将控制台合并为资源访问管理
- 新增 ProtectedLink/LinkVisitRecord,/link/{slug} 门禁页 + 一次性令牌跳转
- 复用邮箱验证体系,验证码邮件区分下载/链接模板
- 控制台下载资源与受保护链接合并为「资源访问管理」单页(页签切换)
- 引用扫描支持 /link/ 链接,角色模板/设置/文档同步更新
- 版本 1.3.0
This commit is contained in:
@@ -4,7 +4,11 @@ import type {
|
||||
DownloadResourceList,
|
||||
DownloadResourceSpec,
|
||||
DownloadRecord,
|
||||
LinkVisitRecord,
|
||||
ListResult,
|
||||
ProtectedLink,
|
||||
ProtectedLinkList,
|
||||
ProtectedLinkSpec,
|
||||
ReferencesMap,
|
||||
} from '@/types';
|
||||
|
||||
@@ -125,3 +129,117 @@ export async function refreshReferences(): Promise<ReferencesMap> {
|
||||
);
|
||||
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<ProtectedLinkList> {
|
||||
const { data } = await axiosInstance.get<LinkVo[]>(
|
||||
`${API_BASE}/protected-links`
|
||||
);
|
||||
const items = (data ?? []).map(normalizeLink);
|
||||
return { items, total: items.length };
|
||||
}
|
||||
|
||||
export async function createLink(spec: ProtectedLinkSpec): Promise<ProtectedLink> {
|
||||
const { data } = await axiosInstance.post<LinkVo>(
|
||||
`${API_BASE}/protected-links`,
|
||||
spec
|
||||
);
|
||||
return normalizeLink(data);
|
||||
}
|
||||
|
||||
export async function getLink(name: string): Promise<ProtectedLink> {
|
||||
const { data } = await axiosInstance.get<LinkVo>(
|
||||
`${API_BASE}/protected-links/${name}`
|
||||
);
|
||||
return normalizeLink(data);
|
||||
}
|
||||
|
||||
export async function updateLink(
|
||||
name: string,
|
||||
spec: ProtectedLinkSpec
|
||||
): Promise<ProtectedLink> {
|
||||
const { data } = await axiosInstance.put<LinkVo>(
|
||||
`${API_BASE}/protected-links/${name}`,
|
||||
spec
|
||||
);
|
||||
return normalizeLink(data);
|
||||
}
|
||||
|
||||
export async function deleteLink(name: string): Promise<void> {
|
||||
await axiosInstance.delete(`${API_BASE}/protected-links/${name}`);
|
||||
}
|
||||
|
||||
export async function listLinkRecords(params: {
|
||||
linkSlug?: string;
|
||||
page?: number;
|
||||
size?: number;
|
||||
}): Promise<ListResult<LinkVisitRecord>> {
|
||||
const { data } = await axiosInstance.get<ListResult<LinkVisitRecord>>(
|
||||
`${API_BASE}/link-visit-records`,
|
||||
{ params }
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function deleteLinkRecord(name: string): Promise<void> {
|
||||
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<ReferencesMap> {
|
||||
const { data } = await axiosInstance.get<ReferencesMap>(
|
||||
`${API_BASE}/link-references`
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function refreshLinkReferences(): Promise<ReferencesMap> {
|
||||
const { data } = await axiosInstance.post<ReferencesMap>(
|
||||
`${API_BASE}/link-references/-/refresh`
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user