Files
medods_n3health_extension/background.js
T
2026-03-17 20:41:44 +03:00

693 lines
22 KiB
JavaScript

// background.js
console.log('✅ Medods N3.Health service worker started');
let isProcessing = false;
// Таблица статусов
const statuses = {
201: {
name: "Создан",
description: "Документ создан через API, готов к обработке",
category: "processing"
},
202: {
name: "Отправлен на подписание",
description: "Документ отправлен получателю",
category: "processing"
},
203: {
name: "Просмотрел",
description: "Документ просмотрен получателем",
category: "processing"
},
204: {
name: "Подписал",
description: "Документ подписан получателем",
category: "completed"
},
205: {
name: "Отказался",
description: "Получатель отказался от подписания",
category: "error"
},
206: {
name: "Срок для подписания истек",
description: "Срок действия ссылки истек до момента проставления подписи или отказа",
category: "error"
},
207: {
name: "Ожидание действий",
description: "Ожидание действий от всех получателей",
category: "processing"
},
208: {
name: "Успешно. Подписан всеми — обработка",
description: "Все получатели подписали, документ обрабатывается",
category: "processing"
},
209: {
name: "Успешно. Подписан не всеми — обработка",
description: "Не все получатели подписали, документ обрабатывается",
category: "processing"
},
210: {
name: "Завершено. Подписано всеми",
description: "Все получатели подписали, документ сохранен",
category: "completed"
},
211: {
name: "Завершено. Подписано не всеми",
description: "Не все получатели подписали, документ сохранен",
category: "completed"
},
212: {
name: "Отменен для получателя",
description: "Подписание отменено для конкретного получателя",
category: "error"
},
213: {
name: "Завершено. Отменено для всех",
description: "Подписание отменено для всех получателей",
category: "completed"
},
214: {
name: "Успешно. Требуется подписание УКЭП",
description: "Требуется подписание УКЭП медицинского работника",
category: "processing"
},
498: {
name: "Завершено. Отклонено всеми",
description: "Все получатели отказались от подписания",
category: "error"
},
499: {
name: "Завершено. Истекло для всех",
description: "Срок ссылки истек для всех получателей",
category: "error"
},
500: {
name: "Ошибка обработки",
description: "Ошибка во время обработки документа",
category: "error"
},
501: {
name: "Ошибка доставки получателю",
description: "Произошла ошибка при доставке конкретному получателю",
category: "error"
}
};
function enrichStatuses(data) {
if (!Array.isArray(data)) return data;
data.forEach(singing => {
if (Array.isArray(singing.statuses)) {
singing.statuses.forEach(status => {
const statusInfo = statuses[status.status] || {
name: "Неизвестный статус",
description: `Статус ${status.status}`,
category: "error"
};
status.category = statusInfo.category;
status.description = statusInfo.description;
status.name = statusInfo.name;
});
}
});
return data;
}
async function sendDataToServer(data) {
try {
const settings = await chrome.storage.local.get(['serverIp', 'serverPort']);
if (!settings.serverIp || !settings.serverPort) {
throw new Error('Server IP or port not configured');
}
const url = `http://${settings.serverIp}:${settings.serverPort}/api/singing`;
console.log('🌐 Отправка данных на сервер:', url);
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data),
signal: AbortSignal.timeout(30000)
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP error: ${response.status} - ${errorText}`);
}
const result = await response.json();
return result;
} catch (error) {
console.info('❌ Ошибка отправки на сервер:', error);
throw error;
}
}
async function processAndSendDocuments(data, sender) {
if (isProcessing) {
throw new Error('Already processing documents');
}
isProcessing = true;
try {
const serverResponse = await sendDataToServer(data);
const isSuccess = serverResponse && serverResponse.status === 'SUCCESS';
return {
success: isSuccess,
message: serverResponse.message || 'Неизвестная ошибка',
sentCount: data.docs?.length || 0
};
} catch (error) {
console.info('❌ Ошибка обработки документов:', error);
return {
success: false,
message: error.message || 'Ошибка обработки документов',
error: error.toString()
};
} finally {
isProcessing = false;
}
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'processAndSendDocuments') {
setTimeout(async () => {
try {
const result = await processAndSendDocuments(message.data, sender);
sendResponse({
success: result.success,
message: result.message,
sentCount: result.sentCount,
});
} catch (error) {
sendResponse({
success: false,
message: error.message || 'Неизвестная ошибка',
error: error.toString()
});
}
}, 0);
return true;
}
if (message.action === 'bgLog') {
try {
console.log(`[EXT][${message.sender}]`, ...message.payload);
} catch (e) { }
}
if (message.action === 'preSingingCheck') {
setTimeout(async () => {
try {
const result = await preSingingCheck(message.data);
sendResponse(result);
} catch (error) {
sendResponse({
success: false,
message: error.message || 'Неизвестная ошибка',
error: error.toString()
});
}
}, 0);
return true;
}
if (message.action === 'getDocuments') {
setTimeout(async () => {
try {
const result = await getDocumentsFromServer(message.data);
sendResponse(result);
} catch (error) {
sendResponse({
success: false,
message: error.message || 'Ошибка получения документов',
error: error.toString()
});
}
}, 0);
return true;
}
if (message.action === 'getDocument') {
setTimeout(async () => {
try {
const result = await getDocumentFromServer(message.data);
sendResponse(result);
} catch (error) {
sendResponse({
success: false,
message: error.message || 'Ошибка получения документа'
});
}
}, 0);
return true;
}
if (message.action === 'revokeDocuments') {
setTimeout(async () => {
try {
const result = await revokeDocumentsOnServer(message.data);
sendResponse(result);
} catch (error) {
sendResponse({
success: false,
message: error.message || 'Ошибка отзыва документов'
});
}
}, 0);
return true;
}
if (message.action === 'resendDocuments') {
setTimeout(async () => {
try {
const result = await resendDocumentsOnServer(message.data);
sendResponse(result);
} catch (error) {
sendResponse({
success: false,
message: error.message || 'Ошибка повторной отправки документов'
});
}
}, 0);
return true;
}
// Новый обработчик для получения статусов из popup
if (message.action === 'getStatuses') {
setTimeout(async () => {
try {
const result = await getStatusesFromServer(message.data);
sendResponse(result);
} catch (error) {
sendResponse({
success: false,
message: error.message || 'Ошибка получения статусов',
error: error.toString()
});
}
}, 0);
return true;
}
// Обработчик расширенного поиска
if (message.action === 'advancedSearch') {
setTimeout(async () => {
try {
const result = await advancedSearch(message.data);
sendResponse(result);
} catch (error) {
sendResponse({
success: false,
message: error.message || 'Ошибка расширенного поиска',
error: error.toString()
});
}
}, 0);
return true;
}
if (message.action === 'searchRecipients') {
setTimeout(async () => {
try {
const result = await searchRecipients(message.data);
sendResponse(result);
} catch (error) {
sendResponse({
success: false,
message: error.message || 'Ошибка поиска получателей',
error: error.toString(),
data: []
});
}
}, 0);
return true;
}
});
// Функция расширенного поиска
async function advancedSearch(data) {
if (isProcessing) {
throw new Error('Already processing documents');
}
isProcessing = true;
try {
const settings = await chrome.storage.local.get(['serverIp', 'serverPort']);
if (!settings.serverIp || !settings.serverPort) {
throw new Error('Server IP or port not configured');
}
const url = `http://${settings.serverIp}:${settings.serverPort}/api/advanced-search`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data),
signal: AbortSignal.timeout(30000)
});
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
let result = await response.json();
result = result.data || [];
// Обогащаем статусы если есть данные
if (Array.isArray(result)) {
result = enrichStatuses(result);
}
return {
success: true,
data: result || []
};
} catch (error) {
console.info('Advanced search error:', error);
return {
success: false,
message: error.message || 'Ошибка расширенного поиска',
error: error.toString()
};
} finally {
isProcessing = false;
}
}
async function preSingingCheck(data) {
try {
const settings = await chrome.storage.local.get(['serverIp', 'serverPort']);
if (!settings.serverIp || !settings.serverPort) {
throw new Error('Server IP or port not configured');
}
const url = `http://${settings.serverIp}:${settings.serverPort}/api/pre_singing`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data),
signal: AbortSignal.timeout(15000)
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP error: ${response.status} - ${errorText}`);
}
const result = await response.json();
return {
success: true,
data: result
};
} catch (error) {
return {
success: false,
message: error.message || 'Ошибка предварительной проверки',
error: error.toString()
};
}
}
async function getDocumentsFromServer(data) {
try {
const settings = await chrome.storage.local.get(['serverIp', 'serverPort']);
if (!settings.serverIp || !settings.serverPort) {
throw new Error('Server IP or port not configured');
}
const url = `http://${settings.serverIp}:${settings.serverPort}/api/documents`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
idPatientMis: data.idPatientMis
}),
signal: AbortSignal.timeout(30000)
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP error: ${response.status} - ${errorText}`);
}
const result = await response.json();
if (result.status === 'SUCCESS' && Array.isArray(result.data.singings)) {
result.data.singings = enrichStatuses(result.data.singings);
}
return {
success: result.status === 'SUCCESS',
data: result.data || [],
message: result.message || 'Документы получены успешно'
};
} catch (error) {
return {
success: false,
message: error.message || 'Ошибка получения документов',
error: error.toString()
};
}
}
// Новая функция для получения статусов
async function getStatusesFromServer(data) {
try {
const settings = await chrome.storage.local.get(['serverIp', 'serverPort']);
if (!settings.serverIp || !settings.serverPort) {
throw new Error('Server IP or port not configured');
}
const url = `http://${settings.serverIp}:${settings.serverPort}/api/statuses`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data || {}),
signal: AbortSignal.timeout(30000)
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP error: ${response.status} - ${errorText}`);
}
let result = await response.json();
if (Array.isArray(result)) {
result = enrichStatuses(result);
}
return {
success: true,
data: result || []
};
} catch (error) {
return {
success: false,
message: error.message || 'Ошибка получения статусов',
error: error.toString()
};
}
}
chrome.runtime.onInstalled.addListener((details) => {
if (details.reason === 'install') {
chrome.storage.local.set({
esiaAuth: false,
trackingIds: [],
serverIp: '',
serverPort: 8000,
processingStatus: 'idle'
});
}
});
async function getDocumentFromServer(data) {
try {
const settings = await chrome.storage.local.get(['serverIp', 'serverPort']);
if (!settings.serverIp || !settings.serverPort) {
throw new Error('Server IP or port not configured');
}
const url = `http://${settings.serverIp}:${settings.serverPort}/api/document`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data),
signal: AbortSignal.timeout(30000)
});
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const result = await response.json();
return {
success: true,
data: result.data
};
} catch (error) {
return {
success: false,
message: error.message
};
}
}
async function revokeDocumentsOnServer(data) {
try {
const settings = await chrome.storage.local.get(['serverIp', 'serverPort']);
if (!settings.serverIp || !settings.serverPort) {
throw new Error('Server IP or port not configured');
}
const url = `http://${settings.serverIp}:${settings.serverPort}/api/revoke`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data),
signal: AbortSignal.timeout(30000)
});
const result = await response.json();
return {
success: result.status === 'SUCCESS',
message: result.message
};
} catch (error) {
return {
success: false,
message: error.message
};
}
}
async function resendDocumentsOnServer(data) {
try {
const settings = await chrome.storage.local.get(['serverIp', 'serverPort']);
if (!settings.serverIp || !settings.serverPort) {
throw new Error('Server IP or port not configured');
}
const url = `http://${settings.serverIp}:${settings.serverPort}/api/resend`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data),
signal: AbortSignal.timeout(30000)
});
const result = await response.json();
return {
success: result.status === 'SUCCESS',
message: result.message
};
} catch (error) {
return {
success: false,
message: error.message
};
}
}
async function searchRecipients(data) {
try {
const settings = await chrome.storage.local.get(['serverIp', 'serverPort']);
if (!settings.serverIp || !settings.serverPort) {
throw new Error('Server IP or port not configured');
}
const url = `http://${settings.serverIp}:${settings.serverPort}/api/search-recipients`;
console.log('[background] Поиск получателей:', url, data);
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data),
signal: AbortSignal.timeout(15000) // 15 секунд таймаут
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP error: ${response.status} - ${errorText}`);
}
const result = await response.json();
let recipients = result;
if (result.data && Array.isArray(result.data)) {
recipients = result.data;
} else if (!Array.isArray(result)) {
recipients = [];
}
return {
success: true,
data: recipients
};
} catch (error) {
console.info('[background] Ошибка поиска получателей:', error);
return {
success: false,
message: error.message || 'Ошибка поиска получателей',
error: error.toString(),
data: []
};
}
}
console.log('✅ Background script loaded');