<script lang="ts" setup>
|
import { computed, reactive, ref, toRefs, unref } from 'vue';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { BasicModal, useModalInner } from '@jnpf/ui/modal';
|
|
import { InfoCircleFilled } from '@ant-design/icons-vue';
|
|
import { copyVersion, delVersion, getVersionInfo, getVersionList, saveVersion } from '#/api/onlineDev/report';
|
import logoImg from '#/assets/images/jnpf.png';
|
import { $t } from '#/locales';
|
|
import Design from './design/index.vue';
|
|
const emit = defineEmits(['register', 'reload']);
|
|
// eslint-disable-next-line no-unused-vars, unused-imports/no-unused-vars
|
const directionTypeOptions = [
|
{ id: 'ltr', fullName: '从左至右' },
|
{ id: 'rtl', fullName: '从右至左' },
|
];
|
const dateFormatOptions = [
|
{ id: 'yyyy', fullName: 'yyyy' },
|
{ id: 'yyyy-MM', fullName: 'yyyy-MM' },
|
{ id: 'yyyy-MM-dd', fullName: 'yyyy-MM-dd' },
|
{ id: 'yyyy-MM-dd HH:mm', fullName: 'yyyy-MM-dd HH:mm' },
|
{ id: 'yyyy-MM-dd HH:mm:ss', fullName: 'yyyy-MM-dd HH:mm:ss' },
|
];
|
|
const defaultWatermarkConfig = {
|
content: '内部使用',
|
fontSize: 32,
|
color: '#B8B8B8',
|
bold: false,
|
italic: false,
|
direction: 'ltr', // 'ltr' | 'rtl' | 'inherit'
|
x: 80,
|
y: 200,
|
repeat: true,
|
spacingX: 200,
|
spacingY: 200,
|
rotate: -45,
|
opacity: 0.2,
|
showTime: false,
|
timeFormat: 'yyyy-MM-dd',
|
};
|
|
interface State {
|
dataForm: any;
|
btnLoading: boolean;
|
saveBtnLoading: boolean;
|
loading: boolean;
|
isReload: boolean;
|
versionVisible: boolean;
|
versionList: any[];
|
currentVersion: any;
|
key: number;
|
activeKey: number;
|
allowExport: number;
|
allowPrint: number;
|
allowWatermark: number;
|
watermarkConfig: any;
|
}
|
const state = reactive<State>({
|
dataForm: {},
|
btnLoading: false,
|
saveBtnLoading: false,
|
loading: true,
|
isReload: false,
|
versionVisible: false,
|
versionList: [],
|
currentVersion: {},
|
key: 0,
|
activeKey: 0,
|
allowExport: 1,
|
allowPrint: 1,
|
allowWatermark: 0,
|
watermarkConfig: {},
|
});
|
|
const {
|
dataForm,
|
btnLoading,
|
saveBtnLoading,
|
loading,
|
versionVisible,
|
versionList,
|
currentVersion,
|
activeKey,
|
allowExport,
|
allowPrint,
|
allowWatermark,
|
watermarkConfig,
|
} = toRefs(state);
|
const reportDesign = ref();
|
const { createMessage } = useMessage();
|
const [registerModal, { closeModal, changeLoading }] = useModalInner(init);
|
|
const getBindValue = computed(() => ({
|
dataSetList: state.dataForm.dataSetList || [],
|
convertConfig: state.dataForm.convertConfig ? JSON.parse(state.dataForm.convertConfig) : [],
|
versionState: state.currentVersion?.state,
|
snapshot: state.dataForm.snapshot,
|
customs: state.dataForm.customs,
|
queryList: state.dataForm.queryList,
|
cells: state.dataForm.cells,
|
versionId: state.currentVersion?.id,
|
sortList: state.dataForm.sortList,
|
columnList: state.dataForm.columnList,
|
key: state.key,
|
}));
|
|
function init(data) {
|
state.isReload = false;
|
state.dataForm.id = data.id || '';
|
state.dataForm.fullName = data.fullName || '';
|
state.loading = true;
|
state.activeKey = 0;
|
state.watermarkConfig = {};
|
changeLoading(true);
|
initData();
|
}
|
|
function initData(update = true) {
|
getVersionList(state.dataForm.id)
|
.then((res) => {
|
state.versionList = res.data || [];
|
if (!update) return;
|
state.currentVersion = state.versionList[0] || {};
|
initReportData();
|
})
|
.catch(() => {
|
state.loading = false;
|
changeLoading(false);
|
});
|
}
|
function initReportData() {
|
if (!state.currentVersion.id) return;
|
changeLoading(true);
|
getVersionInfo(state.currentVersion.id)
|
.then((res) => {
|
state.dataForm = { ...state.dataForm, ...res.data };
|
state.allowExport = res.data.allowExport || 0;
|
state.allowPrint = res.data.allowPrint || 0;
|
state.allowWatermark = res.data.allowWatermark || 0;
|
state.watermarkConfig = res.data.watermarkConfig ? JSON.parse(res.data.watermarkConfig) : { ...defaultWatermarkConfig };
|
state.loading = false;
|
changeLoading(false);
|
state.key = Date.now();
|
})
|
.catch(() => {
|
state.dataForm = {};
|
state.loading = false;
|
changeLoading(false);
|
state.key = Date.now();
|
});
|
}
|
function getVersionColor(state) {
|
return state == 0 ? 'rgba(247,171,51,0.9)' : state == 1 ? 'rgba(75, 222, 0, 0.9)' : 'rgba(152,158,178,0.9)';
|
}
|
function getVersionState(state) {
|
return state == 0 ? '设计中' : state == 1 ? '启用中' : '已归档';
|
}
|
function handleAddVersion() {
|
copyVersion(state.currentVersion.id).then((res) => {
|
const currentId = res.data;
|
getVersionList(state.dataForm.id).then((res) => {
|
state.versionList = res.data || [];
|
if (currentId) {
|
const list = state.versionList.filter((o) => o.id == currentId);
|
state.currentVersion = list.length ? list[0] : state.versionList[0];
|
}
|
initReportData();
|
});
|
});
|
}
|
function handleChangeVersion(item) {
|
if (state.currentVersion.id == item.id) return;
|
state.versionVisible = false;
|
state.currentVersion = item;
|
initReportData();
|
}
|
function handleDelVersion(id) {
|
delVersion(id).then((res) => {
|
createMessage.success(res.msg);
|
initData(state.currentVersion.id === id);
|
});
|
}
|
function handleSubmit(type = 0) {
|
(unref(reportDesign) as any)
|
.getData()
|
.then((reportRes: any) => {
|
const query = {
|
...state.dataForm,
|
...reportRes,
|
type,
|
allowExport: state.allowExport,
|
allowPrint: state.allowPrint,
|
allowWatermark: state.allowWatermark,
|
watermarkConfig: JSON.stringify(state.watermarkConfig),
|
};
|
type == 1 ? (state.btnLoading = true) : (state.saveBtnLoading = true);
|
saveVersion(query)
|
.then((res) => {
|
createMessage.success(res.msg);
|
state.saveBtnLoading = false;
|
state.btnLoading = false;
|
state.isReload = true;
|
state.dataForm = { ...state.dataForm, ...reportRes };
|
if (!type) return;
|
state.currentVersion.state = 1;
|
initData(false);
|
})
|
.catch(() => {
|
state.saveBtnLoading = false;
|
state.btnLoading = false;
|
});
|
})
|
.catch((error) => {
|
error?.message && createMessage.warning(error.message);
|
})
|
.finally(() => {
|
changeLoading(false);
|
});
|
}
|
|
async function handleCancel() {
|
(unref(reportDesign) as any)?.handleDisposeUnit();
|
|
setTimeout(() => {
|
closeModal();
|
if (state.isReload) emit('reload');
|
}, 500);
|
|
// 删除 .univer-theme 下的 .univer-dialog-root 元素
|
setTimeout(() => {
|
const roots = document.querySelectorAll(
|
'.univer-fixed.univer-box-border, .univer-pointer-events-auto.univer-fixed, .univer-theme .univer-dialog-root, .univer-theme .univer-popup-fixed',
|
);
|
roots.forEach((el) => el.remove());
|
}, 600); // 等 modal 完成关闭再删除
|
}
|
function handleCloseVersionPopover() {
|
state.versionVisible = false;
|
}
|
function changeModalLoading(loading) {
|
changeLoading(loading);
|
}
|
</script>
|
<template>
|
<BasicModal
|
v-bind="$attrs"
|
@register="registerModal"
|
default-fullscreen
|
:footer="null"
|
:closable="false"
|
:keyboard="false"
|
:z-index="1000"
|
class="jnpf-full-modal full-modal designer-modal">
|
<template #title>
|
<div class="jnpf-full-modal-header">
|
<div class="header-title !w-auto">
|
<img :src="logoImg" class="header-logo" />
|
<span class="header-dot"></span>
|
<a-tooltip :title="dataForm.fullName">
|
<p class="header-txt">{{ dataForm.fullName }}</p>
|
</a-tooltip>
|
<a-popover
|
v-model:open="versionVisible"
|
trigger="click"
|
placement="bottom"
|
overlay-class-name="jnpf-version-popover"
|
arrow-point-at-center
|
destroy-tooltip-on-hide
|
v-if="currentVersion?.id">
|
<template #content>
|
<div class="w-[250px]">
|
<div class="version-list">
|
<div v-for="item in versionList" class="version-item" :key="item.id" @click="handleChangeVersion(item)">
|
<span class="version-badge" :style="{ background: getVersionColor(item.state) }"></span>
|
<span class="version-name">{{ item.fullName }}</span>
|
<span class="version-state" :style="{ background: getVersionColor(item.state) }">{{ getVersionState(item.state) }}</span>
|
<div class="version-delete">
|
<i class="icon-ym icon-ym-app-delete" @click.stop="handleDelVersion(item.id)" v-if="!item.state && versionList.length > 1"></i>
|
</div>
|
</div>
|
</div>
|
<div class="add-btn" @click="handleAddVersion">
|
<a-button type="link" pre-icon="icon-ym icon-ym-btn-add">新增报表版本</a-button>
|
</div>
|
</div>
|
</template>
|
<a-button type="text" class="current-version">
|
<span class="version-badge" :style="{ background: getVersionColor(currentVersion.state) }"></span>{{ currentVersion?.fullName }}
|
<i class="icon-ym icon-ym-unfold font ml-[5px] text-[10px]"></i>
|
</a-button>
|
</a-popover>
|
<div class="version-tip" v-if="currentVersion?.state != 0">
|
<InfoCircleFilled class="icon" />
|
{{ currentVersion?.state == 1 ? '启用中' : '已归档' }}的版本不可修改,请
|
<a-button type="link" class="px-[2px]" @click="handleAddVersion">添加新版本</a-button>
|
</div>
|
</div>
|
<a-steps v-model:current="activeKey" type="navigation" size="small" class="header-steps tab-steps">
|
<a-step title="报表建模" />
|
<a-step title="报表设置" />
|
</a-steps>
|
<a-space class="options" :size="10">
|
<a-button shape="round" type="primary" @click="handleSubmit(1)" v-if="currentVersion?.state !== 1" :loading="btnLoading" :disabled="saveBtnLoading">
|
{{ currentVersion?.state == 2 ? '启用' : '发布' }}
|
</a-button>
|
<a-button shape="round" type="primary" @click="handleSubmit()" :loading="saveBtnLoading" :disabled="btnLoading" v-if="!currentVersion?.state">
|
{{ $t('common.saveText') }}
|
</a-button>
|
<a-button shape="round" @click="handleCancel()">{{ $t('common.closeText') }}</a-button>
|
</a-space>
|
</div>
|
</template>
|
|
<div class="jnpf-basic-report-designer h-full">
|
<Design
|
ref="reportDesign"
|
v-bind="getBindValue"
|
@close-version-popover="handleCloseVersionPopover"
|
@change-modal-loading="changeModalLoading"
|
v-if="!loading" />
|
<div v-if="activeKey == 1" class="report-config-container">
|
<a-row type="flex" justify="center" align="middle" class="h-full">
|
<a-col :span="12" :xxl="10" class="report-config-container-main">
|
<a-form :model="dataForm" :colon="false">
|
<a-form-item>
|
<template #label>允许导出<BasicHelp text="禁用后,「设计预览」和「发布到菜单中的报表」导出按钮不显示" /></template>
|
<a-switch v-model:checked="allowExport" :checked-value="1" :un-checked-value="0" />
|
</a-form-item>
|
<a-form-item>
|
<template #label>允许打印<BasicHelp text="禁用后,「设计预览」和「发布到菜单中的报表」打印按钮不显示" /></template>
|
<a-switch v-model:checked="allowPrint" :checked-value="1" :un-checked-value="0" />
|
</a-form-item>
|
<a-form-item>
|
<template #label>显示水印<BasicHelp text="启用后,「设计预览」、「打印预览」、「打印」和「发布到菜单中的报表」显示水印" /></template>
|
<a-switch v-model:checked="allowWatermark" :checked-value="1" :un-checked-value="0" />
|
</a-form-item>
|
<template v-if="allowWatermark">
|
<a-form-item label="水印内容">
|
<a-input v-model:value="watermarkConfig.content" placeholder="最长限制15个长度" :maxlength="15" allow-clear />
|
</a-form-item>
|
<a-form-item label="字体大小">
|
<a-input-number :max="80" :min="10" v-model:value="watermarkConfig.fontSize" />
|
</a-form-item>
|
<a-form-item label="字体颜色">
|
<jnpf-color-picker v-model:value="watermarkConfig.color" size="small" />
|
</a-form-item>
|
<a-form-item label="是否加粗">
|
<a-switch v-model:checked="watermarkConfig.bold" />
|
</a-form-item>
|
<a-form-item label="是否斜体">
|
<a-switch v-model:checked="watermarkConfig.italic" />
|
</a-form-item>
|
<a-form-item label="不透明度">
|
<a-input-number :max="1" :min="0" v-model:value="watermarkConfig.opacity" />
|
</a-form-item>
|
<a-form-item label="旋转角度">
|
<a-input-number v-model:value="watermarkConfig.rotate" />
|
</a-form-item>
|
<a-form-item label="横向起点">
|
<a-input-number v-model:value="watermarkConfig.x" />
|
</a-form-item>
|
<a-form-item label="纵向起点">
|
<a-input-number v-model:value="watermarkConfig.y" />
|
</a-form-item>
|
<a-form-item label="重复显示">
|
<a-switch v-model:checked="watermarkConfig.repeat" />
|
</a-form-item>
|
<a-form-item>
|
<template #label>水平密度<BasicHelp text="启用「重复显示」功能后,配置参数方可生效" /></template>
|
<a-input-number v-model:value="watermarkConfig.spacingX" />
|
</a-form-item>
|
<a-form-item>
|
<template #label>垂直密度<BasicHelp text="启用「重复显示」功能后,配置参数方可生效" /></template>
|
<a-input-number v-model:value="watermarkConfig.spacingY" />
|
</a-form-item>
|
<a-form-item label="显示时间">
|
<a-switch v-model:checked="watermarkConfig.showTime" />
|
</a-form-item>
|
<a-form-item label="时间格式" v-if="watermarkConfig.showTime">
|
<jnpf-select v-model:value="watermarkConfig.timeFormat" :options="dateFormatOptions" placeholder="请选择" />
|
</a-form-item>
|
</template>
|
</a-form>
|
</a-col>
|
</a-row>
|
</div>
|
</div>
|
</BasicModal>
|
</template>
|