211 lines
5.1 KiB
Vue
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>
|