feat: restore source parity and harden agent runtime
This commit is contained in:
@@ -0,0 +1,289 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
import { Download, Printer } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
import { ReportDialogHeader, ZqUniverPrint } from '@zq/univer';
|
||||
import '@zq/univer/style';
|
||||
|
||||
import UniverHost from '../univer-host.vue';
|
||||
|
||||
import { ElButton, ElDialog, ElMessage, ElMessageBox } from 'element-plus';
|
||||
|
||||
import {
|
||||
exportReportDesignExcelApi,
|
||||
previewReportDesignApi,
|
||||
} from '#/api/online-dev/report-manager';
|
||||
import { useReportQuery } from '#/components/report-design/hooks/useReportQuery';
|
||||
import ReportQueryForm from '#/components/report-design/modules/report-query-form.vue';
|
||||
import { countSnapshotImages } from '#/components/report-design/utils/report-media-url';
|
||||
import { showPreviewWarnings } from '#/components/report-design/utils/preview-warnings';
|
||||
|
||||
const visible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
const props = defineProps<{
|
||||
versionId: string;
|
||||
reportCode?: string;
|
||||
reportName?: string;
|
||||
queryList: any[];
|
||||
getDraftPayload?: () => Record<string, any> | null | undefined;
|
||||
}>();
|
||||
|
||||
const loading = ref(false);
|
||||
const exportLoading = ref(false);
|
||||
const allowExport = ref(true);
|
||||
const allowPrint = ref(true);
|
||||
const printRef = ref<InstanceType<typeof ZqUniverPrint> | null>(null);
|
||||
const previewReady = ref(false);
|
||||
const previewSessionKey = ref(0);
|
||||
const previewSnapshot = ref<Record<string, any>>({});
|
||||
const previewCells = ref<Record<string, any>>({});
|
||||
const previewChartData = ref<any[]>([]);
|
||||
const previewWatermark = ref<{ show?: boolean; config?: Record<string, any> }>({
|
||||
show: false,
|
||||
config: {},
|
||||
});
|
||||
|
||||
const { searchSchemas, formValues, setQueryList, getDefaultParams, setFormValues } =
|
||||
useReportQuery();
|
||||
|
||||
watch(
|
||||
() => props.queryList,
|
||||
(list) => setQueryList(list || []),
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
function resetPreviewState() {
|
||||
previewReady.value = false;
|
||||
allowExport.value = true;
|
||||
allowPrint.value = true;
|
||||
previewSnapshot.value = {};
|
||||
previewCells.value = {};
|
||||
previewChartData.value = [];
|
||||
previewWatermark.value = { show: false, config: {} };
|
||||
}
|
||||
|
||||
watch(visible, async (v) => {
|
||||
if (!v) {
|
||||
resetPreviewState();
|
||||
return;
|
||||
}
|
||||
if (!props.versionId) return;
|
||||
|
||||
resetPreviewState();
|
||||
await runPreview();
|
||||
previewSessionKey.value += 1;
|
||||
previewReady.value = true;
|
||||
});
|
||||
|
||||
function buildDraftPayload() {
|
||||
const draft = props.getDraftPayload?.();
|
||||
if (!draft) return undefined;
|
||||
return {
|
||||
snapshot: draft.snapshot,
|
||||
cells: draft.cells,
|
||||
queryList: draft.queryList,
|
||||
sortList: draft.sortList,
|
||||
columnList: draft.columnList,
|
||||
fenceList: draft.fenceList,
|
||||
convertConfig: draft.convertConfig,
|
||||
};
|
||||
}
|
||||
|
||||
async function runPreview() {
|
||||
if (!props.versionId) return;
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await previewReportDesignApi(
|
||||
props.versionId,
|
||||
getDefaultParams(),
|
||||
buildDraftPayload(),
|
||||
);
|
||||
previewSnapshot.value = res.snapshot || {};
|
||||
previewCells.value = res.cells || {};
|
||||
previewChartData.value = Array.isArray(res.chartData)
|
||||
? res.chartData
|
||||
: [];
|
||||
previewWatermark.value =
|
||||
res.watermark && typeof res.watermark === 'object'
|
||||
? res.watermark
|
||||
: {
|
||||
show: !!res.allowWatermark,
|
||||
config: res.watermarkConfig || {},
|
||||
};
|
||||
allowExport.value = res.allowExport !== false;
|
||||
allowPrint.value = res.allowPrint !== false;
|
||||
showPreviewWarnings(Array.isArray(res.warnings) ? res.warnings : []);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleExportExcel() {
|
||||
if (exportLoading.value || !props.versionId) return;
|
||||
if (!allowExport.value) {
|
||||
ElMessage.warning($t('report-manager.export.notAllowed'));
|
||||
return;
|
||||
}
|
||||
exportLoading.value = true;
|
||||
try {
|
||||
const blob = await exportReportDesignExcelApi(
|
||||
props.versionId,
|
||||
getDefaultParams(),
|
||||
buildDraftPayload(),
|
||||
);
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `${props.reportCode || props.reportName || 'report'}.xlsx`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
ElMessage.success($t('report-manager.export.success'));
|
||||
} catch (error: any) {
|
||||
ElMessage.error(error?.message || $t('report-manager.export.failed'));
|
||||
} finally {
|
||||
exportLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePrint() {
|
||||
if (!allowPrint.value) {
|
||||
ElMessage.warning($t('report-manager.print.notAllowed'));
|
||||
return;
|
||||
}
|
||||
if (!previewSnapshot.value || !Object.keys(previewSnapshot.value).length) {
|
||||
ElMessage.warning($t('report-manager.render.empty'));
|
||||
return;
|
||||
}
|
||||
|
||||
const imageCount = countSnapshotImages(previewSnapshot.value, previewCells.value);
|
||||
if (imageCount > 100) {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
$t('report-manager.print.imageWarn', { count: imageCount }),
|
||||
$t('report-manager.print.title'),
|
||||
{ type: 'warning' },
|
||||
);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printRef.value?.handleCreatePrintUnit?.({
|
||||
snapshot: previewSnapshot.value as any,
|
||||
watermarkConfig: previewWatermark.value,
|
||||
reportName: props.reportName,
|
||||
reportCode: props.reportCode,
|
||||
});
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
visible.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="visible"
|
||||
class="report-preview-dialog"
|
||||
fullscreen
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:show-close="false"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div class="bg-background flex h-full min-h-0 flex-col">
|
||||
<ReportDialogHeader
|
||||
:report-name="reportName"
|
||||
:report-code="reportCode"
|
||||
:fallback-title="$t('report-manager.preview.title')"
|
||||
>
|
||||
<template #actions>
|
||||
<ElButton
|
||||
v-if="allowExport"
|
||||
:icon="Download"
|
||||
:loading="exportLoading"
|
||||
@click="handleExportExcel"
|
||||
>
|
||||
{{ $t('report-manager.export.title') }}
|
||||
</ElButton>
|
||||
<ElButton v-if="allowPrint" :icon="Printer" @click="handlePrint">
|
||||
{{ $t('report-manager.print.title') }}
|
||||
</ElButton>
|
||||
<ElButton @click="handleClose">
|
||||
{{ $t('common.close') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
</ReportDialogHeader>
|
||||
|
||||
<main
|
||||
v-loading="loading"
|
||||
class="report-preview-dialog__content m-3 min-h-0 min-w-0 flex-1 overflow-hidden rounded-lg"
|
||||
>
|
||||
<ReportQueryForm
|
||||
:schemas="searchSchemas"
|
||||
:model-value="formValues"
|
||||
:loading="loading"
|
||||
@update:model-value="setFormValues"
|
||||
@search="runPreview"
|
||||
/>
|
||||
<div class="report-preview-dialog__sheet">
|
||||
<UniverHost
|
||||
v-if="previewReady"
|
||||
:key="previewSessionKey"
|
||||
mode="preview"
|
||||
readonly
|
||||
class="h-full w-full"
|
||||
:snapshot="previewSnapshot"
|
||||
:cells="previewCells"
|
||||
:chart-data="previewChartData"
|
||||
:watermark="previewWatermark"
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</ElDialog>
|
||||
|
||||
<Teleport to="body">
|
||||
<ZqUniverPrint ref="printRef" />
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.report-preview-dialog.el-dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
.el-dialog__header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.report-preview-dialog__content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.report-preview-dialog__sheet {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user