Files
crm.clientright.ru/DOC_TEMPLATE_UX_DESIGN.md
Fedor 01c4fe80b5 chore: snapshot current working tree changes
Save all currently accumulated repository changes as a backup snapshot for Gitea so no local work is lost.
2026-03-26 14:19:01 +03:00

22 KiB
Raw Blame History

🎨 UX ДИЗАЙН: СОЗДАНИЕ И РЕДАКТИРОВАНИЕ ШАБЛОНОВ

🎯 ВОПРОС: ГДЕ РЕДАКТИРОВАТЬ ШАБЛОНЫ?


📋 ВАРИАНТЫ РЕШЕНИЯ

ВАРИАНТ 1: ГИБРИДНЫЙ ПОДХОД (РЕКОМЕНДУЕТСЯ)

Создание шаблона:

  • В CRM интерфейсе
  • Можно создать пустой шаблон или загрузить существующий файл

Редактирование шаблона:

  • Содержимое (DOCX) → в Nextcloud через OnlyOffice
  • Метаданные и маппинг → в CRM интерфейсе

Преимущества:

  • Удобно редактировать DOCX в OnlyOffice (богатый редактор)
  • Метаданные в CRM (логика рядом с данными)
  • Гибкость - можно редактировать где удобно

ВАРИАНТ 2: ТОЛЬКО В NEXTCLOUD

Создание/редактирование:

  • Все в Nextcloud
  • В CRM только настройка маппинга

Недостатки:

  • Нужно переключаться между системами
  • Маппинг отдельно от шаблона

ВАРИАНТ 3: ТОЛЬКО В CRM

Создание/редактирование:

  • Все в CRM
  • Загрузка файла через интерфейс CRM

Недостатки:

  • Нет удобного редактора DOCX в CRM
  • Дублирование файлов (в CRM и Nextcloud)

🏆 РЕКОМЕНДУЕМЫЙ ПОДХОД: ГИБРИДНЫЙ


📝 СЦЕНАРИЙ 1: СОЗДАНИЕ НОВОГО ШАБЛОНА

В CRM интерфейсе:

┌─────────────────────────────────────────────────────────┐
│  Создание шаблона документа                             │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  Название шаблона: [________________]                   │
│                                                         │
│  Модуль: [Project ▼]                                    │
│                                                         │
│  Файл шаблона:                                          │
│  ○ Создать пустой шаблон                                │
│  ○ Загрузить существующий файл                          │
│     [Выбрать файл...]                                   │
│                                                         │
│  Имя файла в Nextcloud: [pretenziya.docx]               │
│                                                         │
│  [Сохранить и настроить маппинг]                        │
│                                                         │
└─────────────────────────────────────────────────────────┘

Что происходит:

  1. Если "Создать пустой шаблон":

    • CRM создает пустой DOCX через PHPWord
    • Загружает в Nextcloud /Templates/pretenziya.docx
    • Создает запись в vtiger_doctemplate
    • Открывает шаблон в OnlyOffice для редактирования
  2. Если "Загрузить существующий файл":

    • Пользователь выбирает файл
    • CRM загружает в Nextcloud /Templates/
    • Создает запись в vtiger_doctemplate
    • Переходит к настройке маппинга

📝 СЦЕНАРИЙ 2: РЕДАКТИРОВАНИЕ ШАБЛОНА

В CRM интерфейсе (детальный вид шаблона):

┌─────────────────────────────────────────────────────────┐
│  Шаблон: Претензия                    [Редактировать]   │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  Модуль: Project                                        │
│  Файл: pretenziya.docx                                  │
│                                                         │
│  [📝 Редактировать содержимое в OnlyOffice]            │
│     → Откроет файл в Nextcloud для редактирования      │
│                                                         │
│  ────────────────────────────────────────────────────  │
│                                                         │
│  Маппинг переменных:                                    │
│                                                         │
│  Переменная шаблона    →    Поле модуля                │
│  ┌─────────────────┐        ┌──────────────────────┐  │
│  │ CLIENT_NAME     │   →    │ $PROJECT_PROJECTNAME$│  │
│  └─────────────────┘        └──────────────────────┘  │
│                                                         │
│  ┌─────────────────┐        ┌──────────────────────┐  │
│  │ DATE            │   →    │ $PROJECT_CREATEDTIME$ │  │
│  └─────────────────┘        └──────────────────────┘  │
│                                                         │
│  [+ Добавить переменную]                                │
│                                                         │
│  ────────────────────────────────────────────────────  │
│                                                         │
│  [💾 Сохранить маппинг]                                 │
│                                                         │
└─────────────────────────────────────────────────────────┘

Кнопка "Редактировать содержимое":

  • Открывает файл в OnlyOffice через Nextcloud
  • Пользователь редактирует DOCX
  • Сохраняет в Nextcloud
  • CRM автоматически подхватывает изменения

🔧 РЕАЛИЗАЦИЯ

1. Создание пустого шаблона

class DocTemplate_Template_Model {
    
    /**
     * Создать пустой шаблон в Nextcloud
     */
    public function createEmptyTemplate($filename) {
        // 1. Создать пустой DOCX через PHPWord
        $phpWord = new \PhpOffice\PhpWord\PhpWord();
        $section = $phpWord->addSection();
        $section->addText('Шаблон документа');
        
        $tempFile = tempnam(sys_get_temp_dir(), 'template_') . '.docx';
        $writer = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007');
        $writer->save($tempFile);
        
        // 2. Загрузить в Nextcloud через WebDAV
        $this->uploadToNextcloud($tempFile, $filename);
        
        // 3. Удалить временный файл
        unlink($tempFile);
        
        return true;
    }
    
    /**
     * Загрузка файла в Nextcloud
     */
    private function uploadToNextcloud($localFile, $filename) {
        $nextcloudUrl = 'https://office.clientright.ru:8443';
        $username = 'admin';
        $password = 'office';
        $path = '/Templates/';
        
        $webdavUrl = $nextcloudUrl . '/remote.php/dav/files/' . 
                     $username . $path . $filename;
        
        $ch = curl_init($webdavUrl);
        curl_setopt($ch, CURLOPT_PUT, true);
        curl_setopt($ch, CURLOPT_INFILE, fopen($localFile, 'r'));
        curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localFile));
        curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        
        curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($httpCode !== 201 && $httpCode !== 204) {
            throw new Exception("Ошибка загрузки в Nextcloud");
        }
    }
}

2. Загрузка существующего файла

class DocTemplate_Edit_View {
    
    public function process(Vtiger_Request $request) {
        if ($request->has('file_upload')) {
            $uploadedFile = $_FILES['template_file'];
            
            // 1. Валидация файла
            if ($uploadedFile['type'] !== 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
                throw new Exception("Только DOCX файлы");
            }
            
            // 2. Загрузить в Nextcloud
            $filename = $request->get('filename');
            $this->uploadToNextcloud($uploadedFile['tmp_name'], $filename);
            
            // 3. Создать запись в CRM
            $templateModel = new DocTemplate_Template_Model();
            $templateModel->set('templatename', $request->get('templatename'));
            $templateModel->set('filename', $filename);
            $templateModel->set('module', $request->get('module'));
            $templateModel->save();
            
            // 4. Редирект на редактирование маппинга
            header("Location: index.php?module=DocTemplate&view=Edit&record=" . $templateModel->getId());
        }
    }
}

3. Редактирование содержимого (открытие в OnlyOffice)

class DocTemplate_EditContent_Action {
    
    public function process(Vtiger_Request $request) {
        $templateId = $request->get('record');
        $template = DocTemplate_Template_Model::getInstanceById($templateId);
        
        // Получить URL для открытия в OnlyOffice
        $nextcloudUrl = 'https://office.clientright.ru:8443';
        $filename = $template->getFilename();
        $path = $template->getNextcloudPath();
        
        // URL для открытия в OnlyOffice
        $onlyOfficeUrl = $nextcloudUrl . '/apps/files/?dir=' . 
                        urlencode($path) . 
                        '&openfile=' . urlencode($filename);
        
        // Или через прямой вызов OnlyOffice
        $onlyOfficeUrl = $nextcloudUrl . '/apps/onlyoffice/' . 
                        urlencode($path . $filename);
        
        header("Location: " . $onlyOfficeUrl);
        exit;
    }
}

4. Интерфейс редактирования маппинга

JavaScript:

DocTemplate = {
    
    /**
     * Показать редактор маппинга
     */
    showMappingEditor: function(templateId, module) {
        // 1. Получить список полей модуля (как PDFMaker)
        AppConnector.request({
            module: 'DocTemplate',
            action: 'GetModuleFields',
            module_name: module
        }).then(function(response) {
            // 2. Показать модальное окно с редактором маппинга
            DocTemplate.showMappingDialog(response.result.fields, templateId);
        });
    },
    
    /**
     * Диалог редактирования маппинга
     */
    showMappingDialog: function(fields, templateId) {
        var html = '<div class="mapping-editor">' +
            '<table class="table">' +
            '<thead><tr><th>Переменная шаблона</th><th>Поле модуля</th><th></th></tr></thead>' +
            '<tbody id="mapping-rows"></tbody>' +
            '</table>' +
            '<button onclick="DocTemplate.addMappingRow()">+ Добавить</button>' +
            '</div>';
        
        // Показать модальное окно
        // При сохранении → вызвать SaveMapping
    },
    
    /**
     * Сохранение маппинга
     */
    saveMapping: function(templateId, mapping) {
        AppConnector.request({
            module: 'DocTemplate',
            action: 'SaveMapping',
            template_id: templateId,
            mapping: JSON.stringify(mapping)
        }).then(function(response) {
            if (response.success) {
                Vtiger_Helper_Js.showPnotify('Маппинг сохранен');
            }
        });
    }
};

🎨 UI КОМПОНЕНТЫ

1. Список шаблонов (List View)

┌─────────────────────────────────────────────────────────┐
│  Шаблоны документов                    [+ Создать]      │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  Название        │ Модуль    │ Файл              │ Действия│
│  ─────────────────────────────────────────────────────  │
│  Претензия       │ Project   │ pretenziya.docx   │ [✏️][👁️]│
│  Исковое заявл. │ Project   │ isk.docx          │ [✏️][👁️]│
│  Соглашение      │ Contacts  │ soglashenie.docx  │ [✏️][👁️]│
│                                                         │
└─────────────────────────────────────────────────────────┘

2. Детальный вид шаблона

┌─────────────────────────────────────────────────────────┐
│  Претензия                          [Редактировать] [×] │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  Модуль: Project                                        │
│  Файл: pretenziya.docx                                  │
│  Путь: /Templates/                                      │
│                                                         │
│  [📝 Редактировать содержимое в OnlyOffice]            │
│                                                         │
│  ────────────────────────────────────────────────────  │
│                                                         │
│  Маппинг переменных:                                    │
│                                                         │
│  ┌──────────────────────────────────────────────────┐  │
│  │ Переменная    │ Поле модуля              │ [×]  │  │
│  ├──────────────────────────────────────────────────┤  │
│  │ CLIENT_NAME   │ $PROJECT_PROJECTNAME$    │ [×]  │  │
│  │ DATE          │ $PROJECT_CREATEDTIME$    │ [×]  │  │
│  │ AMOUNT        │ $PROJECT_CF_1885$        │ [×]  │  │
│  └──────────────────────────────────────────────────┘  │
│                                                         │
│  [+ Добавить переменную]                                │
│                                                         │
│  [💾 Сохранить]                                        │
│                                                         │
└─────────────────────────────────────────────────────────┘

3. Диалог добавления переменной

┌─────────────────────────────────────────────────────────┐
│  Добавить переменную                                    │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  Переменная шаблона:                                    │
│  [CLIENT_NAME________________]                          │
│                                                         │
│  Поле модуля:                                           │
│  [Выбрать поле ▼]                                       │
│    ├─ Прямые поля                                       │
│    │  ├─ $PROJECT_PROJECTNAME$                         │
│    │  ├─ $PROJECT_CREATEDTIME$                         │
│    │  └─ ...                                            │
│    ├─ Связанные модули                                  │
│    │  ├─ $CONTACTS_LASTNAME$                           │
│    │  └─ ...                                            │
│    └─ Функции                                           │
│       ├─ formatDate($PROJECT_CREATEDTIME$)             │
│       └─ ...                                             │
│                                                         │
│  [Отмена] [Добавить]                                    │
│                                                         │
└─────────────────────────────────────────────────────────┘

🔄 АЛЬТЕРНАТИВНЫЙ ПОДХОД: ВСТРОЕННЫЙ РЕДАКТОР

Вариант: Редактирование прямо в CRM

Если нужен встроенный редактор в CRM (без перехода в Nextcloud):

// Использовать OnlyOffice Document Server API
// Встроить редактор в iframe

class DocTemplate_EditContent_View {
    
    public function process(Vtiger_Request $request) {
        $templateId = $request->get('record');
        $template = DocTemplate_Template_Model::getInstanceById($templateId);
        
        // Получить URL для OnlyOffice Document Server
        $onlyOfficeUrl = $this->getOnlyOfficeEditorUrl($template);
        
        $viewer = $this->getViewer($request);
        $viewer->assign('ONLYOFFICE_URL', $onlyOfficeUrl);
        $viewer->assign('TEMPLATE', $template);
        $viewer->view('EditContent.tpl', 'DocTemplate');
    }
}

Template:

<iframe src="{$ONLYOFFICE_URL}" width="100%" height="800px"></iframe>

РЕКОМЕНДАЦИИ

Для создания шаблона:

  1. В CRM интерфейсе
  2. Можно создать пустой или загрузить файл
  3. Автоматическая загрузка в Nextcloud

Для редактирования содержимого:

  1. В Nextcloud через OnlyOffice (богатый редактор)
  2. Кнопка "Редактировать содержимое" открывает в новой вкладке
  3. После сохранения в Nextcloud - изменения сразу доступны

Для редактирования маппинга:

  1. В CRM интерфейсе
  2. Визуальный редактор с выбором полей
  3. Поддержка формата PDFMaker ($MODULE_FIELDNAME$)

🚀 ГОТОВ РЕАЛИЗОВАТЬ!

Какой вариант тебе больше нравится?

  1. Гибридный (содержимое в Nextcloud, маппинг в CRM) - РЕКОМЕНДУЮ
  2. Только в CRM (встроенный редактор)
  3. Только в Nextcloud (маппинг отдельно)