<script lang="ts" setup>
|
import type { ElnRecordsTab } from './types';
|
|
import type { InspectionProjectItem } from '#/api/x/lims/jianyanguanli/jianyan_jindu';
|
|
import { onUnmounted, ref, watch } from 'vue';
|
|
import { Empty, Result, Spin } from 'ant-design-vue';
|
|
import { getRecordByTestWorkItem } from '#/api/x/eln/records';
|
import { postInspectionProgressDetail } from '#/api/x/lims/jianyanguanli/jianyan_jindu';
|
import { getOnlyOfficeConfig } from '#/api/x/onlyoffice';
|
import OnlyOfficeEditor from '#/components/OnlyOfficeEditor/src/Editor.vue';
|
import { toElnRecordOfficeConfigQuery, unwrapElnRecordEditorConfig } from '#/views/x/eln/records/editor/recordView';
|
|
const props = defineProps<{
|
tab: ElnRecordsTab;
|
}>();
|
|
const projects = ref<InspectionProjectItem[]>([]);
|
const selectedId = ref('');
|
const listLoading = ref(false);
|
const recordLoading = ref(false);
|
const listError = ref('');
|
const recordError = ref('');
|
const editorConfig = ref<Record<string, any>>();
|
let listRequestId = 0;
|
let recordRequestId = 0;
|
|
function responseData<T>(response: unknown): T {
|
return (((response as { data?: unknown })?.data ?? response) || {}) as T;
|
}
|
|
async function loadRecord(testWorkItemId: string) {
|
const currentRequestId = ++recordRequestId;
|
selectedId.value = testWorkItemId;
|
recordLoading.value = true;
|
recordError.value = '';
|
editorConfig.value = undefined;
|
|
try {
|
const recordResponse = await getRecordByTestWorkItem(testWorkItemId);
|
const record = responseData<any>(recordResponse);
|
const configResponse = await getOnlyOfficeConfig(
|
toElnRecordOfficeConfigQuery({
|
document: record.document,
|
mode: 'view',
|
recordId: record.recordId,
|
revisionId: record.revisionId,
|
}),
|
);
|
if (currentRequestId !== recordRequestId) return;
|
editorConfig.value = unwrapElnRecordEditorConfig(configResponse);
|
} catch (error: any) {
|
if (currentRequestId !== recordRequestId) return;
|
recordError.value = error?.message || '加载电子记录失败';
|
} finally {
|
if (currentRequestId === recordRequestId) recordLoading.value = false;
|
}
|
}
|
|
async function loadProjects() {
|
const currentRequestId = ++listRequestId;
|
recordRequestId++;
|
listLoading.value = true;
|
listError.value = '';
|
recordError.value = '';
|
editorConfig.value = undefined;
|
selectedId.value = '';
|
projects.value = [];
|
|
if (!props.tab.qingyandanId?.trim()) {
|
listError.value = '缺少请验单 ID';
|
listLoading.value = false;
|
return;
|
}
|
|
try {
|
const response = await postInspectionProgressDetail({ qingyandan_id: props.tab.qingyandanId.trim() });
|
const detail = responseData<any>(response);
|
const nextProjects = detail.project_detail || detail.projectDetail || [];
|
if (currentRequestId !== listRequestId) return;
|
projects.value = Array.isArray(nextProjects) ? nextProjects : [];
|
const first = projects.value[0];
|
if (first?.id) await loadRecord(first.id);
|
} catch (error: any) {
|
if (currentRequestId !== listRequestId) return;
|
listError.value = error?.message || '加载检验项失败';
|
} finally {
|
if (currentRequestId === listRequestId) listLoading.value = false;
|
}
|
}
|
|
watch(() => props.tab.qingyandanId, loadProjects, { immediate: true });
|
onUnmounted(() => {
|
listRequestId++;
|
recordRequestId++;
|
});
|
</script>
|
|
<template>
|
<div class="report-eln-records-pane">
|
<div v-if="listLoading" class="report-eln-records-pane__state">
|
<Spin size="large" tip="加载检验项中..." />
|
</div>
|
<Result v-else-if="listError" status="error" :title="listError" />
|
<Empty v-else-if="!projects.length" description="暂无检验项" />
|
<template v-else>
|
<nav class="report-eln-records-pane__projects" aria-label="检验项目">
|
<button
|
v-for="project in projects"
|
:key="project.id"
|
:aria-pressed="selectedId === project.id"
|
:class="{ 'is-active': selectedId === project.id }"
|
:data-test="`eln-project-${project.id}`"
|
type="button"
|
@click="loadRecord(project.id)">
|
{{ project.name || project.id }}
|
</button>
|
</nav>
|
<section class="report-eln-records-pane__document">
|
<div v-if="recordLoading" class="report-eln-records-pane__state">
|
<Spin size="large" tip="加载电子记录中..." />
|
</div>
|
<Result v-else-if="recordError" data-test="eln-record-error" status="info" :title="recordError" />
|
<OnlyOfficeEditor v-else-if="editorConfig" :key="editorConfig.document.key" :config="editorConfig" data-test="eln-onlyoffice-editor" />
|
</section>
|
</template>
|
</div>
|
</template>
|
|
<style lang="scss" scoped>
|
.report-eln-records-pane {
|
display: grid;
|
grid-template-columns: minmax(180px, 240px) minmax(0, 1fr);
|
height: 100%;
|
min-height: 420px;
|
|
&__projects {
|
overflow: auto;
|
border-right: 1px solid rgb(0 0 0 / 8%);
|
background: #fafafa;
|
|
button {
|
display: block;
|
width: 100%;
|
min-height: 42px;
|
padding: 10px 16px;
|
overflow-wrap: anywhere;
|
color: rgb(0 0 0 / 88%);
|
text-align: left;
|
background: transparent;
|
border: 0;
|
border-bottom: 1px solid rgb(0 0 0 / 6%);
|
cursor: pointer;
|
}
|
|
button:hover {
|
background: rgb(0 0 0 / 4%);
|
}
|
|
button.is-active {
|
color: var(--primary-color);
|
background: var(--primary-1);
|
box-shadow: inset 3px 0 0 var(--primary-color);
|
}
|
}
|
|
&__document {
|
min-width: 0;
|
min-height: 0;
|
}
|
|
&__state {
|
display: flex;
|
grid-column: 1 / -1;
|
align-items: center;
|
justify-content: center;
|
min-height: 420px;
|
}
|
}
|
|
@media (width <= 720px) {
|
.report-eln-records-pane {
|
grid-template-rows: auto minmax(0, 1fr);
|
grid-template-columns: minmax(0, 1fr);
|
|
&__projects {
|
display: flex;
|
overflow-x: auto;
|
border-right: 0;
|
border-bottom: 1px solid rgb(0 0 0 / 8%);
|
|
button {
|
width: auto;
|
min-width: 120px;
|
border-right: 1px solid rgb(0 0 0 / 6%);
|
border-bottom: 0;
|
}
|
|
button.is-active {
|
box-shadow: inset 0 -3px 0 var(--primary-color);
|
}
|
}
|
}
|
}
|
</style>
|