import type { FormulaRule, FormulaValidation } from '#/api/x/eln/formulas';
|
|
import { onBeforeUnmount, ref } from 'vue';
|
|
import { validateFormula } from '#/api/x/eln/formulas';
|
|
const VALIDATION_DEBOUNCE_MS = 400;
|
|
export function useFormulaValidation() {
|
const error = ref('');
|
const result = ref<FormulaValidation>();
|
const loading = ref(false);
|
let requestSequence = 0;
|
let debounceTimer: ReturnType<typeof setTimeout> | undefined;
|
let activeController: AbortController | undefined;
|
let lastRule: FormulaRule | undefined;
|
|
function clearScheduledValidation() {
|
if (!debounceTimer) return;
|
clearTimeout(debounceTimer);
|
debounceTimer = undefined;
|
}
|
|
function schedule(rule: FormulaRule) {
|
clearScheduledValidation();
|
invalidateActiveValidation();
|
debounceTimer = setTimeout(() => {
|
debounceTimer = undefined;
|
void validateNow(rule);
|
}, VALIDATION_DEBOUNCE_MS);
|
}
|
|
function invalidateActiveValidation() {
|
requestSequence++;
|
activeController?.abort();
|
activeController = undefined;
|
error.value = '';
|
loading.value = false;
|
result.value = undefined;
|
}
|
|
async function validateNow(rule: FormulaRule): Promise<FormulaValidation | undefined> {
|
clearScheduledValidation();
|
lastRule = rule;
|
activeController?.abort();
|
const controller = new AbortController();
|
activeController = controller;
|
const sequence = ++requestSequence;
|
loading.value = true;
|
try {
|
const response = await validateFormula(rule, controller.signal);
|
if (sequence !== requestSequence) return undefined;
|
result.value = response.data;
|
error.value = '';
|
return response.data;
|
} catch (caughtError) {
|
if (sequence !== requestSequence || controller.signal.aborted) return undefined;
|
result.value = { diagnostics: [], latex: null };
|
const message = caughtError instanceof Error ? caughtError.message : '公式校验请求失败';
|
error.value = message || '公式校验请求失败';
|
return undefined;
|
} finally {
|
if (sequence === requestSequence) loading.value = false;
|
}
|
}
|
|
function cancel() {
|
clearScheduledValidation();
|
invalidateActiveValidation();
|
}
|
|
async function retry() {
|
if (!lastRule) return undefined;
|
return validateNow(lastRule);
|
}
|
|
onBeforeUnmount(cancel);
|
|
return { cancel, error, loading, result, retry, schedule, validateNow };
|
}
|