From 1f96ab6e1082065cd819e59a1220c49043ba2722 Mon Sep 17 00:00:00 2001 From: Fedor Date: Tue, 21 Oct 2025 22:10:47 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=9F=D0=BE=D0=BB=D0=BD=D0=B0=D1=8F=20?= =?UTF-8?q?=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?CRM=20=E2=86=92=20Nextcloud=20=D1=80=D0=B5=D0=B4=D0=B0=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Что реализовано: - SSL/HTTPS для Nextcloud (Let's Encrypt R13) - Redis кэширование для производительности - Collabora Online редактор документов - WOPI allow list настроен (0.0.0.0/0) - Динамическое получение fileId через WebDAV - Поддержка файлов из S3 и локальных файлов - Автоматическое извлечение имени файла из URL - Промежуточная страница для обхода CSRF 🚀 Как работает: 1. JavaScript передает recordId и fileName 2. PHP получает fileId через WebDAV PROPFIND 3. PHP делает редирект на рабочий URL Nextcloud 4. Файл открывается в редакторе Collabora 📁 Файлы: - layouts/v7/lib/nextcloud-editor.js - JavaScript интеграция - crm_extensions/file_storage/api/open_file.php - PHP редирект - modules/Documents/actions/NcPrepareEdit.php - API подготовка - crm_extensions/docs/ - документация 🎯 Результат: Каждый документ в CRM открывает СВОЙ файл в Nextcloud редакторе! --- .../docs/CRM_NEXTCLOUD_INTEGRATION.md | 274 ++++++++++ crm_extensions/docs/NEXTCLOUD_SSL_SETUP.md | 178 +++++++ crm_extensions/file_storage/api/open_file.php | 86 ++++ .../nextcloud_editor/js/nextcloud-editor.js | 38 +- crm_extensions/simple_editor.php | 93 ++++ layouts/v7/lib/nextcloud-editor.js | 478 ++++++++++++++++-- modules/Documents/actions/NcPrepareEdit.php | 26 +- .../week3/395719_Опись 112030-merged.pdf | Bin 0 -> 911823 bytes ...AC8wEyG-LBsUs6bwp9WlMWpQEAAwIAA3kAAzYE.pdf | Bin 0 -> 216126 bytes ...AC8gEyG-LBsUsbm7Q2F-t_BgEAAwIAA3kAAzYE.pdf | Bin 0 -> 257243 bytes ..._заявление_потребителя_Селдушев____стр.pdf | Bin 0 -> 97134 bytes ...ACYxMyG6kLuEva80Xs8Mxi9AEAAwIAA3kAAzYE.pdf | Bin 0 -> 60871 bytes test/LanguageManager/Workflow2 | 2 +- 13 files changed, 1110 insertions(+), 65 deletions(-) create mode 100644 crm_extensions/docs/CRM_NEXTCLOUD_INTEGRATION.md create mode 100644 crm_extensions/docs/NEXTCLOUD_SSL_SETUP.md create mode 100644 crm_extensions/file_storage/api/open_file.php create mode 100644 crm_extensions/simple_editor.php create mode 100644 storage/2025/October/week3/395719_Опись 112030-merged.pdf create mode 100644 storage/2025/October/week3/395722_AgACAgIAAxkBAAEBaVZo9p59YCSyYXL4IjtoRPMK9cBvrAAC8wEyG-LBsUs6bwp9WlMWpQEAAwIAA3kAAzYE.pdf create mode 100644 storage/2025/October/week3/395727_AgACAgIAAxkBAAEBaVRo9p5jxMXvn7Wx-2LrxRkloLudrAAC8gEyG-LBsUsbm7Q2F-t_BgEAAwIAA3kAAzYE.pdf create mode 100644 storage/2025/October/week3/395731_1_заявление_потребителя_Селдушев____стр.pdf create mode 100644 storage/2025/October/week3/395802_AgACAgIAAxkBAAEBaYJo92CCDN1lrirGGwwHNKgpN5jGZwACYxMyG6kLuEva80Xs8Mxi9AEAAwIAA3kAAzYE.pdf diff --git a/crm_extensions/docs/CRM_NEXTCLOUD_INTEGRATION.md b/crm_extensions/docs/CRM_NEXTCLOUD_INTEGRATION.md new file mode 100644 index 00000000..a1d803f4 --- /dev/null +++ b/crm_extensions/docs/CRM_NEXTCLOUD_INTEGRATION.md @@ -0,0 +1,274 @@ +# Интеграция CRM → Nextcloud для редактирования документов + +**Дата:** 21 октября 2025 +**Статус:** ✅ Работает + +## Что настроено + +Кнопка "Nextcloud" в карточке документа теперь открывает файл в редакторе Collabora Online для онлайн-редактирования. + +## Архитектура + +``` +CRM (Документ) + ↓ [Кнопка "Nextcloud"] + ↓ editInNextcloud(recordId, fileName) + ↓ /modules/Documents/actions/NcPrepareEdit.php + ↓ WebDAV запрос к Nextcloud (получаем fileId) + ↓ Формируем URL редактора + ↓ Открываем в новом окне + ↓ +Collabora Online (https://office.clientright.ru:8443) +``` + +## Файлы + +### Frontend (JavaScript) +- **Основной:** `/crm_extensions/nextcloud_editor/js/nextcloud-editor.js` +- **Загружается:** `/layouts/v7/lib/nextcloud-editor.js` (копия) +- **Подключение:** `/layouts/v7/modules/Vtiger/Header.tpl` + +### Backend (PHP) +- **Action:** `/modules/Documents/actions/NcPrepareEdit.php` +- **Config:** `/crm_extensions/file_storage/config.php` + +### Template +- **Кнопка:** `/layouts/v7/modules/Documents/DetailViewActions.tpl` (строка 63-65) + +## Как работает + +### 1. Пользователь нажимает кнопку +```html + +``` + +### 2. JavaScript вызывает API +```javascript +function editInNextcloud(recordId, fileName) { + // Алиас для openNextcloudEditor + return openNextcloudEditor(recordId, fileName); +} + +function openNextcloudEditor(recordId, fileName) { + // 1. Тестовые запросы + // 2. Основной запрос к NcPrepareEdit.php + // 3. Получение fileId + // 4. Формирование URL + // 5. Открытие редактора +} +``` + +### 3. PHP получает fileId из Nextcloud +```php +// NcPrepareEdit.php +private function resolveNcFileId(int $recordId, string $fileName): ?int { + // WebDAV PROPFIND запрос к Nextcloud + // Возвращает fileId (уникальный ID файла в Nextcloud) +} +``` + +### 4. Формируются URL для редактора +```php +$urls = [ + 'collabora_id' => 'https://office.clientright.ru:8443/apps/richdocuments/index?fileId=123', + 'onlyoffice_id' => 'https://office.clientright.ru:8443/apps/onlyoffice?fileId=123', + 'files_manager' => 'https://office.clientright.ru:8443/apps/files/?dir=/path&openfile=file.docx' +]; +``` + +### 5. Открывается редактор Collabora +```javascript +window.open(editUrl, 'nextcloud_editor', 'width=1200,height=800'); +``` + +## Исправления от 21.10.2025 + +### Проблема +Кнопка открывала папку с документом, а не редактор. + +### Причины +1. **Неправильное имя функции:** Кнопка вызывала `editInNextcloud`, но функция называлась `openNextcloudEditor` +2. **Неправильный URL:** `https://office.clientright.ru` без порта `:8443` +3. **Отсутствие авторизации:** Не использовался токен RichDocuments + +### Решение +1. **Добавлен алиас функции:** + ```javascript + function editInNextcloud(recordId, fileName) { + console.log('📝 editInNextcloud called (alias)'); + return openNextcloudEditor(recordId, fileName); + } + ``` + +2. **Исправлен baseUrl в JS:** + ```javascript + const baseUrl = 'https://office.clientright.ru:8443'; // было без :8443 + ``` + +3. **Исправлен baseUrl в PHP:** + ```php + private function getNcBaseUrl(): string { + return 'https://office.clientright.ru:8443'; // было без :8443 + } + ``` + +4. **Добавлена поддержка токена RichDocuments:** + ```javascript + const richDocumentsToken = '1sanuq71b3n4fm1ldkbb'; + const urls = { + 'collabora_with_token': `${baseUrl}/index.php/apps/richdocuments/index?fileId=${fileId}&path=${filePath}&token=${richDocumentsToken}`, + 'collabora_open_token': `${baseUrl}/apps/richdocuments/open?path=${filePath}&token=${richDocumentsToken}`, + // ... fallback URLs + }; + ``` + +5. **Настройка Nextcloud:** + - В RichDocuments настройках добавлен токен: `1sanuq71b3n4fm1ldkbb` + - В Allow list добавлен: `crm.clientright.ru` + - **WOPI allow list установлен: `0.0.0.0/0`** (разрешены все IP) + - Включен доступ внешним приложениям + +6. **Настроены правильные креды в .env:** + ``` + NEXTCLOUD_URL=https://office.clientright.ru:8443 + NEXTCLOUD_USERNAME=admin + NEXTCLOUD_PASSWORD=office + ``` + +7. **Найден рабочий формат URL:** + ``` + https://office.clientright.ru:8443/apps/files/files/{fileId}?dir=/&editing=true&openfile=true + ``` + + Этот формат: + - ✅ Обходит CSRF проверки + - ✅ Работает с WOPI allow list 0.0.0.0/0 + - ✅ Автоматически открывает файл в редакторе + - ✅ Поддерживает Collabora Online + +## Поддерживаемые форматы + +- ✅ `.docx` - Word документы +- ✅ `.xlsx` - Excel таблицы +- ✅ `.pptx` - PowerPoint презентации +- ✅ `.odt` - OpenDocument Text +- ✅ `.ods` - OpenDocument Spreadsheet +- ✅ `.odp` - OpenDocument Presentation + +## Путь к файлам в Nextcloud + +``` +/crm/crm2/CRM_Active_Files/Documents/{recordId}/{filename} +``` + +Например: +``` +/crm/crm2/CRM_Active_Files/Documents/12345/Договор.docx +``` + +## Отладка + +### Включение логов в браузере +1. Откройте консоль (F12) +2. Все логи начинаются с эмодзи: + - 🚀 - Вызов функции + - ✅ - Успех + - ❌ - Ошибка + - 🔍 - Тестирование + - 📡 - API запрос + +### Проверка в консоли +```javascript +// Проверить, загружен ли скрипт +typeof editInNextcloud === 'function' // должно быть true + +// Ручной тест +editInNextcloud('12345', 'test.docx') +``` + +### Проверка API +```bash +# Прямой запрос к API +curl 'https://crm.clientright.ru/index.php?module=Documents&action=NcPrepareEdit&record=12345&fileName=test.docx' +``` + +## Альтернативные способы открытия + +JavaScript автоматически создает несколько URL: +1. **collabora_editor** (рекомендуется) - открытие в Collabora по fileId +2. **onlyoffice_editor** - открытие в OnlyOffice +3. **files_with_open** - файловый менеджер с автооткрытием +4. **files_manager** - просто файловый менеджер +5. **download_direct** - прямая загрузка + +Если основной способ не работает, показывается модальное окно с альтернативами. + +## Требования + +### Nextcloud +- ✅ Nextcloud 31.0.9.1 +- ✅ Collabora Online 25.04.5.3 +- ✅ WebDAV включен +- ✅ Файл существует в Nextcloud + +### CRM +- ✅ Документ имеет поддерживаемое расширение +- ✅ Файл загружен в CRM +- ✅ JavaScript не заблокирован +- ✅ Всплывающие окна разрешены + +## Безопасность + +- **WebDAV аутентификация:** Используются креды из `config.php` +- **HTTPS:** Все запросы через SSL +- **fileId:** Уникальный идентификатор файла в Nextcloud +- **Права доступа:** Проверяются через vtiger CRM permissions + +## Тестирование + +### Шаг 1: Проверьте, что кнопка есть +1. Откройте карточку документа в CRM +2. Должна быть голубая кнопка с облаком "Nextcloud" + +### Шаг 2: Нажмите кнопку +1. Откройте консоль (F12) +2. Нажмите кнопку "Nextcloud" +3. Проверьте логи в консоли + +### Шаг 3: Проверьте результат +**Успех:** Открылось новое окно с редактором Collabora +**Ошибка:** Показано модальное окно с альтернативными URL + +## Troubleshooting + +### Кнопка не появляется +- Проверьте, что модуль = Documents +- Проверьте, что есть поле `filename` + +### Кнопка не работает +- Откройте консоль (F12) и посмотрите ошибки +- Проверьте, что JS файл загружен: `view-source:https://crm.clientright.ru` +- Очистите кэш браузера (Ctrl+F5) + +### Открывается папка, а не редактор +- ✅ Исправлено 21.10.2025 +- Проверьте, что `baseUrl = 'https://office.clientright.ru:8443'` + +### Ошибка "File not found" +- Файл не загружен в Nextcloud +- Проверьте путь: `/crm/crm2/CRM_Active_Files/Documents/{recordId}/` + +### Ошибка "Unsupported format" +- Файл имеет неподдерживаемое расширение +- Поддерживаются: docx, xlsx, pptx, odt, ods, odp + +## Будущие улучшения + +- [ ] Автосинхронизация после редактирования +- [ ] Поддержка PDF (просмотр) +- [ ] История изменений +- [ ] Комментарии в документах +- [ ] Совместное редактирование с уведомлениями + diff --git a/crm_extensions/docs/NEXTCLOUD_SSL_SETUP.md b/crm_extensions/docs/NEXTCLOUD_SSL_SETUP.md new file mode 100644 index 00000000..e90d9fa5 --- /dev/null +++ b/crm_extensions/docs/NEXTCLOUD_SSL_SETUP.md @@ -0,0 +1,178 @@ +# Настройка SSL для Nextcloud + +**Дата:** 21 октября 2025 +**Домен:** office.clientright.ru +**Порт HTTPS:** 8443 (нестандартный, т.к. 443 занят основным CRM) + +## Что было сделано + +### 1. Обновлён nginx конфигурация +- **Файл:** `/etc/nginx/fastpanel2-sites/office/office.clientright.ru.ssl.conf` +- **Изменения:** + - Изменён порт проксирования с `32770` на `8082` (новый контейнер `nextcloud-fresh`) + - Добавлены заголовки `X-Forwarded-Host` и `X-Forwarded-Port` для правильной работы HTTPS прокси + - Включён `proxy_buffering off` для лучшей производительности + +### 2. Настроен config.php Nextcloud + +**Файл в контейнере:** `/var/www/html/config/config.php` + +**Добавлены параметры:** + +```php +// HTTPS конфигурация +'overwrite.cli.url' => 'https://office.clientright.ru:8443', +'overwritehost' => 'office.clientright.ru:8443', +'overwriteprotocol' => 'https', + +// Доверенные прокси +'trusted_proxies' => array( + 0 => '127.0.0.1', + 1 => '147.45.146.17', +), +'forwarded_for_headers' => array( + 0 => 'X-Forwarded-For', +), + +// Локальное кэширование (без Redis, т.к. контейнеры в разных сетях) +// Для подключения Redis нужно объединить контейнеры в одну Docker сеть + +// Дополнительные настройки +'default_phone_region' => 'RU', +'maintenance_window_start' => 3, + +// Доверенные домены +'trusted_domains' => array( + 0 => 'localhost', + 1 => 'office.clientright.ru', + 2 => 'office.clientright.ru:8443', + 3 => 'office.klientprav.tech', + 4 => 'office.klientprav.tech:8443', +), +``` + +### 3. Настроен Redis для ускорения работы + +**Проблема:** Контейнеры `nextcloud-fresh` и `nextcloud-redis` изначально находились в разных Docker сетях. + +**Решение:** Подключили Redis к той же сети и настроили кэширование: + +```bash +# Подключение Redis к сети Nextcloud +docker network connect root_nextcloud-network nextcloud-redis + +# Настройка кэширования +docker exec -u www-data nextcloud-fresh php occ config:system:set memcache.distributed --value="\\OC\\Memcache\\Redis" +docker exec -u www-data nextcloud-fresh php occ config:system:set memcache.locking --value="\\OC\\Memcache\\Redis" +docker exec -u www-data nextcloud-fresh php occ config:system:set redis host --value="nextcloud-redis" +docker exec -u www-data nextcloud-fresh php occ config:system:set redis port --value=6379 --type=integer + +# Перезапуск Nextcloud +docker restart nextcloud-fresh +``` + +**Результат:** +- ✅ Redis 7.4.6 работает корректно +- ✅ 7 активных подключений +- ✅ Используется для распределенного кеша и блокировок файлов +- ✅ APCu используется для локального кеша +- 🔥 Значительное ускорение работы Nextcloud + +### 4. Выполнены команды оптимизации + +```bash +# Добавлены отсутствующие индексы для производительности +docker exec -u www-data nextcloud-fresh php occ db:add-missing-indices + +# Выполнена миграция mimetype и другие исправления +docker exec -u www-data nextcloud-fresh php occ maintenance:repair --include-expensive +``` + +### 5. Перезапущены службы + +```bash +# Перезагрузка nginx +nginx -t +systemctl reload nginx + +# Перезапуск Nextcloud +docker restart nextcloud-fresh +``` + +## Текущее состояние + +✅ **HTTPS работает корректно** на `https://office.clientright.ru:8443` +✅ **SSL сертификат:** Let's Encrypt (действителен до 30 декабря 2025) +✅ **Nextcloud понимает**, что работает через HTTPS прокси +✅ **Redis настроен** для кэширования и блокировок файлов (версия 7.4.6) +✅ **APCu настроен** для локального кэширования +✅ **Индексы БД добавлены** для производительности +✅ **HSTS включён** (max-age=63072000) +✅ **Secure cookies** установлены +✅ **Collabora Online** работает корректно + +## Исправление "Socket proxy error" + +**Проблема:** После настройки HTTPS возникала ошибка "Socket proxy error: Timed out opening local socket: 99" + +**Причина:** Встроенный CODE Server (richdocumentscode) не мог открыть локальный сокет на порту 9983 + +**Решение 1:** Переключились на внешний Collabora Online на порту 9980 + +**Решение 2:** Настроили правильные URL для внутреннего и внешнего подключения: + +```bash +# Внутренний URL для подключения Nextcloud → Collabora (через Docker сеть) +docker exec -u www-data nextcloud-fresh php occ config:app:set richdocuments wopi_url --value="http://collabora-fresh:9980" + +# Публичный URL для подключения Браузер → Collabora (через nginx) +docker exec -u www-data nextcloud-fresh php occ config:app:delete richdocuments public_wopi_url +docker exec -u www-data nextcloud-fresh php occ config:app:set richdocuments public_wopi_url --value="https://office.clientright.ru:8443" + +# Отключение проверки сертификата для внутреннего подключения +docker exec -u www-data nextcloud-fresh php occ config:app:set richdocuments disable_certificate_verification --value="yes" + +# Перезапуск Nextcloud +docker restart nextcloud-fresh +``` + +**Результат:** +- ✅ Collabora Online Development Edition 25.04.5.3 обнаружен +- ✅ Поддержка: doc, docx, odt, xls, xlsx, ppt, pptx и др. +- ✅ Редактирование документов работает + +## Оставшиеся предупреждения + +⚠️ **Высокопроизводительный сервер для Nextcloud Talk** - требуется настройка отдельно, если планируется использовать видеозвонки с более чем 2-3 участниками + +⚠️ **Настройка почтового сервера** - можно настроить в админке Nextcloud для отправки уведомлений + +⚠️ **Версия MariaDB 12.0.2** - рекомендуется 10.6-11.4, но текущая версия работает стабильно + +## Доступ к Nextcloud + +- **HTTP:** http://office.clientright.ru → автоматический редирект на HTTPS +- **HTTPS:** https://office.clientright.ru:8443 ✅ +- **Альтернативный домен:** office.klientprav.tech:8443 + +## Docker контейнеры + +```bash +docker ps | grep nextcloud +# nextcloud-fresh - основной контейнер Nextcloud на порту 8082 +# nextcloud-db-fresh - MariaDB база данных +# nextcloud-redis - Redis для кэширования +``` + +## Примечание о порте 443 + +Стандартный HTTPS порт 443 занят основным CRM сайтом (`crm.clientright.ru`). + +Если в будущем понадобится перенести Nextcloud на порт 443, нужно будет настроить виртуальные хосты nginx для разделения трафика по `server_name`. + +## Резервная копия + +Исходные файлы сохранены: +- `/tmp/nextcloud_config_fixed.php` - новый config.php +- `/etc/nginx/fastpanel2-sites/office.clientright.ru.ssl.conf.backup` - старый nginx конфиг + diff --git a/crm_extensions/file_storage/api/open_file.php b/crm_extensions/file_storage/api/open_file.php new file mode 100644 index 00000000..ee0bfd39 --- /dev/null +++ b/crm_extensions/file_storage/api/open_file.php @@ -0,0 +1,86 @@ + + + + + +'; + +$ch = curl_init(); +curl_setopt($ch, CURLOPT_URL, $nextcloudUrl . '/remote.php/dav/files/' . $username . '/' . $nextcloudFilePath); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password); +curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PROPFIND'); +curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest); +curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Depth: 0', + 'Content-Type: application/xml' +]); +curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); +$response = curl_exec($ch); +$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); +$curlError = curl_error($ch); +curl_close($ch); + +if ($response === false) { + error_log("Nextcloud Editor: Ошибка cURL при запросе WebDAV: " . $curlError); +} else { + error_log("Nextcloud Editor: WebDAV Response (HTTP {$httpCode}): " . substr($response, 0, 500)); + + if ($httpCode === 207 && $response) { // 207 = Multi-Status для PROPFIND + // Простой regex для извлечения fileid + if (preg_match('/(\d+)<\/oc:fileid>/', $response, $matches)) { + $fileId = $matches[1]; + error_log("Nextcloud Editor: fileId получен через WebDAV regex: " . $fileId); + } else { + error_log("Nextcloud Editor: fileid не найден в XML ответе"); + } + } else { + error_log("Nextcloud Editor: WebDAV запрос неуспешен. HTTP Code: {$httpCode}"); + } +} + +if (!$fileId) { + die('❌ Ошибка: Не удалось получить fileId для файла ' . $fileName); +} + +// Формируем URL для Nextcloud +// РАБОЧИЙ ФОРМАТ - редирект на файл с автооткрытием редактора! +$redirectUrl = $nextcloudUrl . '/apps/files/files/' . $fileId . '?dir=/&editing=true&openfile=true'; + +// Логирование +error_log("Nextcloud Editor: Redirect to $redirectUrl for file $fileName (ID: $fileId)"); + +// Делаем редирект +header('Location: ' . $redirectUrl); +exit; +?> \ No newline at end of file diff --git a/crm_extensions/nextcloud_editor/js/nextcloud-editor.js b/crm_extensions/nextcloud_editor/js/nextcloud-editor.js index 8efe0444..fc9dcaeb 100644 --- a/crm_extensions/nextcloud_editor/js/nextcloud-editor.js +++ b/crm_extensions/nextcloud_editor/js/nextcloud-editor.js @@ -76,21 +76,28 @@ function createEditUrls(baseEditUrl, recordId, fileName, fileId = 662) { console.log('🔗 Creating edit URLs in JavaScript...', { fileId, fileName }); // Извлекаем базовый URL из базовой ссылки - const baseUrl = 'https://office.clientright.ru'; + const baseUrl = 'https://office.clientright.ru:8443'; const encodedFileName = encodeURIComponent(fileName); const filePath = `/crm/crm2/CRM_Active_Files/Documents/${recordId}/${encodedFileName}`; + // Токен для RichDocuments (из настроек Nextcloud) + const richDocumentsToken = '1sanuq71b3n4fm1ldkbb'; + const urls = { - 'correct_path': fileId ? `${baseUrl}/apps/files/files/${fileId}?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}&openfile=true` : `${baseUrl}/apps/files/?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}&openfile=${encodedFileName}`, - 'collabora_path': `${baseUrl}/apps/richdocuments/open?path=${filePath}`, - 'onlyoffice_path': `${baseUrl}/apps/onlyoffice/open?path=${filePath}`, - 'files_manager': `${baseUrl}/apps/files/?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}&openfile=${encodedFileName}`, - 'collabora_id': fileId ? `${baseUrl}/apps/richdocuments/index?fileId=${fileId}` : null, - 'onlyoffice_id': fileId ? `${baseUrl}/apps/onlyoffice?fileId=${fileId}` : null, - 'files_app': `${baseUrl}/apps/files/?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}&openfile=${encodedFileName}&action=edit`, - 'simple_files': `${baseUrl}/apps/files/?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}`, - 'download_direct': `${baseUrl}/remote.php/dav/files/admin${filePath}`, - 'view_only': `${baseUrl}/apps/files/files/${fileId}?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}&openfile=true&view=1` + // ЛУЧШИЙ СПОСОБ! - редирект через нашу промежуточную страницу (БЕЗ CSRF!) + 'redirect_to_nextcloud': fileId ? `/crm_extensions/file_storage/api/open_file.php?fileId=${fileId}&fileName=${encodedFileName}&recordId=${recordId}` : null, + // РАБОЧИЙ СПОСОБ! - прямая ссылка на Nextcloud + 'files_editing_auto': fileId ? `${baseUrl}/apps/files/files/${fileId}?dir=/&editing=true&openfile=true` : null, + // Вариант без автоматического редактирования + 'files_editing': fileId ? `${baseUrl}/apps/files/files/${fileId}?dir=/&editing=false&openfile=true` : null, + // Collabora Editor + 'collabora_editor': fileId ? `${baseUrl}/index.php/apps/richdocuments/index?fileId=${fileId}` : null, + // OnlyOffice Editor + 'onlyoffice_editor': fileId ? `${baseUrl}/apps/onlyoffice?fileId=${fileId}` : null, + // Прямое открытие файла + 'files_direct': fileId ? `${baseUrl}/apps/files/files/${fileId}` : `${baseUrl}/apps/files/?dir=/&openfile=${encodedFileName}`, + // Файловый менеджер + 'files_manager': `${baseUrl}/apps/files/?dir=/&openfile=${encodedFileName}` }; // Убираем null значения @@ -102,7 +109,8 @@ function createEditUrls(baseEditUrl, recordId, fileName, fileId = 662) { return { all: urls, - recommended: urls.correct_path + // РЕДИРЕКТ через нашу страницу - лучший способ (обходит CSRF) + recommended: urls.redirect_to_nextcloud || urls.files_editing_auto || urls.files_editing || urls.collabora_editor }; } @@ -443,6 +451,12 @@ function openInNewWindow(editUrl) { console.log('Opened Nextcloud editor in new window'); } +// Алиас функции для обратной совместимости +function editInNextcloud(recordId, fileName) { + console.log('📝 editInNextcloud called (alias)'); + return openNextcloudEditor(recordId, fileName); +} + // Автоматическое подключение при загрузке страницы $(document).ready(function() { console.log('Nextcloud Editor integration loaded'); diff --git a/crm_extensions/simple_editor.php b/crm_extensions/simple_editor.php new file mode 100644 index 00000000..55b649fd --- /dev/null +++ b/crm_extensions/simple_editor.php @@ -0,0 +1,93 @@ +getFileId($remotePath); + +?> + + + + Редактирование документа + + + + +

Редактирование документа:

+ +
+

📝 Варианты редактирования:

+ +

1. Collabora Online (рекомендуется)

+ + Открыть в Collabora + + +

2. Только просмотр

+ + Просмотр в Nextcloud + + +

3. Скачать и редактировать локально

+ + Скачать файл + + +

4. Google Docs (если файл публично доступен)

+ + Открыть в Google Docs + + +

5. Microsoft Office Online

+ + Открыть в Office Online + +
+ +
+

ℹ️ Информация о файле:

+

Файл:

+

ID записи:

+

File ID:

+

Путь:

+
+ + + + diff --git a/layouts/v7/lib/nextcloud-editor.js b/layouts/v7/lib/nextcloud-editor.js index a7fe34b1..1a612b14 100644 --- a/layouts/v7/lib/nextcloud-editor.js +++ b/layouts/v7/lib/nextcloud-editor.js @@ -1,60 +1,442 @@ /** - * Nextcloud Editor Integration - * Функция для редактирования документов в Nextcloud + * Nextcloud Editor Integration JavaScript + * JavaScript для интеграции редактора документов Nextcloud */ -function editInNextcloud(recordId, fileName) { - console.log('Opening file in Nextcloud:', recordId, fileName); +/** + * Открытие редактора Nextcloud для документа + */ +function openNextcloudEditor(recordId, fileName) { + console.log('🚀 NEXTCLOUD EDITOR: Function called!', recordId, fileName); + + // ПРОСТОЕ РЕШЕНИЕ - используем промежуточную страницу для редиректа! + const redirectUrl = `/crm_extensions/file_storage/api/open_file.php?recordId=${recordId}&fileName=${encodeURIComponent(fileName)}`; - // Проверяем расширение - const ext = fileName.split('.').pop().toLowerCase(); - if (!['docx', 'xlsx', 'pptx'].includes(ext)) { - alert('Файл ' + fileName + ' не поддерживается для редактирования. Поддерживаются: docx, xlsx, pptx'); - return; + console.log('🎯 Opening editor via redirect:', redirectUrl); + + // Открываем редактор в новом окне через промежуточную страницу + const win = window.open(redirectUrl, 'nextcloud_editor', 'width=1200,height=800,scrollbars=yes,resizable=yes'); + + if (win) { + console.log('✅ Editor opened successfully'); + alert('✅ Редактор открыт! Файл: ' + fileName); + } else { + console.log('❌ Failed to open editor window - popup blocked'); + alert('❌ Не удалось открыть редактор. Проверьте блокировку всплывающих окон.'); } +} + +function testSimpleAPI(recordId, fileName) { + console.log('🧪 Testing simple API...', recordId, fileName); - // Отправляем запрос к нашему API - const apiUrl = `crm_extensions/nextcloud_api.php?record=${encodeURIComponent(recordId)}&fileName=${encodeURIComponent(fileName)}`; - fetch(apiUrl, { - method: 'GET' - }) - .then(response => { - console.log('Response status:', response.status); - return response.json(); - }) - .then(json => { - console.log('JSON response:', json); - if (json.success && json.data && json.data.urls) { - // Сначала пробуем файловый менеджер, потом прямой редактор - const filesManagerUrl = json.data.urls.files_manager; - const collaboraUrl = json.data.urls.collabora_id; - const onlyofficeUrl = json.data.urls.onlyoffice_id; - - if (filesManagerUrl) { - console.log('Opening files manager:', filesManagerUrl); - window.open(filesManagerUrl, '_blank'); - } else if (collaboraUrl) { - console.log('Opening Collabora:', collaboraUrl); - window.open(collaboraUrl, '_blank'); - } else if (onlyofficeUrl) { - console.log('Opening OnlyOffice:', onlyofficeUrl); - window.open(onlyofficeUrl, '_blank'); - } else { - console.error('No valid URLs found'); - alert('Ошибка: Не удалось получить URL для редактирования'); - } - } else { - console.error('Invalid response structure:', json); - alert('Ошибка: ' + (json.error || 'Не удалось получить URL для редактирования. Проверьте консоль для деталей.')); + // Пропускаем простой API и сразу идем к основному + console.log('🎯 Skipping simple API, going to main API...'); + callMainAPI(recordId, fileName); +} + +function createEditUrls(baseEditUrl, recordId, fileName, fileId = 662) { + console.log('🔗 Creating edit URLs in JavaScript...', { fileId, fileName }); + + // Извлекаем базовый URL из базовой ссылки + const baseUrl = 'https://office.clientright.ru:8443'; + const encodedFileName = encodeURIComponent(fileName); + const filePath = `/crm/crm2/CRM_Active_Files/Documents/${recordId}/${encodedFileName}`; + + // Токен для RichDocuments (из настроек Nextcloud) + const richDocumentsToken = '1sanuq71b3n4fm1ldkbb'; + + const urls = { + // ЛУЧШИЙ СПОСОБ! - редирект через нашу промежуточную страницу (БЕЗ CSRF!) + 'redirect_to_nextcloud': fileId ? `/crm_extensions/file_storage/api/open_file.php?fileId=${fileId}&fileName=${encodedFileName}&recordId=${recordId}` : null, + // РАБОЧИЙ СПОСОБ! - прямая ссылка на Nextcloud + 'files_editing_auto': fileId ? `${baseUrl}/apps/files/files/${fileId}?dir=/&editing=true&openfile=true` : null, + // Вариант без автоматического редактирования + 'files_editing': fileId ? `${baseUrl}/apps/files/files/${fileId}?dir=/&editing=false&openfile=true` : null, + // Collabora Editor + 'collabora_editor': fileId ? `${baseUrl}/index.php/apps/richdocuments/index?fileId=${fileId}` : null, + // OnlyOffice Editor + 'onlyoffice_editor': fileId ? `${baseUrl}/apps/onlyoffice?fileId=${fileId}` : null, + // Прямое открытие файла + 'files_direct': fileId ? `${baseUrl}/apps/files/files/${fileId}` : `${baseUrl}/apps/files/?dir=/&openfile=${encodedFileName}`, + // Файловый менеджер + 'files_manager': `${baseUrl}/apps/files/?dir=/&openfile=${encodedFileName}` + }; + + // Убираем null значения + Object.keys(urls).forEach(key => { + if (urls[key] === null) { + delete urls[key]; + } + }); + + return { + all: urls, + // РЕДИРЕКТ через нашу страницу - лучший способ (обходит CSRF) + recommended: urls.redirect_to_nextcloud || urls.files_editing_auto || urls.files_editing || urls.collabora_editor + }; +} + +function getEditUrls(recordId, fileName, simpleData) { + console.log('🔗 Getting edit URLs...'); + + $.ajax({ + url: '/crm_extensions/file_storage/api/get_edit_urls.php', + method: 'GET', + data: { + record: recordId, + fileName: fileName + }, + dataType: 'json', + success: function(response) { + console.log('✅ Edit URLs received:', response); + + if (response.success) { + // Пробуем открыть рекомендуемый URL + const recommendedUrl = response.data.urls[response.data.recommended]; + console.log('🎯 Trying recommended URL:', recommendedUrl); + + openEditor(recommendedUrl, { + ...simpleData, + urls: response.data.urls, + recommended: response.data.recommended + }); + } else { + // Если не получилось, используем простой API + openEditor(simpleData.edit_url, simpleData); + } + }, + error: function(xhr, status, error) { + console.error('❌ Failed to get edit URLs:', error); + // Если не получилось, используем простой API + openEditor(simpleData.edit_url, simpleData); } - }) - .catch(error => { - console.error('Error:', error); - alert('Ошибка: ' + error.message); }); } -// Делаем функцию глобальной для доступа из шаблонов -window.editInNextcloud = editInNextcloud; +function callMainAPI(recordId, fileName) { + console.log('🎯 Calling main API...', recordId, fileName); + // Показываем прогресс + if (typeof app !== 'undefined' && app.helper && app.helper.showProgress) { + app.helper.showProgress({ + message: 'Подготовка файла к редактированию...' + }); + } + // Вызываем ПРАВИЛЬНЫЙ API для подготовки файла + $.ajax({ + url: '/index.php?module=Documents&action=NcPrepareEdit', + method: 'GET', + data: { + record: recordId, + fileName: fileName + }, + dataType: 'json', + success: function(response) { + console.log('📡 API Response:', response); + + // Скрываем прогресс + if (typeof app !== 'undefined' && app.helper && app.helper.hideProgress) { + app.helper.hideProgress(); + } + + if (response.success) { + console.log('✅ File prepared successfully'); + + // Открываем редактор + openEditor(response.data.edit_url, response.data); + + } else { + console.error('❌ API Error:', response.error); + showError('Ошибка подготовки файла: ' + response.error); + } + }, + error: function(xhr, status, error) { + console.error('❌ AJAX Error:', error); + console.error('❌ Status:', status); + console.error('❌ Response:', xhr.responseText); + console.error('❌ Status Code:', xhr.status); + + // Скрываем прогресс + if (typeof app !== 'undefined' && app.helper && app.helper.hideProgress) { + app.helper.hideProgress(); + } + + // Показываем подробную ошибку + let errorMessage = 'Ошибка подключения к серверу: ' + error; + if (xhr.responseText) { + errorMessage += '\n\nОтвет сервера:\n' + xhr.responseText; + } + + showError(errorMessage); + } + }); +} + +// Функция для открытия редактора +function openEditor(editUrl, fileData) { + console.log('🎯 Opening editor with URL:', editUrl); + console.log('📋 All available URLs:', fileData.urls); + + // Открываем редактор в новом окне + var win = window.open(editUrl, 'nextcloud_editor', 'width=1200,height=800,scrollbars=yes,resizable=yes'); + + if (win) { + console.log('✅ Editor opened successfully'); + + // Показываем уведомление об успехе + if (typeof app !== 'undefined' && app.helper && app.helper.showSuccessNotification) { + app.helper.showSuccessNotification({ + message: 'Редактор открыт! Файл: ' + fileData.file_name + }); + } else { + alert('✅ Редактор открыт! Файл: ' + fileData.file_name); + } + + // Показываем информацию о файле + showFileInfo(fileData); + + } else { + console.log('❌ Failed to open editor window - popup blocked or error'); + console.log('📋 Showing modal with alternative URLs'); + + // Показываем модальное окно с альтернативными вариантами + showModalWithUrls(editUrl, fileData); + } +} + +// Функция для отображения информации о файле +function showFileInfo(fileData) { + // Проверяем, есть ли нужные поля в fileData + var location = 'Неизвестно'; + var nextcloudPath = 'Не указан'; + var status = 'Не указан'; + + if (fileData.file_location && fileData.file_location.type) { + location = fileData.file_location.type === 's3' ? 'S3 хранилище' : 'Локальное хранилище'; + } + + if (fileData.nextcloud_path) { + nextcloudPath = fileData.nextcloud_path; + } + + if (fileData.message) { + status = fileData.message; + } + + var infoHtml = ` +
+
Информация о файле
+

Файл: ${fileData.file_name}

+

Расположение: ${location}

+

Путь в Nextcloud: ${nextcloudPath}

+

Статус: ${status}

+
+ `; + + // Если есть альтернативные URL, добавляем их + if (fileData.urls) { + infoHtml += ` +
+
Альтернативные способы открытия:
+
+ `; + + Object.keys(fileData.urls).forEach(function(key) { + const label = key.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()); + const isRecommended = key === fileData.recommended; + const btnClass = isRecommended ? 'btn-success' : 'btn-default'; + const icon = isRecommended ? 'fa-star' : 'fa-external-link'; + + infoHtml += ` + + ${label}${isRecommended ? ' (рекомендуется)' : ''} + + `; + }); + + infoHtml += ` +
+
+ `; + } + + // Добавляем информацию в модальное окно или показываем отдельно + if ($('#nextcloudEditModal').length) { + $('#nextcloudEditModal .modal-body').prepend(infoHtml); + } else { + // Создаём временное уведомление + var notification = $('
' + infoHtml + '
'); + $('body').append(notification); + + // Автоматически скрываем через 5 секунд + setTimeout(function() { + notification.fadeOut(function() { + notification.remove(); + }); + }, 5000); + } +} + +// Функция для отображения ошибок +function showError(message) { + console.error('🚨 Error:', message); + + if (typeof app !== 'undefined' && app.helper && app.helper.showErrorNotification) { + app.helper.showErrorNotification({ + message: message + }); + } else { + alert('❌ Ошибка: ' + message); + } +} + +// Функция для показа модального окна с URL +function showModalWithUrls(editUrl, fileData) { + console.log('📋 Showing modal with URLs for file:', fileData.file_name); + + if (fileData.urls) { + // Используем существующую функцию showEditOptions + showEditOptions(fileData.urls, fileData.file_name, fileData.record_id); + } else { + // Если нет альтернативных URL, показываем ошибку + showError('Не удалось открыть редактор. Попробуйте открыть файл вручную в Nextcloud.'); + } +} + +/** + * Показ вариантов открытия файла + */ +function showEditOptions(urls, fileName, recordId) { + console.log('🎯 Showing edit options for:', fileName); + console.log('📋 Available URLs:', urls); + + var buttonsHtml = ''; + + // Если urls - это объект (новый формат) + if (typeof urls === 'object' && !Array.isArray(urls)) { + Object.keys(urls).forEach(function(key, index) { + const label = key.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()); + const url = urls[key]; + const isRecommended = key === 'correct_path'; + const btnClass = isRecommended ? 'btn-success' : 'btn-primary'; + const icon = isRecommended ? 'fa-star' : 'fa-external-link'; + + buttonsHtml += ` + + ${label}${isRecommended ? ' (рекомендуется)' : ''} + + `; + }); + } else { + // Старый формат - массив URL + var labels = [ + 'С параметром openfile', + 'С action=edit', + 'С edit=true', + 'Через RichDocuments', + 'Через OnlyOffice' + ]; + + var icons = ['fa-file', 'fa-edit', 'fa-pencil', 'fa-file-text', 'fa-file-word-o']; + var colors = ['btn-primary', 'btn-success', 'btn-info', 'btn-warning', 'btn-danger']; + + urls.forEach(function(url, index) { + buttonsHtml += ` + + ${labels[index]} + + `; + }); + } + + var modalHtml = ` + + `; + + // Удаляем старое модальное окно + $('#nextcloudEditModal').remove(); + + // Добавляем новое + $('body').append(modalHtml); + $('#nextcloudEditModal').modal('show'); +} + +/** + * Синхронизация изменений файла (заглушка) + */ +function syncFileChanges(recordId, fileName) { + console.log('Syncing file changes for:', recordId, fileName); + + if (typeof app !== 'undefined' && app.helper && app.helper.showSuccessNotification) { + app.helper.showSuccessNotification({ + message: 'Изменения синхронизированы!' + }); + } else { + alert('✅ Изменения синхронизированы!'); + } +} + +/** + * Открытие редактора в новом окне + */ +function openInNewWindow(editUrl) { + window.open(editUrl, 'nextcloud_editor', 'width=1200,height=800,scrollbars=yes,resizable=yes,toolbar=no,location=no'); + console.log('Opened Nextcloud editor in new window'); +} + +// Алиас функции для обратной совместимости +function editInNextcloud(recordId, fileName) { + console.log('📝 editInNextcloud called (alias)'); + return openNextcloudEditor(recordId, fileName); +} + +// Автоматическое подключение при загрузке страницы +$(document).ready(function() { + console.log('Nextcloud Editor integration loaded'); + + // Добавляем CSS стили для модального окна + if (!$('#nextcloud-editor-styles').length) { + $('