Files
cabinet/mr.diff
2026-05-28 12:09:28 +03:00

226 lines
10 KiB
Diff

diff --git a/assets/components/misSession.js b/assets/components/misSession.js
new file mode 100644
index 0000000..45088ef
--- /dev/null
+++ b/assets/components/misSession.js
@@ -0,0 +1,118 @@
+/**
+ * MIS (webSDK / widget.sovamed.ru) session helpers.
+ * Symfony login (ROLE_USER) and MIS session are independent.
+ */
+
+function MisSessionError() {
+ this.name = 'MisSessionError';
+ this.message = 'MIS session is not authenticated';
+}
+
+function isAuthenticated(webSDK) {
+ return Boolean(webSDK?.data?.user?.authenticated);
+}
+
+function ensureAuthenticated(webSDK) {
+ return new Promise(function(resolve, reject) {
+ if (isAuthenticated(webSDK)) {
+ resolve(webSDK);
+ return;
+ }
+
+ if (typeof webSDK?.isLoggedIn === 'function') {
+ webSDK.isLoggedIn(webSDK.sdkOrigin).then(function(result) {
+ if (result?.authenticated) {
+ resolve(webSDK);
+ return;
+ }
+ reject(new MisSessionError());
+ }).catch(function() {
+ reject(new MisSessionError());
+ });
+ return;
+ }
+
+ reject(new MisSessionError());
+ });
+}
+
+function removeSdkOverlayModals() {
+ document.querySelectorAll('.wr-sdk-widget-modal').forEach(function(modal) {
+ modal.remove();
+ });
+}
+
+/**
+ * Move #iframeProtocol from SDK overlay into cabinet bootstrap popup.
+ * openConference() must be called without container (SDK applies Guest URL fix).
+ */
+function mountConferenceInPopup(popup) {
+ var iframe = document.getElementById('iframeProtocol');
+ var popupBody = popup?.querySelector('#popup-body');
+
+ if (!iframe || !popupBody) {
+ return false;
+ }
+
+ removeSdkOverlayModals();
+ popupBody.innerHTML = '';
+ popupBody.appendChild(iframe);
+ iframe.style.width = '100%';
+ iframe.style.border = 'none';
+ iframe.style.height = (window.innerHeight - 100) + 'px';
+
+ var fullScreenBtn = popup.querySelector('.full-scren-modal');
+ if (fullScreenBtn) {
+ fullScreenBtn.classList.remove('d-none');
+ }
+
+ popup.querySelector('.modal-dialog').classList = 'modal-dialog';
+ popup.querySelector('.modal-content').classList = 'modal-content';
+ popup.querySelector('.modal-title').innerHTML = 'Онлайн консультация';
+
+ if (typeof $ !== 'undefined' && typeof $(popup).modal === 'function') {
+ $(popup).modal('show');
+ }
+
+ return true;
+}
+
+function showMisSessionExpired(popup) {
+ if (!popup) {
+ window.location.pathname = '/logout';
+ return;
+ }
+
+ popup.querySelector('.modal-dialog').classList = 'modal-dialog';
+ popup.querySelector('.modal-title').innerHTML = 'Сессия виджета истекла';
+ popup.querySelector('#popup-body').innerHTML =
+ '<p class="mb-3">Личный кабинет открыт, но сессия виджета записи (MIS) истекла. ' +
+ 'Для оплаты и онлайн-приёма нужно войти снова — повторная авторизация в iframe не требуется.</p>' +
+ '<button type="button" class="btn btn-outline-secondary w-100" id="mis-session-relogin">Войти снова</button>';
+
+ popup.querySelector('#mis-session-relogin').addEventListener('click', function() {
+ window.location.pathname = '/logout';
+ });
+
+ if (typeof $ !== 'undefined' && typeof $(popup).modal === 'function') {
+ $(popup).modal('show');
+ }
+}
+
+function handleMisSessionFailure(popup, error, logContext) {
+ if (error instanceof MisSessionError || error?.name === 'MisSessionError') {
+ showMisSessionExpired(popup);
+ return true;
+ }
+
+ return false;
+}
+
+module.exports = {
+ MisSessionError: MisSessionError,
+ isAuthenticated: isAuthenticated,
+ ensureAuthenticated: ensureAuthenticated,
+ mountConferenceInPopup: mountConferenceInPopup,
+ showMisSessionExpired: showMisSessionExpired,
+ handleMisSessionFailure: handleMisSessionFailure,
+};
diff --git a/assets/controllers/caseHistory_controller.js b/assets/controllers/caseHistory_controller.js
index 735c13c..aabafb1 100644
--- a/assets/controllers/caseHistory_controller.js
+++ b/assets/controllers/caseHistory_controller.js
@@ -2,6 +2,7 @@ import { Controller } from 'stimulus';
import Cookies from 'js-cookie';
const loader = require("./../components/loader.js");
const helper = require("./../components/helper.js");
+const misSession = require("./../components/misSession.js");
/*
* This is an example Stimulus controller!
@@ -248,20 +249,23 @@ export default class extends Controller {
btnConfirence.setAttribute('data-filial' , data.filial)
btnConfirence.addEventListener('click', function () {
popup.querySelector('#popup-body').innerHTML = '';
-
- webSDK.openConference({
- schedid: btnConfirence.dataset.id,
- container: popup.querySelector('#popup-body')
- }).then(function () {
- popup.querySelector('.full-scren-modal').classList.remove('d-none');
- document.getElementById('iframeProtocol').style.height = (window.innerHeight - 100) + 'px';
- popup.querySelector('.modal-dialog').classList = 'modal-dialog';
- popup.querySelector('.modal-content').classList = 'modal-content';
- popup.querySelector('.modal-content').classList = 'modal-content';
- popup.querySelector('.modal-title').innerHTML = 'Онлайн консультация';
- $(popup).modal('show');
+ misSession.ensureAuthenticated(webSDK).then(function() {
+ return webSDK.openConference({
+ schedid: btnConfirence.dataset.id
+ });
+ }).then(function () {
+ if (!misSession.mountConferenceInPopup(popup)) {
+ throw { data: { message: 'Не удалось открыть окно онлайн-консультации.' } };
+ }
}).catch(function (e) {
+ if (misSession.handleMisSessionFailure(popup, e)) {
+ helper.sendRequest({
+ data: {'error': e, method: 'openConference', reason: 'mis_session_expired'}
+ }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
+ return;
+ }
+
if (typeof e.data?.message !== 'undefined') {
var msg = e.data.message.replace('UTC+3', 'UTC+3 (московское время)');
popup.querySelector('#popup-body').innerHTML = msg;
@@ -272,9 +276,9 @@ export default class extends Controller {
}
helper.sendRequest({
- data: {'error': e, method: 'openConference'}
- }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
- });
+ data: {'error': e, method: 'openConference'}
+ }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
+ });
});
} else {
@@ -376,7 +380,6 @@ export default class extends Controller {
btnPayment.setAttribute('data-amt' , data.payment.amt);
btnPayment.setAttribute('data-payprofileid' , data.payment.magazineId);
btnPayment.addEventListener('click', function () {
-
var params = {
'orderid': Number(btnPayment.dataset.id) ,
'payprofileid': btnPayment.dataset.payprofileid,
@@ -386,14 +389,26 @@ export default class extends Controller {
'pcode': webSDK.data.user.id,
'successurl': document.location.origin + '/case-history#pay-success',
'errorurl': document.location.origin + '/case-history#error',
- 'containerId': 'popup-body',
+ 'containerId': 'popup-body',
};
- webSDK.loadPaymentView(params);
+ misSession.ensureAuthenticated(webSDK).then(function() {
+ webSDK.loadPaymentView(params);
+ popup.querySelector('#popup-body').innerHTML = '';
+ popup.querySelector('.modal-title').innerHTML = 'Оплата';
+ $(popup).modal('show');
+ }).catch(function(e) {
+ if (misSession.handleMisSessionFailure(popup, e)) {
+ helper.sendRequest({
+ data: {'error': e, method: 'loadPaymentView', reason: 'mis_session_expired'}
+ }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
+ return;
+ }
- popup.querySelector('#popup-body').innerHTML = '';
- popup.querySelector('.modal-title').innerHTML = 'Оплата';
- $(popup).modal('show');
+ helper.sendRequest({
+ data: {'error': e, method: 'loadPaymentView'}
+ }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
+ });
});
} else {
btnPayment.classList.add('d-none');