feat(export): configurable CSV field quoting mode

This commit is contained in:
zipg authored and GitHub committed 2026-09-03 17:51:50 +08:00
1 parent d421bd33fc
commit 203eab3dec
32 files changed
+442 -56

No files matched your search

+3 -2
View File
@@ -153,6 +153,7 @@ import type {
ElasticsearchDeleteByQueryResult,
} from "@/lib/backend/tauri";
import type { QueryEditability } from "@/lib/sql/sqlAnalysis";
import type { CsvQuoteMode } from "@/lib/export/csvQuoteMode";
import { isTerminalTransferProgress } from "@/lib/backend/transferProgress";
import type {
DataGridColumnDistinctValuesSqlOptions,
@@ -2595,9 +2596,9 @@ export async function cancelQueryResultExport(exportId: string, executionId?: st
});
}
export async function exportQueryResultCsv(filePath: string, columns: string[], rows: readonly (readonly XlsxCellValue[])[]): Promise<void> {
export async function exportQueryResultCsv(filePath: string, columns: string[], rows: readonly (readonly XlsxCellValue[])[], csvQuoteMode: CsvQuoteMode = "all"): Promise<void> {
const { formatCsv } = await import("@/lib/export/exportFormats");
const content = formatCsv(columns, rows as (string | number | boolean | null)[][]);
const content = formatCsv(columns, rows as (string | number | boolean | null)[][], csvQuoteMode);
const fileName = filePath.split(/[\\/]/).pop() || "export.csv";
const blob = new Blob(["\uFEFF", content], {
type: "text/csv;charset=utf-8",
+6 -1
View File
@@ -8,6 +8,7 @@ import { appendDebugLog, isDebugLoggingEnabled } from "@/lib/backend/debugLog";
import { decodeMeilisearchDocumentPage, decodeMeilisearchSearchResult, type MeilisearchDocumentPage, type MeilisearchDocumentPageWire, type MeilisearchSearchResult, type MeilisearchSearchWireResult } from "@/lib/backend/meilisearchTransport";
import type { XuguTablespaceInfo } from "@/types/database";
import type { CreatedKey, EnqueuedTaskSummary, KeyCreateInput, KeyListItem, KeyPage, KeyUpdateInput, MeilisearchSystemOverview, MeilisearchTask, TaskListInput, TaskPage, TaskSelector } from "@/types/meilisearchManagement";
import type { CsvQuoteMode } from "@/lib/export/csvQuoteMode";
/** Normalize Tauri rejections once at the public backend boundary. */
async function invokeBackend<T>(command: string, args?: Record<string, unknown>): Promise<T> {
@@ -4839,6 +4840,7 @@ export interface TableExportRequest {
tableName: string;
filePath: string;
format: "csv" | "xlsx" | "json" | "markdown" | "sql" | "txt";
csvQuoteMode?: CsvQuoteMode;
columns?: string[];
columnTypes?: Array<string | null | undefined>;
columnComments?: Array<string | null> | null;
@@ -4862,6 +4864,7 @@ export interface TableCsvExportOptions {
columns?: string[];
pageSize?: number;
timeoutSecs?: number;
csvQuoteMode?: CsvQuoteMode;
}
export interface TableExportProgress {
@@ -4886,6 +4889,7 @@ export interface QueryResultExportRequest {
useAgentCursor: boolean;
filePath: string;
format: "csv" | "xlsx" | "txt" | "sql";
csvQuoteMode?: CsvQuoteMode;
includeSqlSheet?: boolean;
pageSize: number;
rowLimit?: number | null;
@@ -5029,12 +5033,13 @@ export async function recordDatabaseExportDestination(directory: string): Promis
await invoke("record_database_export_destination", { directory });
}
export async function exportQueryResultCsv(filePath: string, columns: string[], rows: readonly (readonly XlsxCellValue[])[]): Promise<void> {
export async function exportQueryResultCsv(filePath: string, columns: string[], rows: readonly (readonly XlsxCellValue[])[], csvQuoteMode: CsvQuoteMode = "all"): Promise<void> {
return invoke("export_query_result_csv", {
request: {
filePath,
columns,
rows,
csvQuoteMode,
},
});
}