Files
SPDM/src/components/common/treeCaseTable/reportTemplateSelect.vue
JiangSheng b427715638 feat: 报告模版工况绑定
(cherry picked from commit 9f2b8e6468)
2026-03-09 10:04:46 +08:00

211 lines
5.1 KiB
Vue

<template>
<div class="full">
<el-select-v2
v-if="editable"
v-model="selected"
:options="options"
class="full"
:clearable="clearable"
:size="size"
:multiple="multiple"
:collapse-tags="multiple"
:collapse-tags-tooltip="multiple"
:fit-input-width="false"
@change="onChange"
/>
<span v-else class="plain-label">
<template v-if="selectedTemplates.length === 1">
<el-icon
class="view"
@click="previewReport(selectedTemplates[0].uuid)"
:title="$t('通用.预览')"
>
<View />
</el-icon>
<OverflowTooltip :content="selectedTemplates[0].templateName" max-width="120px" />
</template>
<template v-else-if="selectedTemplates.length >= 2">
<el-popover
placement="bottom"
trigger="hover"
:width="400"
popper-class="report-template-select-popover"
>
<template #reference>
<span class="link-text">
{{ $t('工况库.关联N个报告模版', { count: selectedTemplates.length }) }}
</span>
</template>
<div class="template-list">
<div v-for="item in selectedTemplates" :key="item.uuid" class="template-item">
<el-icon class="view" :title="$t('通用.预览')" @click="previewReport(item.uuid)">
<View />
</el-icon>
<OverflowTooltip :content="item.templateName" class="item-name" />
</div>
</div>
</el-popover>
</template>
</span>
<ReportViewDialog
v-if="reportViewVisible"
v-model:showDialog="reportViewVisible"
:reportFileId="currentPreviewFileId"
:reportUuid="currentPreviewUuid"
/>
</div>
</template>
<script setup lang="ts">
import { ref, watch, computed } from 'vue';
import { useReportStore } from '@/stores/reportTemplate';
import ReportViewDialog from '@/components/common/report/reportViewDialog.vue';
import OverflowTooltip from '@/components/common/text/overflowTooltip.vue';
import { View } from '@element-plus/icons-vue';
interface Props {
modelValue?: any;
clearable?: boolean;
editable?: boolean;
size?: '' | 'large' | 'default' | 'small';
multiple?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
modelValue: '',
clearable: false,
editable: true,
size: 'default',
multiple: true,
});
const emits = defineEmits(['update:modelValue', 'change']);
const parseValue = (value: string): string[] | string => {
if (!value) return props.multiple ? [] : '';
if (props.multiple) {
return value.split(',').filter((v) => v.trim());
}
return value;
};
const stringifyValue = (value: string[] | string): string => {
if (props.multiple && Array.isArray(value)) {
return value.join(',');
}
return String(value || '');
};
const selected = ref<string[] | string>(parseValue(props.modelValue));
watch(
() => props.modelValue,
(v) => {
selected.value = parseValue(v);
}
);
watch(selected, (v) => {
const stringValue = stringifyValue(v);
emits('update:modelValue', stringValue);
});
const reportStore = useReportStore();
const options = computed(() => reportStore.options);
const selectedCodes = computed(() => {
if (props.multiple && Array.isArray(selected.value)) {
return selected.value;
}
return selected.value ? [selected.value] : [];
});
const selectedTemplates = computed(() => {
return reportStore.templates.filter((t: any) => selectedCodes.value.includes(t.templateCode));
});
const onChange = (val: string[] | string) => {
emits('change', stringifyValue(val));
};
const reportViewVisible = ref(false);
const currentPreviewUuid = ref('');
const currentPreviewFileId = ref('');
const previewReport = (uuid: string) => {
const template = reportStore.templates.find((t: any) => t.uuid === uuid);
if (template) {
currentPreviewUuid.value = uuid;
currentPreviewFileId.value = template.fileId || '';
reportViewVisible.value = true;
}
};
</script>
<style scoped lang="scss">
.full {
width: 100%;
}
.plain-label {
display: inline-flex;
align-items: center;
gap: 6px;
vertical-align: middle;
line-height: 1;
max-width: 100%;
.view {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
cursor: pointer;
color: var(--el-color-primary);
flex-shrink: 0;
}
.link-text {
color: var(--el-color-primary);
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
}
.template-list {
max-height: 400px;
overflow-y: auto;
.template-item {
display: flex;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid var(--el-border-color-lighter);
&:last-child {
border-bottom: none;
}
.item-name {
flex: 1;
min-width: 0;
}
.view {
flex-shrink: 0;
cursor: pointer;
color: var(--el-color-primary);
margin-right: 8px;
}
}
}
</style>
<style lang="scss">
.report-template-select-popover {
max-height: 450px;
overflow: hidden;
}
</style>