刘光辉
3 小时以前 cf11e63b659afcc9792ab3e395f1b45d844431a8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<script lang="ts" setup>
import type { DmsCompareSession } from '#/api/x/dms/compare';
import type { DmsFileCenterItem } from '#/api/x/dms/fileCenter';
 
import { computed, ref } from 'vue';
 
import { BasicForm, useForm } from '@jnpf/ui/form';
import { BasicModal, useModalInner } from '@jnpf/ui/modal';
import { formatToDateTime } from '@jnpf/utils';
 
import { v4 as uuidv4 } from 'uuid';
 
import { createDmsCompareSession } from '#/api/x/dms/compare';
import { getDocumentVersions } from '#/api/x/dms/fileCenter';
 
import { comparableVersions, versionLabel } from './compareRules';
 
const emit = defineEmits<{ compare: [session: DmsCompareSession] }>();
const current = ref<DmsFileCenterItem>();
const versions = ref<DmsFileCenterItem[]>([]);
const selectedId = ref<string>();
const cursor = ref<string>();
const hasMore = ref(false);
const loading = ref(false);
const submitting = ref(false);
const error = ref('');
let generation = 0;
const options = computed(() =>
  versions.value.map((item) => ({
    value: item.id,
    label: `${versionLabel(item)} · ${formatToDateTime(item.createdAt)}`,
  })),
);
const [registerForm, { resetFields, validate }] = useForm({
  baseColProps: { span: 24 },
  layout: 'vertical',
  schemas: [
    {
      component: 'Select',
      componentProps: () => ({
        disabled: submitting.value,
        fieldNames: { label: 'label', value: 'value' },
        loading: loading.value,
        onChange: (value?: string) => (selectedId.value = value),
        options: options.value,
        placeholder: '请选择之前修订的版本',
      }),
      field: 'historicalVersionId',
      label: '历史版本号',
      rules: [{ message: '请选择历史版本号', required: true, trigger: 'change' }],
    },
  ],
  showActionButtonGroup: false,
});
const [registerModal, { closeModal }] = useModalInner(async (data: { item: DmsFileCenterItem }) => {
  generation++;
  current.value = data.item;
  versions.value = [];
  selectedId.value = undefined;
  cursor.value = undefined;
  hasMore.value = false;
  submitting.value = false;
  error.value = '';
  await resetFields();
  await loadVersions();
});
 
async function loadVersions() {
  const item = current.value;
  if (!item?.documentId) return;
  const requestGeneration = generation;
  loading.value = true;
  error.value = '';
  try {
    const response = await getDocumentVersions('HISTORICAL', item.documentId, { pageSize: 50, cursor: cursor.value });
    if (requestGeneration !== generation) return;
    const unique = new Map([...versions.value, ...response.data.list].map((version) => [version.id, version]));
    versions.value = comparableVersions(item, [...unique.values()]);
    cursor.value = response.data.nextCursor;
    hasMore.value = response.data.hasMore && !!response.data.nextCursor;
  } catch (error_) {
    if (requestGeneration === generation) error.value = error_ instanceof Error ? error_.message : '历史版本加载失败,请重试';
  } finally {
    if (requestGeneration === generation) loading.value = false;
  }
}
 
function cancel() {
  generation++;
}
 
async function submit() {
  const item = current.value;
  if (!item?.documentId || submitting.value) return;
  const values = await validate();
  if (!values) return;
  const historicalVersionId = String(values.historicalVersionId || '');
  if (!historicalVersionId) return;
  const requestGeneration = generation;
  submitting.value = true;
  error.value = '';
  try {
    const session = await createDmsCompareSession({
      documentId: item.documentId,
      currentVersionId: item.id,
      historicalVersionId,
      operationId: uuidv4(),
    });
    if (requestGeneration !== generation) return;
    closeModal();
    emit('compare', session);
  } catch (error_) {
    if (requestGeneration === generation) error.value = error_ instanceof Error ? error_.message : '无法开始比较,请刷新后重试';
  } finally {
    if (requestGeneration === generation) submitting.value = false;
  }
}
</script>
 
<template>
  <BasicModal
    v-bind="$attrs"
    title="版本比较"
    :width="560"
    :confirm-loading="submitting"
    :ok-button-props="{ disabled: !selectedId || loading || submitting }"
    @register="registerModal"
    @ok="submit"
    @cancel="cancel">
    <a-descriptions bordered size="small" :column="1" class="mb-[20px]">
      <a-descriptions-item label="文件名称">{{ current?.fileName || current?.name }}</a-descriptions-item>
      <a-descriptions-item label="现行版本">{{ versionLabel(current) }}</a-descriptions-item>
    </a-descriptions>
    <BasicForm @register="registerForm" />
    <a-button v-if="hasMore" type="link" :loading="loading" :disabled="submitting" @click="loadVersions">加载更多历史版本</a-button>
    <jnpf-empty v-if="!loading && !error && versions.length === 0" description="没有可比较的历史 DOCX 版本" />
    <p v-if="submitting">正在生成版本差异,请稍候…</p>
    <a-alert v-if="error" type="error" show-icon :message="error" class="mb-[12px]" />
    <a-button v-if="error && !submitting" type="link" @click="loadVersions">重新加载版本</a-button>
    <div class="text-secondary">以历史版本为基准,查看现行版本的新增、删除及修改。</div>
  </BasicModal>
</template>