fix(desktop): не показывать ложное несовпадение контрольной суммы документа
Пересчёт хэша при появлении binary и состояние загрузки вместо предупреждения, пока PDF ещё не готов. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -19,6 +19,7 @@ q-card.dynamic-padding(
|
||||
DocumentSignatures(
|
||||
:doc-hash='documentAggregate?.document?.doc_hash ?? ""',
|
||||
:regenerated-hash='regeneratedHash',
|
||||
:hash-loading='hashComputing',
|
||||
:signatures='canonSignatures',
|
||||
:verifying='onRegenerate',
|
||||
:hide-verify='true',
|
||||
@@ -27,7 +28,7 @@ q-card.dynamic-padding(
|
||||
)
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { useGlobalStore } from 'src/shared/store';
|
||||
import DOMPurify from 'dompurify';
|
||||
import { DigitalDocument, prepareDocumentArchive } from 'src/shared/lib/document';
|
||||
@@ -54,10 +55,13 @@ const hasDocHash = computed(() => !!props.documentAggregate?.document?.doc_hash)
|
||||
|
||||
const loading = ref(false);
|
||||
const { isMobile } = useWindowSize();
|
||||
const regeneratedHash = ref();
|
||||
const regeneratedHash = ref<string | undefined>();
|
||||
const hashComputing = ref(false);
|
||||
const onRegenerate = ref(false);
|
||||
const regenerated = ref();
|
||||
|
||||
let hashRequestId = 0;
|
||||
|
||||
const regenerate = async () => {
|
||||
try {
|
||||
onRegenerate.value = true;
|
||||
@@ -171,9 +175,18 @@ const shadowStyles = computed(
|
||||
);
|
||||
|
||||
const hashBuffer = async () => {
|
||||
const binary = doc.value?.binary;
|
||||
if (!binary) {
|
||||
regeneratedHash.value = undefined;
|
||||
hashComputing.value = hasDocHash.value;
|
||||
return;
|
||||
}
|
||||
|
||||
const requestId = ++hashRequestId;
|
||||
hashComputing.value = true;
|
||||
|
||||
try {
|
||||
// Декодирование из base64
|
||||
const binaryString = atob(doc.value?.binary ?? '');
|
||||
const binaryString = atob(binary);
|
||||
const len = binaryString.length;
|
||||
const data = new Uint8Array(len);
|
||||
|
||||
@@ -181,16 +194,31 @@ const hashBuffer = async () => {
|
||||
data[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
|
||||
// Вычисление хэша из декодированных бинарных данных
|
||||
regeneratedHash.value = (
|
||||
await useGlobalStore().hashMessage(data)
|
||||
).toUpperCase();
|
||||
console.log('Хэш успешно вычислен:', regeneratedHash.value);
|
||||
const hash = (await useGlobalStore().hashMessage(data)).toUpperCase();
|
||||
if (requestId !== hashRequestId) return;
|
||||
|
||||
regeneratedHash.value = hash;
|
||||
} catch (error) {
|
||||
if (requestId !== hashRequestId) return;
|
||||
regeneratedHash.value = undefined;
|
||||
console.error('Ошибка при вычислении хэша:', error);
|
||||
} finally {
|
||||
if (requestId === hashRequestId) {
|
||||
hashComputing.value = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => (hasDocHash.value ? doc.value?.binary : undefined),
|
||||
(binary, prevBinary) => {
|
||||
if (binary === prevBinary) return;
|
||||
regeneratedHash.value = undefined;
|
||||
if (hasDocHash.value) void hashBuffer();
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
// Получение ФИО/названия подписанта по сертификату
|
||||
const getSignerName = (signer_certificate: any) => {
|
||||
if (!signer_certificate) return 'Неизвестный подписант';
|
||||
@@ -219,10 +247,7 @@ const verifySignatures = () => {
|
||||
// }
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (hasDocHash.value) hashBuffer();
|
||||
verifySignatures();
|
||||
});
|
||||
verifySignatures();
|
||||
|
||||
async function download() {
|
||||
try {
|
||||
|
||||
@@ -14,6 +14,8 @@ export interface DocumentSignaturesProps {
|
||||
docHash: string;
|
||||
/** Контрольная сумма, пересчитанная на клиенте. Если задана и == docHash — отметка «верно». */
|
||||
regeneratedHash?: string;
|
||||
/** Идёт локальный пересчёт контрольной суммы — показываем загрузку, не «не совпадает». */
|
||||
hashLoading?: boolean;
|
||||
/** Список приложенных подписей */
|
||||
signatures?: DocumentSignatureEntry[];
|
||||
/** Идёт ли сейчас «сверка» — для loading-состояния кнопки */
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
q-icon(:name='hashIcon' size='14px')
|
||||
span Контрольная сумма
|
||||
.doc-sig__hash {{ docHash }}
|
||||
.doc-sig__hash-hint(v-if='regeneratedHash !== undefined && !hashMatches')
|
||||
.doc-sig__hash-hint(v-if='hashLoading')
|
||||
q-spinner(color='primary' size='14px')
|
||||
span Проверяем контрольную сумму…
|
||||
.doc-sig__hash-hint(v-else-if='regeneratedHash !== undefined && !hashMatches')
|
||||
q-icon(name='warning_amber' size='14px')
|
||||
span Локально пересчитанный хеш не совпадает
|
||||
|
||||
@@ -82,6 +85,7 @@ import type { DocumentSignaturesProps } from './DocumentSignatures.types';
|
||||
const props = withDefaults(defineProps<DocumentSignaturesProps>(), {
|
||||
signatures: () => [],
|
||||
verifying: false,
|
||||
hashLoading: false,
|
||||
hideDownload: false,
|
||||
hideVerify: false,
|
||||
});
|
||||
@@ -96,7 +100,7 @@ const hashMatches = computed((): boolean =>
|
||||
);
|
||||
|
||||
const hashState = computed((): 'pos' | 'neutral' | 'neg' => {
|
||||
if (props.regeneratedHash === undefined) return 'neutral';
|
||||
if (props.hashLoading || props.regeneratedHash === undefined) return 'neutral';
|
||||
return hashMatches.value ? 'pos' : 'neg';
|
||||
});
|
||||
|
||||
@@ -169,6 +173,9 @@ function toggle(idx: number): void {
|
||||
color: var(--p-neg);
|
||||
font-size: var(--p-fs-meta, 12px);
|
||||
}
|
||||
.doc-sig__hash-hint:has(.q-spinner) {
|
||||
color: var(--p-ink-2);
|
||||
}
|
||||
|
||||
/* ============ Список подписей ============ */
|
||||
.doc-sig__list {
|
||||
|
||||
Reference in New Issue
Block a user