693 lines
22 KiB
JavaScript
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'); |