diff --git a/src/components/grid/DataGrid.vue b/src/components/grid/DataGrid.vue
index db3b207f8..f39dac6e8 100644
--- a/src/components/grid/DataGrid.vue
+++ b/src/components/grid/DataGrid.vue
@@ -938,6 +938,7 @@ const {
requestDeleteRow,
confirmDeleteRow,
restoreRow,
+ restoreRows,
pendingDeleteRowIds,
requestDeleteRows,
cloneRows,
@@ -1122,6 +1123,22 @@ function affectedRowIds(): number[] {
return [];
}
+function exportSelectedRowsCsv() {
+ return exportCsv(affectedRowIds());
+}
+
+function exportSelectedRowsXlsx() {
+ return exportXlsx(affectedRowIds());
+}
+
+function exportSelectedRowsJson() {
+ return exportJson(affectedRowIds());
+}
+
+function exportSelectedRowsMarkdown() {
+ return exportMarkdown(affectedRowIds());
+}
+
function isRowActive(index: number): boolean {
const item = displayItems.value[index];
if (item && isRowSelected(item.id)) return true;
@@ -2632,8 +2649,12 @@ defineExpose({
{{ isMultiRow ? t("grid.cloneRows", { count: multiRowCount }) : t("grid.cloneRow") }}
-
- {{ t("grid.restoreRow") }}
+
+
+ {{ isMultiRow ? t("grid.restoreRows", { count: multiRowCount }) : t("grid.restoreRow") }}
{{ t("grid.exportXlsx") }}
{{ t("grid.exportJson") }}
{{ t("grid.exportMarkdown") }}
+
+
+ {{ t("grid.exportSelectedRowsCsv") }}
+ {{ t("grid.exportSelectedRowsXlsx") }}
+ {{ t("grid.exportSelectedRowsJson") }}
+ {{
+ t("grid.exportSelectedRowsMarkdown")
+ }}
+
@@ -2676,7 +2706,7 @@ defineExpose({
(truncated)
{{ t("grid.rowsAffected", { count: result.affected_rows }) }}
{{ result.execution_time_ms }}ms
- {{ selectionSummary }}
+ {{ selectionSummary }}
@@ -2730,6 +2760,15 @@ defineExpose({
{{ t("grid.exportXlsx") }}
{{ t("grid.exportJson") }}
{{ t("grid.exportMarkdown") }}
+
+
+ {{ t("grid.exportSelectedRowsCsv") }}
+ {{ t("grid.exportSelectedRowsXlsx") }}
+ {{ t("grid.exportSelectedRowsJson") }}
+ {{
+ t("grid.exportSelectedRowsMarkdown")
+ }}
+
diff --git a/src/composables/useDataGridEditor.ts b/src/composables/useDataGridEditor.ts
index bc06718ac..264358a0e 100644
--- a/src/composables/useDataGridEditor.ts
+++ b/src/composables/useDataGridEditor.ts
@@ -448,6 +448,12 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) {
}
}
+ function restoreRows(rowIds: number[]) {
+ for (const rowId of rowIds) {
+ restoreRow(rowId);
+ }
+ }
+
function deleteSelectedRow(contextCell: Ref<{ rowId: number; rowIndex: number; col: number } | null>) {
if (!contextCell.value) return;
requestDeleteRow(contextCell.value.rowId);
@@ -679,6 +685,7 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) {
requestDeleteRows,
confirmDeleteRow,
restoreRow,
+ restoreRows,
deleteSelectedRow,
saveChanges,
discardChanges,
diff --git a/src/composables/useDataGridExport.ts b/src/composables/useDataGridExport.ts
index e2d4f6466..08c5188ff 100644
--- a/src/composables/useDataGridExport.ts
+++ b/src/composables/useDataGridExport.ts
@@ -68,6 +68,12 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
toast(t("grid.copied"));
}
+ function rowsToExport(rowIds?: number[]): RowItem[] {
+ if (!rowIds?.length) return displayItems.value;
+ const rowIdSet = new Set(rowIds);
+ return displayItems.value.filter((item) => rowIdSet.has(item.id));
+ }
+
// --- Selection copy functions ---
function copySelectionTsv() {
if (!hasCellSelection.value) return;
@@ -233,9 +239,9 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
}
// --- Export functions ---
- async function exportCsv() {
+ async function exportCsv(rowIds?: number[]) {
try {
- const rows = displayItems.value.map((item) => item.data.map((c) => displayCellValue(c)));
+ const rows = rowsToExport(rowIds).map((item) => item.data.map((c) => displayCellValue(c)));
if (await saveFileContent(formatCsv(columns.value, rows), "export.csv", "CSV", "csv")) {
toast(t("grid.exported"));
}
@@ -244,9 +250,9 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
}
}
- async function exportJson() {
+ async function exportJson(rowIds?: number[]) {
try {
- const rows = displayItems.value.map((item) => item.data);
+ const rows = rowsToExport(rowIds).map((item) => item.data);
if (await saveFileContent(formatJson(columns.value, rows), "export.json", "JSON", "json")) {
toast(t("grid.exported"));
}
@@ -255,10 +261,10 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
}
}
- async function exportMarkdown() {
+ async function exportMarkdown(rowIds?: number[]) {
try {
const cols = columns.value;
- const visibleRows = displayItems.value.map((item) => item.data);
+ const visibleRows = rowsToExport(rowIds).map((item) => item.data);
const { formatMarkdownTable } = await import("@/lib/markdownTable");
const md = formatMarkdownTable({ columns: cols, rows: visibleRows });
if (await saveFileContent(md, "export.md", "Markdown", "md")) {
@@ -269,13 +275,13 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
}
}
- async function exportXlsx() {
+ async function exportXlsx(rowIds?: number[]) {
try {
const { buildXlsxWorkbook } = await import("@/lib/xlsxExport");
const workbook = buildXlsxWorkbook({
sheetName: tableMeta.value?.tableName || "Export",
columns: columns.value,
- rows: displayItems.value.map((item) => item.data),
+ rows: rowsToExport(rowIds).map((item) => item.data),
});
if (await saveBinaryFileContent(workbook, "export.xlsx", "Excel", "xlsx")) {
toast(t("grid.exported"));
diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts
index ac1b6140f..77a753e23 100644
--- a/src/i18n/locales/en.ts
+++ b/src/i18n/locales/en.ts
@@ -246,6 +246,10 @@ export default {
exportXlsx: "Export XLSX",
exportJson: "Export JSON",
exportMarkdown: "Export Markdown",
+ exportSelectedRowsCsv: "Export Selected Rows as CSV",
+ exportSelectedRowsXlsx: "Export Selected Rows as XLSX",
+ exportSelectedRowsJson: "Export Selected Rows as JSON",
+ exportSelectedRowsMarkdown: "Export Selected Rows as Markdown",
exported: "Exported",
exportFailed: "Export failed: {message}",
filter: "Filter",
@@ -288,6 +292,7 @@ export default {
deleteRow: "Delete Row",
deleteRows: "Delete {count} Rows",
cloneRows: "Clone {count} Rows",
+ restoreRows: "Restore {count} Rows",
copyRows: "Copy {count} Rows (JSON)",
copyRowsInsert: "Copy {count} Rows as INSERT",
selectedRows: "{count} rows selected",
diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts
index fc00a198b..ba5c12a60 100644
--- a/src/i18n/locales/es.ts
+++ b/src/i18n/locales/es.ts
@@ -247,6 +247,10 @@ export default {
exportXlsx: "Exportar XLSX",
exportJson: "Exportar JSON",
exportMarkdown: "Exportar Markdown",
+ exportSelectedRowsCsv: "Exportar filas seleccionadas como CSV",
+ exportSelectedRowsXlsx: "Exportar filas seleccionadas como XLSX",
+ exportSelectedRowsJson: "Exportar filas seleccionadas como JSON",
+ exportSelectedRowsMarkdown: "Exportar filas seleccionadas como Markdown",
exported: "Exportado",
exportFailed: "Error al exportar: {message}",
filter: "Filtrar",
@@ -289,6 +293,7 @@ export default {
deleteRow: "Eliminar fila",
deleteRows: "Eliminar {count} filas",
cloneRows: "Clonar {count} filas",
+ restoreRows: "Restaurar {count} filas",
copyRows: "Copiar {count} filas (JSON)",
copyRowsInsert: "Copiar {count} filas como INSERT",
selectedRows: "{count} filas seleccionadas",
diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts
index 3e8e56fb1..d0209a616 100644
--- a/src/i18n/locales/zh-CN.ts
+++ b/src/i18n/locales/zh-CN.ts
@@ -245,6 +245,10 @@ export default {
exportXlsx: "导出 XLSX",
exportJson: "导出 JSON",
exportMarkdown: "导出 Markdown",
+ exportSelectedRowsCsv: "导出选中行为 CSV",
+ exportSelectedRowsXlsx: "导出选中行为 XLSX",
+ exportSelectedRowsJson: "导出选中行为 JSON",
+ exportSelectedRowsMarkdown: "导出选中行为 Markdown",
exported: "导出完成",
exportFailed: "导出失败:{message}",
filter: "筛选",
@@ -287,6 +291,7 @@ export default {
deleteRow: "删除行",
deleteRows: "删除 {count} 行",
cloneRows: "克隆 {count} 行",
+ restoreRows: "恢复 {count} 行",
copyRows: "复制 {count} 行 (JSON)",
copyRowsInsert: "复制 {count} 行为 INSERT",
selectedRows: "已选 {count} 行",