release 1.1
This commit is contained in:
+408
-200
@@ -4,6 +4,7 @@
|
||||
// Глобальная переменная для хранения текущего уведомления
|
||||
let currentMessageEl = null;
|
||||
let messageTimeout = null;
|
||||
let deliveryTypeSettings = {};
|
||||
|
||||
// Функция для отображения сообщений
|
||||
function showMessage(message, type = 'success', duration = 3000) {
|
||||
@@ -136,45 +137,81 @@
|
||||
modalWrapper.className = 'el-dialog__wrapper';
|
||||
modalWrapper.style.cssText = 'z-index: 2001; position: fixed; top: 0; right: 0; bottom: 0; left: 0; overflow: auto;';
|
||||
|
||||
const backdrop = document.createElement('div');
|
||||
backdrop.className = 'v-modal';
|
||||
backdrop.style.cssText = 'z-index: 2001;';
|
||||
backdrop.tabIndex = 0;
|
||||
// Разделяем статусы на общие и по получателям
|
||||
const commonStatuses = singing.statuses.filter(s => s.idPatientMis === null);
|
||||
const recipientStatuses = singing.statuses.filter(s => s.idPatientMis !== null);
|
||||
|
||||
const sortedStatuses = [...singing.statuses].sort((a, b) => a.id - b.id);
|
||||
// Группируем статусы по получателям
|
||||
const statusesByRecipient = {};
|
||||
recipientStatuses.forEach(status => {
|
||||
if (status.patient) {
|
||||
const patientName = status.patient.name || 'Неизвестный получатель';
|
||||
if (!statusesByRecipient[patientName]) {
|
||||
statusesByRecipient[patientName] = [];
|
||||
}
|
||||
statusesByRecipient[patientName].push(status);
|
||||
}
|
||||
});
|
||||
|
||||
const statusesHtml = sortedStatuses.map(status => `
|
||||
<div class="status-history-item" style="padding: 12px; border-bottom: 1px solid #ebeef5; display: flex; align-items: center; gap: 12px;">
|
||||
<i class="el-icon ${getStatusIcon(status.category)}" style="font-size: 16px; color: ${status.category === 'completed' ? '#67C23A' :
|
||||
// Сортируем получателей по имени
|
||||
const sortedRecipients = Object.keys(statusesByRecipient).sort();
|
||||
|
||||
// Функция для генерации HTML статуса
|
||||
const getStatusHtml = (status) => `
|
||||
<div class="status-history-item" style="padding: 12px; border-bottom: 1px solid #ebeef5; display: flex; align-items: center; gap: 12px;">
|
||||
<i class="el-icon ${getStatusIcon(status.category)}" style="font-size: 16px; color: ${status.category === 'completed' ? '#67C23A' :
|
||||
status.category === 'processing' ? '#409EFF' :
|
||||
status.category === 'error' ? '#F56C6C' : '#909399'
|
||||
}; width: 20px;"></i>
|
||||
<div style="flex: 1;">
|
||||
<div style="font-weight: 500; color: #303133;">${status.description}</div>
|
||||
<div style="font-size: 12px; color: #909399; margin-top: 4px;">${formatDate(status.created_at)}</div>
|
||||
</div>
|
||||
<div style="flex: 1;">
|
||||
<div style="font-weight: 500; color: #303133;">${status.description}</div>
|
||||
<div style="font-size: 12px; color: #909399; margin-top: 4px;">${formatDate(status.created_at)}</div>
|
||||
</div>
|
||||
`).join('');
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Генерируем HTML для общих статусов
|
||||
const commonStatusesHtml = commonStatuses
|
||||
.sort((a, b) => a.id - b.id)
|
||||
.map(getStatusHtml)
|
||||
.join('');
|
||||
|
||||
// Генерируем HTML для статусов получателей
|
||||
const recipientStatusesHtml = sortedRecipients.map(recipientName => {
|
||||
const recipientStatuses = statusesByRecipient[recipientName]
|
||||
.sort((a, b) => a.id - b.id)
|
||||
.map(getStatusHtml)
|
||||
.join('');
|
||||
|
||||
return `
|
||||
<div style="background: #F5F7FA; padding: 8px 12px; font-weight: 500; color: #303133; border-bottom: 1px solid #DCDFE6;">
|
||||
<i class="el-icon el-icon-user" style="margin-right: 6px; color: #409EFF;"></i>
|
||||
${recipientName}
|
||||
</div>
|
||||
${recipientStatuses}
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
modalWrapper.innerHTML = `
|
||||
<div class="el-dialog" style="width: 500px; margin-top: 15vh;">
|
||||
<div class="el-dialog__header">
|
||||
<span class="el-dialog__title">История статусов</span>
|
||||
<button type="button" class="el-dialog__headerbtn" aria-label="Close">
|
||||
<i class="el-dialog__close el-icon el-icon-close"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="el-dialog__body" style="max-height: 400px; overflow-y: auto; padding: 0;">
|
||||
${statusesHtml}
|
||||
</div>
|
||||
<div class="el-dialog__footer" style="margin-top: 12px; width: 100%; text-align: right;">
|
||||
<button type="button" class="el-button m-button el-button--small is-plain button-with-icon close-btn">
|
||||
<i class="m-icon fa-times button-icon fad" style="font-size: 14px; margin-right: 6px;"></i>
|
||||
<span>Закрыть</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="el-dialog" style="width: 500px; margin-top: 15vh;">
|
||||
<div class="el-dialog__header">
|
||||
<span class="el-dialog__title">История статусов</span>
|
||||
<button type="button" class="el-dialog__headerbtn" aria-label="Close">
|
||||
<i class="el-dialog__close el-icon el-icon-close"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
<div class="el-dialog__body" style="max-height: 400px; overflow-y: auto; padding: 0;">
|
||||
${commonStatusesHtml}
|
||||
${recipientStatusesHtml}
|
||||
</div>
|
||||
<div class="el-dialog__footer" style="margin-top: 12px; width: 100%; text-align: right;">
|
||||
<button type="button" class="el-button m-button el-button--small is-plain button-with-icon close-btn">
|
||||
<i class="m-icon fa-times button-icon fad" style="font-size: 14px; margin-right: 6px;"></i>
|
||||
<span>Закрыть</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(modalWrapper);
|
||||
|
||||
@@ -196,80 +233,13 @@
|
||||
document.addEventListener('keydown', escHandler);
|
||||
}
|
||||
|
||||
// Функция создания модального окна подтверждения отзыва
|
||||
function createRevokeConfirmModal(singing) {
|
||||
return new Promise((resolve) => {
|
||||
const modalWrapper = document.createElement('div');
|
||||
modalWrapper.className = 'el-dialog__wrapper';
|
||||
modalWrapper.style.cssText = 'z-index: 2001; position: fixed; top: 0; right: 0; bottom: 0; left: 0; overflow: auto;';
|
||||
|
||||
const backdrop = document.createElement('div');
|
||||
backdrop.className = 'v-modal';
|
||||
backdrop.style.cssText = 'z-index: 2001;';
|
||||
backdrop.tabIndex = 0;
|
||||
|
||||
modalWrapper.innerHTML = `
|
||||
<div class="el-dialog" style="width: 450px; margin-top: 25vh;">
|
||||
<div class="el-dialog__header">
|
||||
<span class="el-dialog__title">Подтверждение отзыва</span>
|
||||
<button type="button" class="el-dialog__headerbtn" aria-label="Close">
|
||||
<i class="el-dialog__close el-icon el-icon-close"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="el-dialog__body" style="padding: 20px;">
|
||||
<div style="display: flex; align-items: flex-start; gap: 12px;">
|
||||
<i class="el-icon el-icon-warning" style="font-size: 24px; color: #E6A23C;"></i>
|
||||
<div>
|
||||
<p style="margin: 0 0 10px 0; color: #606266;">Вы действительно хотите отозвать документы из подписания?</p>
|
||||
<div style="background: #f8f8f8; padding: 10px; border-radius: 4px; font-size: 13px; color: #E6A23C; border-left: 3px solid #E6A23C;">
|
||||
<i class="el-icon el-icon-document" style="margin-right: 6px;"></i>
|
||||
<strong>Документы:</strong> ${singing.documents.map(d => `№${d.number} ${d.title}`).join(', ')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="el-dialog__footer" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<button type="button" class="el-button m-button el-button--small is-plain button-with-icon cancel-btn"
|
||||
style="display: flex; align-items: center;">
|
||||
<i class="m-icon fa-times button-icon fad" style="font-size: 14px; margin-right: 6px;"></i>
|
||||
<span>Отмена</span>
|
||||
</button>
|
||||
<button type="button" class="el-button m-button el-button--small is-plain button-with-icon confirm-btn" style="color: #F56C6C; border-color: #F56C6C; display: flex; align-items: center;">
|
||||
<i class="m-icon fa-ban button-icon fad" style="font-size: 14px; margin-right: 6px;"></i>
|
||||
<span>Отозвать</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(modalWrapper);
|
||||
|
||||
const closeModal = () => {
|
||||
modalWrapper.remove();
|
||||
resolve(false);
|
||||
};
|
||||
|
||||
modalWrapper.querySelector('.el-dialog__headerbtn').addEventListener('click', closeModal);
|
||||
modalWrapper.querySelector('.cancel-btn').addEventListener('click', closeModal);
|
||||
modalWrapper.querySelector('.confirm-btn').addEventListener('click', () => {
|
||||
modalWrapper.remove();
|
||||
resolve(true);
|
||||
});
|
||||
modalWrapper.addEventListener('click', (e) => {
|
||||
if (e.target === modalWrapper) closeModal();
|
||||
});
|
||||
|
||||
// Закрытие по ESC
|
||||
const escHandler = (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
closeModal();
|
||||
document.removeEventListener('keydown', escHandler);
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', escHandler);
|
||||
});
|
||||
// Функция для получения имени получателя по ID
|
||||
function getRecipientNameById(singing, idPatientMis) {
|
||||
const status = singing.statuses.find(s => s.idPatientMis === idPatientMis && s.patient);
|
||||
return status?.patient?.name || 'Неизвестный получатель';
|
||||
}
|
||||
|
||||
|
||||
// Функция отображения PDF
|
||||
async function viewDocument(documentPath, title) {
|
||||
try {
|
||||
@@ -364,6 +334,53 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Функция повторной отправки документов
|
||||
async function resendDocuments(singing, modalToClose) {
|
||||
try {
|
||||
// Сразу закрываем окно со списком документов
|
||||
if (modalToClose && modalToClose.parentNode) {
|
||||
modalToClose.remove();
|
||||
}
|
||||
|
||||
// Показываем подтверждение с выбором получателей и способа отправки
|
||||
const result = await createResendConfirmModal(singing);
|
||||
if (!result.confirmed) return;
|
||||
|
||||
// Если получателей нет или не выбраны, показываем ошибку
|
||||
if (result.recipients.length === 0) {
|
||||
showMessage('Не выбраны получатели для повторной отправки', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Если не выбран способ отправки, показываем ошибку
|
||||
if (!result.deliveryType) {
|
||||
showMessage('Не выбран способ отправки', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
showMessage('Повторная отправка документов...', 'info');
|
||||
|
||||
// Отправляем запрос на повторную отправку с указанием получателей и способа отправки
|
||||
const response = await sendMessageToContent('resendDocuments', {
|
||||
trackingId: singing.trackingId,
|
||||
idPatientMis: result.recipients,
|
||||
deliveryType: result.deliveryType
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
showMessage('Документы успешно отправлены повторно', 'success');
|
||||
console.log('Документы успешно отправлены повторно');
|
||||
// Обновляем список документов
|
||||
await prepareDocuments();
|
||||
} else {
|
||||
showMessage('Ошибка повторной отправки документов: ' + (response.message || 'Неизвестная ошибка'), 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка повторной отправки документов:', error);
|
||||
showMessage('Ошибка повторной отправки документов', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Функция создания модального окна подтверждения повторной отправки
|
||||
function createResendConfirmModal(singing) {
|
||||
return new Promise((resolve) => {
|
||||
@@ -371,44 +388,259 @@
|
||||
modalWrapper.className = 'el-dialog__wrapper';
|
||||
modalWrapper.style.cssText = 'z-index: 2001; position: fixed; top: 0; right: 0; bottom: 0; left: 0; overflow: auto;';
|
||||
|
||||
const backdrop = document.createElement('div');
|
||||
backdrop.className = 'v-modal';
|
||||
backdrop.style.cssText = 'z-index: 2001;';
|
||||
backdrop.tabIndex = 0;
|
||||
// Собираем всех получателей (recipients + idPatientMis)
|
||||
const allRecipients = [];
|
||||
|
||||
// Добавляем idPatientMis если есть
|
||||
if (singing.idPatientMis) {
|
||||
allRecipients.push({
|
||||
id: singing.idPatientMis,
|
||||
name: getRecipientNameById(singing, singing.idPatientMis)
|
||||
});
|
||||
}
|
||||
|
||||
// Добавляем recipients
|
||||
if (singing.recipients && singing.recipients.length > 0) {
|
||||
singing.recipients.forEach(id => {
|
||||
// Проверяем, не добавили ли уже этого получателя
|
||||
if (!allRecipients.some(r => r.id === id)) {
|
||||
allRecipients.push({
|
||||
id: id,
|
||||
name: getRecipientNameById(singing, id)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const hasRecipients = allRecipients.length > 0;
|
||||
|
||||
// Маппинг типов доставки на отображаемые названия
|
||||
const deliveryTypeLabels = {
|
||||
'sms': 'СМС-сообщение',
|
||||
'max': 'МАХ-сообщение',
|
||||
'mila': 'Mila-сообщение',
|
||||
'goskey': 'Goskey-сообщение'
|
||||
};
|
||||
|
||||
// Доступные типы доставки
|
||||
const deliveryTypes = Object.keys(deliveryTypeSettings).filter(key => deliveryTypeSettings[key] === true);
|
||||
|
||||
// Создаем HTML для списка получателей с чекбоксами
|
||||
const recipientsHtml = hasRecipients ? `
|
||||
<div style="margin-top: 16px;">
|
||||
<div style="font-weight: 500; color: #303133; margin-bottom: 8px;">Получатели:</div>
|
||||
<div style="max-height: 200px; overflow-y: auto; border: 1px solid #DCDFE6; border-radius: 4px; padding: 8px;">
|
||||
${allRecipients.map(recipient => `
|
||||
<div style="display: flex; align-items: center; padding: 6px 8px; border-bottom: 1px solid #EBEEF5;">
|
||||
<label style="display: flex; align-items: center; width: 100%; cursor: pointer;">
|
||||
<span class="el-checkbox" style="margin-right: 10px;">
|
||||
<input type="checkbox" class="recipient-checkbox" value="${recipient.id}" style="width: 16px; height: 16px; cursor: pointer;">
|
||||
</span>
|
||||
<span style="color: #606266;">${recipient.name}</span>
|
||||
</label>
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
` : '';
|
||||
|
||||
modalWrapper.innerHTML = `
|
||||
<div class="el-dialog" style="width: 450px; margin-top: 25vh;">
|
||||
<div class="el-dialog__header">
|
||||
<span class="el-dialog__title">Подтверждение повторной отправки</span>
|
||||
<button type="button" class="el-dialog__headerbtn" aria-label="Close">
|
||||
<i class="el-dialog__close el-icon el-icon-close"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="el-dialog__body" style="padding: 20px;">
|
||||
<div style="display: flex; align-items: flex-start; gap: 12px;">
|
||||
<i class="el-icon el-icon-warning" style="font-size: 24px; color: #E6A23C;"></i>
|
||||
<div>
|
||||
<p style="margin: 0 0 10px 0; color: #606266;">Вы действительно хотите повторно отправить документы на подписание?</p>
|
||||
<div style="background: #f8f8f8; padding: 10px; border-radius: 4px; font-size: 13px; color: #E6A23C; border-left: 3px solid #E6A23C;">
|
||||
<i class="el-icon el-icon-document" style="margin-right: 6px;"></i>
|
||||
<strong>Документы:</strong> ${singing.documents.map(d => `№${d.number} ${d.title}`).join(', ')}
|
||||
<div class="el-dialog" style="width: 500px; margin-top: 15vh;">
|
||||
<div class="el-dialog__header">
|
||||
<span class="el-dialog__title">Подтверждение повторной отправки</span>
|
||||
<button type="button" class="el-dialog__headerbtn" aria-label="Close">
|
||||
<i class="el-dialog__close el-icon el-icon-close"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="el-dialog__body" style="padding: 20px; max-height: 60vh; overflow-y: auto;">
|
||||
<div style="display: flex; align-items: flex-start; gap: 12px;">
|
||||
<i class="el-icon el-icon-warning" style="font-size: 24px; color: #E6A23C;"></i>
|
||||
<div style="flex: 1;">
|
||||
<p style="margin: 0 0 10px 0; color: #606266;">Вы действительно хотите повторно отправить документы на подписание?</p>
|
||||
<div style="background: #f8f8f8; padding: 10px; border-radius: 4px; font-size: 13px; color: #E6A23C; border-left: 3px solid #E6A23C; margin-bottom: 10px;">
|
||||
<i class="el-icon el-icon-document" style="margin-right: 6px;"></i>
|
||||
<strong>Документы:</strong> ${singing.documents.map(d => `№${d.number} ${d.title}`).join(', ')}
|
||||
</div>
|
||||
${recipientsHtml}
|
||||
|
||||
<!-- Выпадающий список способа отправки -->
|
||||
<div style="margin-top: 16px;">
|
||||
<div style="font-weight: 500; color: #303133; margin-bottom: 8px;">Способ отправки:</div>
|
||||
<div class="delivery-select-wrapper" style="position: relative; width: 100%;">
|
||||
<select class="delivery-select" style="
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
padding: 0 24px 0 10px;
|
||||
border: 1px solid #DCDFE6;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
font-family: inherit;
|
||||
">
|
||||
<option value="" selected disabled>Выберите способ отправки</option>
|
||||
${deliveryTypes.map(type => `
|
||||
<option value="${type}">
|
||||
${deliveryTypeLabels[type]}
|
||||
</option>
|
||||
`).join('')}
|
||||
</select>
|
||||
<span style="
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
pointer-events: none;
|
||||
color: #C0C4CC;
|
||||
font-size: 12px;
|
||||
">▼</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${!hasRecipients ? '<p style="color: #909399; margin: 10px 0 0;">Нет получателей для повторной отправки</p>' : ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="el-dialog__footer" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<button type="button" class="el-button m-button el-button--small is-plain button-with-icon cancel-btn"
|
||||
style="display: flex; align-items: center;">
|
||||
<i class="m-icon fa-times button-icon fad" style="font-size: 14px; margin-right: 6px;"></i>
|
||||
<span>Отмена</span>
|
||||
</button>
|
||||
<button type="button" class="el-button m-button el-button--small is-plain button-with-icon confirm-btn"
|
||||
style="color: #67C23A; border-color: #67C23A; display: flex; align-items: center; ${!hasRecipients ? 'opacity: 0.5; pointer-events: none;' : ''}">
|
||||
<i class="m-icon fa-redo-alt button-icon fad" style="font-size: 14px; margin-right: 6px;"></i>
|
||||
<span>Отправить повторно</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(modalWrapper);
|
||||
|
||||
// Получаем элементы
|
||||
const checkboxes = modalWrapper.querySelectorAll('.recipient-checkbox');
|
||||
const confirmBtn = modalWrapper.querySelector('.confirm-btn');
|
||||
const deliverySelect = modalWrapper.querySelector('.delivery-select');
|
||||
let selectedDeliveryType = deliverySelect.value || null;
|
||||
|
||||
// Функция обновления состояния кнопки
|
||||
function updateConfirmButton() {
|
||||
const anyChecked = Array.from(checkboxes).some(cb => cb.checked);
|
||||
const hasDeliveryType = selectedDeliveryType && selectedDeliveryType !== '';
|
||||
|
||||
if (anyChecked && hasDeliveryType) {
|
||||
confirmBtn.style.opacity = '1';
|
||||
confirmBtn.style.pointerEvents = 'auto';
|
||||
} else {
|
||||
confirmBtn.style.opacity = '0.5';
|
||||
confirmBtn.style.pointerEvents = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Обработчик изменения выбора в select
|
||||
deliverySelect.addEventListener('change', (e) => {
|
||||
selectedDeliveryType = e.target.value;
|
||||
updateConfirmButton();
|
||||
});
|
||||
|
||||
// Обработчики для чекбоксов
|
||||
if (checkboxes.length > 0) {
|
||||
checkboxes.forEach(cb => {
|
||||
cb.addEventListener('change', updateConfirmButton);
|
||||
});
|
||||
}
|
||||
|
||||
// Функции закрытия
|
||||
const closeModal = () => {
|
||||
modalWrapper.remove();
|
||||
resolve({ confirmed: false, recipients: [], deliveryType: null });
|
||||
};
|
||||
|
||||
// Обработчик кнопки подтверждения
|
||||
confirmBtn.addEventListener('click', () => {
|
||||
const selectedRecipients = Array.from(checkboxes)
|
||||
.filter(cb => cb.checked)
|
||||
.map(cb => cb.value);
|
||||
|
||||
if (selectedRecipients.length === 0 || !selectedDeliveryType) {
|
||||
return;
|
||||
}
|
||||
|
||||
modalWrapper.remove();
|
||||
resolve({
|
||||
confirmed: true,
|
||||
recipients: selectedRecipients,
|
||||
deliveryType: selectedDeliveryType
|
||||
});
|
||||
});
|
||||
|
||||
// Обработчики закрытия
|
||||
modalWrapper.querySelector('.el-dialog__headerbtn').addEventListener('click', closeModal);
|
||||
modalWrapper.querySelector('.cancel-btn').addEventListener('click', closeModal);
|
||||
modalWrapper.addEventListener('click', (e) => {
|
||||
if (e.target === modalWrapper) closeModal();
|
||||
});
|
||||
|
||||
// Закрытие по ESC
|
||||
const escHandler = (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
closeModal();
|
||||
document.removeEventListener('keydown', escHandler);
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', escHandler);
|
||||
|
||||
// Инициализация состояния кнопки
|
||||
updateConfirmButton();
|
||||
});
|
||||
}
|
||||
|
||||
// Функция создания модального окна подтверждения отзыва
|
||||
function createRevokeConfirmModal(singing) {
|
||||
return new Promise((resolve) => {
|
||||
const modalWrapper = document.createElement('div');
|
||||
modalWrapper.className = 'el-dialog__wrapper';
|
||||
modalWrapper.style.cssText = 'z-index: 2001; position: fixed; top: 0; right: 0; bottom: 0; left: 0; overflow: auto;';
|
||||
|
||||
modalWrapper.innerHTML = `
|
||||
<div class="el-dialog" style="width: 450px; margin-top: 25vh;">
|
||||
<div class="el-dialog__header">
|
||||
<span class="el-dialog__title">Подтверждение отзыва</span>
|
||||
<button type="button" class="el-dialog__headerbtn" aria-label="Close">
|
||||
<i class="el-dialog__close el-icon el-icon-close"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="el-dialog__body" style="padding: 20px;">
|
||||
<div style="display: flex; align-items: flex-start; gap: 12px;">
|
||||
<i class="el-icon el-icon-warning" style="font-size: 24px; color: #E6A23C;"></i>
|
||||
<div>
|
||||
<p style="margin: 0 0 10px 0; color: #606266;">Вы действительно хотите отозвать документы из подписания?</p>
|
||||
<div style="background: #f8f8f8; padding: 10px; border-radius: 4px; font-size: 13px; color: #E6A23C; border-left: 3px solid #E6A23C;">
|
||||
<i class="el-icon el-icon-document" style="margin-right: 6px;"></i>
|
||||
<strong>Документы:</strong> ${singing.documents.map(d => `№${d.number} ${d.title}`).join(', ')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="el-dialog__footer" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<button type="button" class="el-button m-button el-button--small is-plain button-with-icon cancel-btn"
|
||||
style="display: flex; align-items: center;">
|
||||
<i class="m-icon fa-times button-icon fad" style="font-size: 14px; margin-right: 6px;"></i>
|
||||
<span>Отмена</span>
|
||||
</button>
|
||||
<button type="button" class="el-button m-button el-button--small is-plain button-with-icon confirm-btn" style="color: #67C23A; border-color: #67C23A; display: flex; align-items: center;">
|
||||
<i class="m-icon fa-redo-alt button-icon fad" style="font-size: 14px; margin-right: 6px;"></i>
|
||||
<span>Отправить повторно</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
<div class="el-dialog__footer" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<button type="button" class="el-button m-button el-button--small is-plain button-with-icon cancel-btn"
|
||||
style="display: flex; align-items: center;">
|
||||
<i class="m-icon fa-times button-icon fad" style="font-size: 14px; margin-right: 6px;"></i>
|
||||
<span>Отмена</span>
|
||||
</button>
|
||||
<button type="button" class="el-button m-button el-button--small is-plain button-with-icon confirm-btn" style="color: #F56C6C; border-color: #F56C6C; display: flex; align-items: center;">
|
||||
<i class="m-icon fa-ban button-icon fad" style="font-size: 14px; margin-right: 6px;"></i>
|
||||
<span>Отозвать</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(modalWrapper);
|
||||
|
||||
@@ -438,43 +670,9 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Функция повторной отправки документов
|
||||
async function resendDocuments(singing, modalToClose) {
|
||||
try {
|
||||
// Сразу закрываем окно со списком документов
|
||||
if (modalToClose && modalToClose.parentNode) {
|
||||
modalToClose.remove();
|
||||
}
|
||||
|
||||
// Показываем подтверждение
|
||||
const confirmed = await createResendConfirmModal(singing);
|
||||
if (!confirmed) return;
|
||||
|
||||
showMessage('Повторная отправка документов...', 'info');
|
||||
|
||||
// Отправляем запрос на повторную отправку
|
||||
const response = await sendMessageToContent('resendDocuments', {
|
||||
id: singing.id,
|
||||
trackingId: singing.trackingId,
|
||||
idPatientMis: singing.idPatientMis
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
showMessage('Документы успешно отправлены повторно', 'success');
|
||||
console.log('Документы успешно отправлены повторно');
|
||||
// Обновляем список документов
|
||||
await prepareDocuments();
|
||||
} else {
|
||||
showMessage('Ошибка повторной отправки документов: ' + (response.message || 'Неизвестная ошибка'), 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка повторной отправки документов:', error);
|
||||
showMessage('Ошибка повторной отправки документов', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Функция создания таблицы документов
|
||||
function createDocumentsTable(data) {
|
||||
|
||||
// Создаем модальное окно
|
||||
const modalWrapper = document.createElement('div');
|
||||
modalWrapper.className = 'el-dialog__wrapper';
|
||||
@@ -509,9 +707,10 @@
|
||||
} else {
|
||||
const tableRows = data.map((singing, index) => {
|
||||
// Определяем последний статус
|
||||
const lastStatus = singing.statuses.reduce((max, status) =>
|
||||
const commonStatuses = singing.statuses.filter(s => s.idPatientMis === null);
|
||||
const lastStatus = commonStatuses.reduce((max, status) =>
|
||||
status.id > max.id ? status : max
|
||||
, singing.statuses[0]);
|
||||
, commonStatuses[0] || singing.statuses[0]);
|
||||
|
||||
const statusClass = getStatusClass(lastStatus.category);
|
||||
const statusIcon = getStatusIcon(lastStatus.category);
|
||||
@@ -519,6 +718,14 @@
|
||||
lastStatus.category === 'processing' ? '#409EFF' :
|
||||
lastStatus.category === 'error' ? '#F56C6C' : '#909399';
|
||||
|
||||
// Маппинг типов доставки на отображаемые названия
|
||||
const deliveryTypeLabels = {
|
||||
'sms': 'СМС-сообщение',
|
||||
'max': 'МАХ-сообщение',
|
||||
'mila': 'Mila-сообщение',
|
||||
'goskey': 'Goskey-сообщение'
|
||||
};
|
||||
|
||||
// Формируем ячейку с документами
|
||||
const documentsHtml = singing.documents.map(doc => `
|
||||
<div style="display: flex; align-items: flex-start; gap: 8px; margin-bottom: ${singing.documents.length > 1 ? '8px' : '0'}; padding: 4px 0;">
|
||||
@@ -550,47 +757,47 @@
|
||||
${documentsHtml}
|
||||
</td>
|
||||
<td style="padding: 12px; vertical-align: top;">
|
||||
<div style="display: flex; align-items: center; gap: 12px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px; flex: 1;">
|
||||
<div style="display: flex; align-items: center; gap: 4px;">
|
||||
<div style="display: flex; align-items: center; gap: 4px; flex: 1;">
|
||||
<i class="el-icon ${statusIcon}" style="color: ${statusColor}; font-size: 16px;"></i>
|
||||
<div>
|
||||
<div style="color: ${statusColor};">${lastStatus.description}</div>
|
||||
<div style="font-size: 12px; color: #909399; margin-top: 2px;">${formatDate(lastStatus.created_at)}</div>
|
||||
<div style="font-size: 12px; color: #909399; margin-top: 2px;">${formatDate(lastStatus.created_at)} ✉️ ${deliveryTypeLabels[singing.deliveryType]}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
${singing.storagePath ? `
|
||||
<button class="el-button el-button--text view-main-doc-btn"
|
||||
data-title="${singing.title}"
|
||||
data-path="${singing.storagePath}"
|
||||
title="Просмотреть основной документ"
|
||||
style="padding: 0; border: none;">
|
||||
<i class="el-icon el-icon-document" style="color: #409EFF; font-size: 18px;"></i>
|
||||
</button>
|
||||
` : ''}
|
||||
<div style="display: flex; gap: 2px; align-items: center;">
|
||||
${singing.storagePath && singing.storagePath.length > 0
|
||||
? singing.storagePath.map((path, index) => `
|
||||
<button class="el-button el-button--text view-main-doc-btn"
|
||||
data-title="${singing.title || `Итоговый документ ${index + 1}`}"
|
||||
data-path="${path}"
|
||||
title="Просмотреть основной документ ${singing.storagePath.length > 1 ? index + 1 : ''}"
|
||||
style="margin: 0; padding: 0; border: none; min-width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center;">
|
||||
<i class="el-icon el-icon-document" style="color: #409EFF; font-size: 16px;"></i>
|
||||
</button>
|
||||
`).join('')
|
||||
: ''}
|
||||
${singing.statuses.length > 1 ? `
|
||||
<button class="el-button el-button--text view-statuses-btn"
|
||||
data-index="${index}"
|
||||
title="История статусов"
|
||||
style="padding: 0; border: none;">
|
||||
<i class="el-icon el-icon-time" style="color: #909399; font-size: 18px;"></i>
|
||||
style="margin: 0; padding: 0; border: none; min-width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center;">
|
||||
<i class="el-icon el-icon-time" style="color: #909399; font-size: 16px;"></i>
|
||||
</button>
|
||||
` : ''}
|
||||
${lastStatus.category === 'processing' ? `
|
||||
<div style="display: flex; gap: 4px;">
|
||||
<button class="el-button el-button--text resend-btn"
|
||||
data-index="${index}"
|
||||
title="Повторно отправить документы"
|
||||
style="padding: 0; border: none;">
|
||||
<i class="el-icon el-icon-refresh" style="color: #67C23A; font-size: 18px;"></i>
|
||||
</button>
|
||||
<button class="el-button el-button--text revoke-btn"
|
||||
data-index="${index}"
|
||||
title="Отозвать документы"
|
||||
style="padding: 0; border: none;">
|
||||
<i class="el-icon el-icon-circle-close" style="color: #F56C6C; font-size: 18px;"></i>
|
||||
</button>
|
||||
</div>
|
||||
<button class="el-button el-button--text resend-btn"
|
||||
data-index="${index}"
|
||||
title="Повторно отправить документы"
|
||||
style="margin: 0; padding: 0; border: none; min-width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center;">
|
||||
<i class="el-icon el-icon-refresh" style="color: #67C23A; font-size: 16px;"></i>
|
||||
</button>
|
||||
<button class="el-button el-button--text revoke-btn"
|
||||
data-index="${index}"
|
||||
title="Отозвать документы"
|
||||
style="margin: 0; padding: 0; border: none; min-width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center;">
|
||||
<i class="el-icon el-icon-circle-close" style="color: #F56C6C; font-size: 16px;"></i>
|
||||
</button>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
@@ -707,7 +914,8 @@
|
||||
const response = await sendMessageToContent('prepareDocuments', {});
|
||||
|
||||
if (response.success) {
|
||||
createDocumentsTable(response.data);
|
||||
deliveryTypeSettings = response.data.deliveryType;
|
||||
createDocumentsTable(response.data.singings);
|
||||
} else {
|
||||
showMessage('Ошибка загрузки документов: ' + (response.message || 'Неизвестная ошибка'), 'error');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user