feat(plugin): P1-P4 审计修复 — 第一批 (Excel/CSV导出 + 市场API + 对账扫描)
1.1 Excel/CSV 导出:
- 后端 export 支持 format 参数 (json/csv/xlsx)
- rust_xlsxwriter 生成带样式 Excel
- 前端导出按钮改为 Dropdown 格式选择 (JSON/CSV/Excel)
- blob 下载支持 CSV/XLSX 二进制格式
1.2 市场后端 API + 前端对接:
- SeaORM Entity: market_entry, market_review
- API: 浏览/详情/一键安装/评论列表/提交评分
- 一键安装: upload → install → enable 一条龙 + 依赖检查
- 前端 PluginMarket 对接真实 API (搜索/分类/安装/评分)
1.3 对账扫描:
- reconcile_references() 扫描跨插件引用悬空 UUID
- POST /plugins/{plugin_id}/reconcile 端点
This commit is contained in:
@@ -217,7 +217,7 @@ export interface ExportOptions {
|
||||
search?: string;
|
||||
sort_by?: string;
|
||||
sort_order?: 'asc' | 'desc';
|
||||
format?: 'csv' | 'json';
|
||||
format?: 'json' | 'csv' | 'xlsx';
|
||||
}
|
||||
|
||||
export async function exportPluginData(
|
||||
@@ -238,6 +238,25 @@ export async function exportPluginData(
|
||||
return data.data;
|
||||
}
|
||||
|
||||
export async function exportPluginDataAsBlob(
|
||||
pluginId: string,
|
||||
entity: string,
|
||||
format: 'csv' | 'xlsx',
|
||||
options?: Omit<ExportOptions, 'format'>,
|
||||
): Promise<Blob> {
|
||||
const params: Record<string, string> = { format };
|
||||
if (options?.filter) params.filter = JSON.stringify(options.filter);
|
||||
if (options?.search) params.search = options.search;
|
||||
if (options?.sort_by) params.sort_by = options.sort_by;
|
||||
if (options?.sort_order) params.sort_order = options.sort_order;
|
||||
|
||||
const response = await client.get(
|
||||
`/plugins/${pluginId}/${entity}/export`,
|
||||
{ params, responseType: 'blob' },
|
||||
);
|
||||
return response.data as Blob;
|
||||
}
|
||||
|
||||
export interface ImportRowError {
|
||||
row: number;
|
||||
errors: string[];
|
||||
|
||||
@@ -256,3 +256,81 @@ export interface PluginTriggerEvent {
|
||||
entity: string;
|
||||
on: 'create' | 'update' | 'delete' | 'create_or_update';
|
||||
}
|
||||
|
||||
// ── 插件市场 API ──
|
||||
|
||||
export interface MarketEntry {
|
||||
id: string;
|
||||
plugin_id: string;
|
||||
name: string;
|
||||
version: string;
|
||||
description?: string;
|
||||
author?: string;
|
||||
category?: string;
|
||||
tags?: string[];
|
||||
icon_url?: string;
|
||||
screenshots?: string[];
|
||||
min_platform_version?: string;
|
||||
status: string;
|
||||
download_count: number;
|
||||
rating_avg: number;
|
||||
rating_count: number;
|
||||
changelog?: string;
|
||||
created_at?: string;
|
||||
updated_at?: string;
|
||||
}
|
||||
|
||||
export interface MarketEntryDetail extends MarketEntry {
|
||||
dependency_warnings: string[];
|
||||
}
|
||||
|
||||
export interface MarketReview {
|
||||
id: string;
|
||||
user_id: string;
|
||||
market_entry_id: string;
|
||||
rating: number;
|
||||
review_text?: string;
|
||||
created_at?: string;
|
||||
}
|
||||
|
||||
export async function listMarketEntries(params?: {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
category?: string;
|
||||
search?: string;
|
||||
}) {
|
||||
const { data } = await client.get<{ success: boolean; data: PaginatedResponse<MarketEntry> }>(
|
||||
'/market/entries',
|
||||
{ params },
|
||||
);
|
||||
return data.data;
|
||||
}
|
||||
|
||||
export async function getMarketEntry(id: string) {
|
||||
const { data } = await client.get<{ success: boolean; data: MarketEntryDetail }>(
|
||||
`/market/entries/${id}`,
|
||||
);
|
||||
return data.data;
|
||||
}
|
||||
|
||||
export async function installFromMarket(id: string) {
|
||||
const { data } = await client.post<{ success: boolean; data: PluginInfo }>(
|
||||
`/market/entries/${id}/install`,
|
||||
);
|
||||
return data.data;
|
||||
}
|
||||
|
||||
export async function listMarketReviews(id: string) {
|
||||
const { data } = await client.get<{ success: boolean; data: MarketReview[] }>(
|
||||
`/market/entries/${id}/reviews`,
|
||||
);
|
||||
return data.data;
|
||||
}
|
||||
|
||||
export async function submitMarketReview(id: string, review: { rating: number; review_text?: string }) {
|
||||
const { data } = await client.post<{ success: boolean; data: MarketReview }>(
|
||||
`/market/entries/${id}/reviews`,
|
||||
review,
|
||||
);
|
||||
return data.data;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user