Контекстное меню в диалоге с деревом связанных документов.

9 31

В системе DIRECTUM передаточные учетные документы формируются в комплект.

Чтобы просмотреть список всех связанных документов, входящих в комплект, необходимо нажать на кнопку "Комплект" на ленте карточки "Передаточные учетные документы":

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

Так как для отображения диалога используется HTML, по нажатию правой кнопки мыши открывается контекстное меню HTML-страницы:

Поэтому появилась необходимость реализовать работу контекстного меню в соответствии с действиями, расположенными на карточке документа:

Для этого в исходный код добавляется JavaScript для обработки нажатия и VBScript для подключения к базе (файл InvoiceTree.html):

<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Цепочка документов</title>
	<link rel="stylesheet" href="InvoiceTree.css">
	<link rel="stylesheet" href="SMDCalculation/style.css" type="text/css" charset="utf-8" />
    <script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
    <script language=Javascript>
$(function(){
  $('a').click(function(e)  {
    //ловим элемент, по которому кликнули
    var t = e.target || e.srcElement;
    //получаем название тега
    var elm_name = t.tagName.toLowerCase();
    //если это инпут - ничего не делаем
    if(elm_name != 'a')  { return false; }
  });
  $('body').click(function(e)  {
    $('.context-menu').remove();
  });
});

function print(docId){
  executeVBAction(docId, "Просмотр");
}

function opencard(docId){
  executeVBAction(docId, "");
}

function sign(docId){
  executeVBAction(docId, "SignObjectAction");
}

function attach(docId){
  executeVBAction(docId, "Search_ATTACHED_TO_TASK_SEARCH");
}

document.oncontextmenu = function (){return false};

// Вешаем слушатель события нажатие кнопок мыши для всего документа:
$(document).mousedown(function(event) {  
    // Убираем css класс selected-html-element у абсолютно всех элементов на странице с помощью селектора:
    $('*').removeClass('selected-html-element');
    // Проверяем нажата ли именно правая кнопка мыши:
    if (event.which === 3)  {
        // Удаляем предыдущие вызванное контекстное меню:
        $('.context-menu').remove();
        // ловим элемент, по которому кликнули
        var t = event.target || event.srcElement;
        // получаем название тега
        var elm_name = t.tagName.toLowerCase();
        if(elm_name != 'a')  { return false; }

        // Найти ИД документа
        var hrefs = t.href.split("=");
        var docId = hrefs[hrefs.length - 1];
        
        // Добавляем класс selected-html-element что бы наглядно показать на чем именно мы кликнули (исключительно для тестирования):
        var target = $(event.target);
        target.addClass('selected-html-element');
        // Создаем меню:
        var menu = $('<div class="context-menu" />');
        menu.css({
            left: event.pageX+'px', // Задаем позицию меню на X
            top: event.pageY+'px' // Задаем позицию меню по Y
        });
        menu.appendTo('body'); // Присоединяем наше меню к body документа:
        menu.append( // Добавляем пункты меню:
            $('<ul/>').append('<li><a href="#" onclick="print(' + docId + ');">Печатная форма</a></li>') 
                    .append('<li><a href="#" onclick="opencard(' + docId + ');">Открыть карточку</a></li>')
                    .append('<li><a href="#" onclick="sign(' + docId + ');">Подписать</a></li>')
                    .append('<li><a href="#" onclick="attach(' + docId + ');">Вложено в задачи</a></li>') 
            );
        menu.show('fast'); // Показываем меню с небольшим стандартным эффектом jQuery. Как раз очень хорошо подходит для меню
    }
});
    </script>
    <script language=vbScript>
sub executeVBAction(docId, actionName)
  db_name = "DIRECTUM"
  set LP = CreateObject("SBLogon.LoginPoint")
  set App = LP.GetApplication("systemcode=" + db_name)
  set Doc = App.EDocumentFactory.GetObjectByID(docId)
  if actionName = "" then
  	Doc.Form.ShowModal
  else
  	set action = Doc.Form.Actions.FindAction(actionName)
  	action.Execute
  end if
end sub
    </script>
</head>
<body>
<div id="document-tree">
<h4><a href="http://directum.npo-comp.ru/doc.asp?sys=DIRECTUM&amp;id=127528">!!Вх. УПД № 21 от 19.11.2016 от ООО Березка</a></h4>
<ul>
<ul>
<li><span><a href="http://directum.npo-comp.ru/doc.asp?sys=DIRECTUM&amp;id=127529">Корр. УПД № 22 от 24.11.2016 к вх. УПД №21 от 19.11.2016 с учетом испр. № от  от ООО Березка</a></span><ul>
<ul>
<li><span><a href="http://directum.npo-comp.ru/doc.asp?sys=DIRECTUM&amp;id=127530">Испр. № 33 от 30.11.2016 к корр. УПД № 22 от 24.11.2016 к вх. УПД №21 от 19.11.2016 с учетом испр. № от от ООО Березка</a></span><ul>
</ul>
</li>
</ul>
</ul>
</li>
</ul>
<ul>
<li><span><a href="http://directum.npo-comp.ru/doc.asp?sys=DIRECTUM&amp;id=128914">Корр. УПД № 22 от 24.11.2016 к вх. УПД №21 от 19.11.2016 от ООО Березка</a></span><ul>
<ul>
<li><span><a href="http://directum.npo-comp.ru/doc.asp?sys=DIRECTUM&amp;id=128916" class="current">Испр. № 33 от 30.11.2016 к корр. УПД № 22 от 24.11.2016 к вх. УПД №21 от 19.11.2016 от ООО Березка</a></span><ul>
</ul>
</li>
</ul>
</ul>
</li>
</ul>
</ul>
<h4><a href="http://directum.npo-comp.ru/doc.asp?sys=DIRECTUM&amp;id=128912">Вх. УПД № 21 от 19.11.2016 от ООО Березка</a></h4>
<ul>
<ul>
<li><span><a href="http://directum.npo-comp.ru/doc.asp?sys=DIRECTUM&amp;id=128914">Корр. УПД № 22 от 24.11.2016 к вх. УПД №21 от 19.11.2016 от ООО Березка</a></span><ul>
<ul>
<li><span><a href="http://directum.npo-comp.ru/doc.asp?sys=DIRECTUM&amp;id=128916" class="current">Испр. № 33 от 30.11.2016 к корр. УПД № 22 от 24.11.2016 к вх. УПД №21 от 19.11.2016 от ООО Березка</a></span><ul>
</ul>
</li>
</ul>
</ul>
</li>
</ul>
</ul>
</div>
</body>
</html>

Стили подгружаются из файла InvoiceTree.css:


  /* общий стиль */
    body {font-family: Arial, Tahoma, sans-serif; margin: 2em; font-size: 62.5%;}
/* Класс контекстного меню: */
.context-menu {
    position: absolute; /* Задаем абсолютное позиционирование для нашего меню */
    /*display: none; /* Изначально не показываем его */
    background-color: #CCC; /* Цвет фона меню */
    border: 1px solid #333; /* Граница */

    /* Немного красивостей. Добавляем тень для нашего меню, что бы отобразить его слегка выше остальных элементов страницы: */
    -moz-box-shadow: -5px 2px 10px rgba(0,0,0,0.5); /* Для Firefox */
    -webkit-box-shadow: -5px 2px 10px rgba(0,0,0,0.5); /* Для Safari и Chrome */
    box-shadow: -5px 2px 10px rgba(0,0,0,0.5); /* Параметры тени */
}

/* Добавляем стили для списка которые будет находиться внутри меню и, собственно, содержать его пункты: */
.context-menu ul { list-style: none; margin: 0; padding: 0; }
.context-menu ul li { margin: 0; padding: 0; background-color: #FFF; display: block; }
/* Стили для ссылок пунктов меню: */
.context-menu ul li a { color: #333; text-decoration: none; font-size: 12px; display: block; padding: 5px; }
.context-menu ul li a:hover { background-color: #CCC; }
    a {
     text-decoration: none;
     outline: none;
    }
    a:link {
     color: #0066cc;  
    } 
    /* a:visited {color: #00cc63; } */  
    a:hover {
     text-decoration: underline;
    }
    a:active, a:focus {
     color: #666; 
     background-color: #f4f4f4; 
    }
    a.current {
     color: black;
     font-weight: bold;
    }
  
    /* Дерево многоуровневое
    -------------------------------- */
    #document-tree {
     width: 100%; /* блок под дерево */
     border: solid; /* границы блока */
     border-color: silver gray gray silver;
     border-width: 2px;
     padding: 0 0 1em 0; /* нижний отступ */
     font-size: 1.3em;
    }
     span { /* обертка пункта */
       text-decoration: none;
       display: block; /* растянем до правого края блока */
       margin: 0 0 0 1.2em;      
       background-color: transparent;
       border: solid silver; /* цвет линий */  
       border-width: 0 0 1px 1px; /* границы: низ и лево */
     }
      span a {/* тест элемента дерева */
        display: block; 
        position: relative;
        top: .95em; /* смещаем узел на середину линии */
        background-color: #fff; /* закраска в цвет фона обязательна иначе будет видно линию */
        margin: 0 0 .2em .7em; /* делаем промежуток между узлами, отодвигаем левее  */
        padding: 0 0.3em; /* небольшой отступ от линии */
       }
      h4 {/* заголовок дерева */
       font-size: 1em;
       font-weight: bold;
       margin: 0;
       padding: 0 .25em;
       border-bottom: 1px solid silver;
      }

     h4 a {
       display: block;
     }
     ul, li {
       list-style-image:none;
       list-style-position:outside;
       list-style-type:none;
       margin:0;
       padding:0;
     }
       ul li {
        line-height: 1.2em;
       }
        ul li ul {}
          ul li ul li {
           margin: 0 0 0 1.2em;
           border-left: 0px; /* нет вертикальной линии между узлами */
          }
    /* IE 6 Fixup */
    * html #document-tree * { height: 1%;}

В нашей системе файлы выгружаются во временную папку в момент вызова диалога.

Состав папки выглядит следующим образом:

Состав папки js:

В папке js хранится стандартная библиотека jquery-1.6.2.min.js.

Набор кнопок в выпадающем меню можно изменять по своему усмотрению в соответствии с действиями карточки документа.

9
Авторизуйтесь, чтобы оценить материал.
4
Александр Чугунов

Чего-то я не понял зачем здесь VBScript. HTML же можно поместить в диалог, например. И работать с Application.
В IE через ActiveX можно прямо из JS подключиться к Directum. Какие преимущества у VBScript? 
Когда делал меню в веб-контроле связанных документов (Тут есть скриншот), то открытие карточки документа и другие действия делал примерно так (выдержка из кода):

application = window.external.Form.View.Component.Application;

function openCard(documentId) {
    try {
      var EDoc = application.EDocumentFactory.GetObjectByID(documentId);
      EDoc.Form.ShowModal();
      EDoc.LeaveEditMode();
      delete EDoc;
    } catch (e) {
      alert(e.description);
    }
    return false;
  }

"В нашей системе файлы выгружаются во временную папку в момент вызова диалога." - ну это прилично замедляет. В Вашем случае это не критично, так как по требованию только загружается. Если загружать всегда при открытии, то лучше использовать что-то типа этого. То, что на скриншоте в заявке, я делал на чистом JS, весь шаблон HTML уместился в 400 строк кода (HTML, CSS с иконками в base64, JS, вместе с меню), загрузка содержимого асинхронно (вызов сценария). Так что получилась мгновенная загрузка карточки.

Александр Чугунов: обновлено 27.04.2017 в 10:54
Александр Чугунов

И еще, кстати, не увидел как у Вас обрабатывается показ меню, когда оно не влезает в размер окна (кликнули максимально справа и снизу).
Я про что-то типа этого (если использовать JQuery'вский pageX, то код будет проще):

var mousePosition = {x: e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0), y: e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0)};

var menuLeft = mousePosition.x;
var menuTop = mousePosition.y;

if (menuLeft + menu.offsetWidth > html.offsetWidth) {
menuLeft = html.offsetWidth - menu.offsetWidth;
}
if (menuTop + menu.offsetHeight - html.scrollTop > html.offsetHeight) {
menuTop = html.offsetHeight + html.scrollTop - menu.offsetHeight;
}
menu.style.left = menuLeft + "px";
menu.style.top = menuTop + "px";

 

Александр Чугунов

И как, кстати, получается список документов с учетом прав доступа? Используете поиски? Это же жуть как долго для построения дерева...
Собственно, из-за того, что это очень медленно, я тогда сделал загрузку только 1 уровня, остальное подгружается по требованию при нажатии на "+".

Александр Чугунов: обновлено 27.04.2017 в 11:23
Михаил Тарасов

Размещу ка я тут библиотеку, которую использовал для подобных целей (Само решение до ума не довел, но дело не в библиотеке...)

Основу взял тут и доработал до возможности вызывать суб меню, а так же правильного позиционирования у краёв. 

Прикреплен файл: jquery.contextMenu.js
Прикреплен файл: jquery.contextMenu.css
 

Но, полноценное дублирование контекстного меню, как в системе, в Web'е, скажу я вам, та ещё задачка. 


P.S. В библиотеке нет кода, выводящего именно такое меню для документа. Это требуется писать самому...

Александр Чугунов

Михаил, я эту же библиотеку хотел использовать когда-то=) Но тогда оказалось проще откуда-то скопипастить простейшую менюшку на чистом JS. Для простых задач чистого JS хватает и с ним проще, а вот когда надо что-то серьезное, без библиотек уже никуда.
Интересно как меню сделали в решении Автоклассификаторы, меню и стили доделывали после меня уже после моего ухода...

Михаил Тарасов

Александр, а так там к документам и прочим объектам и не надо специальной библиотеки. Они же в обложке все отображаются. Там работает механизм контекстного меню на ссылках на объекты системы... Это для диалогов, документов и справочникам надо свои костыли изобретать...

Александр Чугунов

Михаил, нет, там свое меню сделали. С возможностью добавлять свои пункты для каждого классификатора, разное для одного или нескольких выделенных документов.

Александр Манохин

Александр, VBScript затем, что он нравится больше))

 
Александр Манохин

>> "В нашей системе файлы выгружаются во временную папку в момент вызова диалога." - ну это прилично замедляет.


По сравнению с отрисовкой - копейки. Можно сделать, чтобы выгружалось только если нет в папке - ибо меняется от ситуации к ситуации только html.

 

 
Александр Манохин

>> И еще, кстати, не увидел как у Вас обрабатывается показ меню, когда оно не влезает в размер окна (кликнули максимально справа и снизу).


Поскольку в релиз не вошло, то и не особо заморачивались с этой проблемой. Теперь будем знать как реализовать, спасибо за решение!

 

Александр Манохин: обновлено 27.04.2017 в 14:04
Александр Манохин: обновлено 27.04.2017 в 14:04
Александр Манохин

>> И как, кстати, получается список документов с учетом прав доступа? Используете поиски? Это же жуть как долго для построения дерева...


Как раз этот отчет для возможности просмотреть полный комплект - даже если на некоторые документы прав нет. просто при попытке обращения к действиям и при попытке перейти по ссылке будет соответствующее предупреждение (билдеровское, разумеется).

Александр Манохин: обновлено 27.04.2017 в 14:04
Александр Чугунов

Александр, еще был вопрос про Application, почему Вы его не использовали, а делали отдельное подключение к базе.

А Вы замеряли что выдаете такие утверждения про скорость работы? Это ж надо с сервера скачать (надеюсь один архив, и не из версии документа через ОМ, потому что это жуть как медленно), сохранить на диск, распаковать, записать обратно на диск. Если сюда еще добавить время на формирование HTML, то получится приличное время. И всё это делается до открытия карточки. А отрисовка - параллельно с открытием.
Вот как я написал, в Вашем случае это не критично, но если при каждом открытии такое делать, то при "пролистывании" справочника будет прилично подтормаживать.

Теперь понятно почему стандартная разработка такая тормознутая, с таким подходом видать и делали, например, в календаре совещаний при каждом чихе загрузку с сервера 400кб HTML. Вот только в тяжелых условиях промышленной эксплуатации не всегда RTT < 1мс, канал 100мбит и SQL не загружен совсем чтобы мгновенно ответить.

Анна Долганова

Зачем качать архив? текст js, css зашит в коде - его просто записывают через WriteFile. Запись 4 файлов происходит за 6 мс

Александр Чугунов

Анна, Вы поставили меня в тупик. Я не знаю, почему я считаю что в функциях нельзя хранить все JS, CSS и тд. Мелкие скрипты я там храню, но вот библиотеки типа JQuery почему-то нет. Может потому что обычно парой файлов не обходится, обычно их десятки, поэтому хочется хранить их в архиве. Вот, например, у меня архив с несколькими десятками файлов библиотек, иконок и т.д. Весит около мегабайта. Что-то в функцию писать не хочется.

Jquery + библиотеки + иконки думаю около 100 кб будут весить для представленного решения в релизном варианте. Календарь совещаний 400кб, всего в 4 раза больше. Зачем там делали отдельную таблицу на SQL и хранят там, если можно и в функцию 400 кб запихнуть? Кэширование у функций есть, есть сравнение изменений при импорте - идеальный вариант, как кажется. По сути любой файл разработки можно в функциях хранить. К тому же, теоретически, из функций даже на диск писать не надо, можно сразу в веб-контрол записывать весь HTML с включенными script и style.
Так что для мелких файлов функции очень хорошо подходят, но вот хранить там библиотеки как-то не хочется, если есть возможность хранить и нормально использовать как-то по другому.

PS 6мс это запись в кэш диска, а не на диск. Записать и сразу считать по сути всегда будет быстро из-за использования кэша.

Александр Чугунов

Александр, еще одно замечание: в JS коде нет, и скорее всего в ISBL тоже не сделали корректировку размера веб-контрола по размеру родительского элемента

window.external.width = window.external.parent.width; 
window.external.height = window.external.parent.height;

Это нужно для ситуаций, когда у пользователя включено масштабирование. Там еще хорошо бы размер шрифта и элементов корректировать чтоб мелким всё слишком не стало. Надо статью по этому поводу чтоль дооформить до конца...

Анна Долганова

Александр, конкретно в данном предлагаемом примере можно было бы сделать обложку - тогда библиотеки будут в системе в архиве, и дополнительных манипуляций на стороне прикладной делать уже не стоит.

Можно в принципе и в строках локализации хранить, и в новых таблицах тексты - смотреть по ситуации. Тут файлов мало, картинок нет - почему бы не зашить в код.

И кстати, у меня получилось 99,5 кб чистого веса для этих файлов :)

Александр Чугунов

Анна, обложка для данного решения выглядит хорошо. Можно, кстати, попробовать по действию открывать IEdmsExplorer с нужной папкой. Только вопрос как передать туда ИД или сам объект (Environment там тот же?). Будет почти как в IE - можно и растянуть на нужный размер, и работа с билдером будет напрямую. Только этот EdmsExplorer, опять же, открывается медленно, но оно того наверно стоит. Если будете пробовать, пожалуйста, отпишитесь. А то чет в такую дождливую погоду всё лень...
Строки локализации имеют ограниченный размер, что не очень удобно.
Ну я чуть-чуть не угадал с размером=)

Так мне кто-нибудь ответит почему в решении, представленном в статье, используется отдельное подключение к системе через VBScript? Почему не используется Application? Пока не будет аргументов, материал, представленный в статье, - это пример как делать не надо. Кто сказал что VBScript будет у всех работать? В некоторых компаниях запрещено даже исполнение JS из непроверенных истоников (поэтому все обложки приходится переносить на веб-сервер, и веб-контролы тоже, и проще их выносить когда они уже были как файлы в кэше и сами работали с билдером, вызывая сценарий/действие, которые возвращали данные, а не билдер формировал часть html и вставлял в шаблон html)
Я не считаю веб-часть как что-то представляющее интерес, потому что любой фронтендщик знает как сделать такую простенькую страницу и свое меню. Это несложно нагуглить и сделать (хотя бы копипастом). Было бы интересно увидеть как правильно размещать веб-контрол и работать из него с билдером.
Уж представители вендора могли бы про это написать, а не публиковать кривой прототип (самое главное зачем? кому-то для аттестации на следующую категорию надо было статью написать?).

Александр Чугунов: обновлено 28.04.2017 в 15:58
Михаил Тарасов

По поводу передачи параметра: Костыльно, но работать должно.

Обложка выгружается в подпапку темпа. Поднятся на пару уровней выше по дереву папок от выгруженной обложки и генерить в эту папку JS файл с нужными данными. А потом подключать его по абсолютному или относительному ( /../..)  пути.

Михаил, ну как вариант, но костыльно и через реестр передавать ИД объекта можно. Хотелось узнать, можно ли нормально всё организовать.

Роман Деменков

Мы у себя через EdmsExplorer модифицировали отчёт - Использование записи справочника.

Роман, а не поделитесь как это всё работает (как в обложку передаете в по какому объекту отчет строить)? А лучше статьей оформите, мне кажется это очень полезный материал. На клабе точно возникали вопросы как открыть IE, передав в него объект системы. А тут замена IE получается нормальная.
Выглядит очень круто=) 

Михаил Тарасов

В данном случае, возможно, передача данных идет вставкой в папку ссылок на объекты.

Михаил, ну это работоспособный вариант, но очень плохой, если только не создавать каждый раз новую папку (или для каждого пользователя). Ведь при таком подходе при F5 у него всё сломается, а вот, например, в отчете использования записи справочника хотелось бы чтобы он просто обновлялся. При F5 window.external.Folder.Params очищается, так что туда ИД объекта не записать... Вот найти бы зацепку. Жаль, что из веб-страницы не обратиться к IEdmsExplorer, ведь у него есть Params...

Роман Деменков

Там всё просто. На статью времени нет пока, к сожалению.

Сделано было года два-три назад, для ручной обработки дублей справочников.

Стандартный отчёт очень долго формируется, так как через Word, а особенно долго ждёт завершения работы оного.

Сделано не очень оптимально для большого кол-ва записей. Используется Angular.js 1.

Сам отчёт практически не модифицирован. Так как он всё собирает во временную таблицу tmpIspAn:

...
  // Получить имя текущего пользователя
  UserName = ПользовательИмя('SQL')
  TableName = Format("[%s].tmpIspAn"; ArrayOf(UserName)) 
...

В самом низу просто добавляем открытие Expliorer вместо Word:

FolderInfo = Folders.ObjectInfo(109903)

Explorer = ServiceFactory.GetExplorer(False)
Explorer.ShowAddressBar = False
Explorer.ShowRibbon = False
Explorer.ShowStatusBar = isHide
Explorer.ShowTree = isHide
Explorer.TreeRootContents = FolderInfo
Explorer.Caption = 'Использование записи справочника'
Explorer.Show
Exit()

У папки указан урл на сервер вебдоступа: http://directum/usage.html

То есть на этот момент у нас все данные об объекте хранятся во временной таблице.

Javascript вызывает сценарий который выдаёт эти данные в JSON:

if (window.external.Folder) {
  var script = window.external.Folder.Application.ScriptFactory.GetObjectByName('RMKUsageReport');
  var data = angular.fromJson(script.Execute());
}
// RMKUsageReport
// Выбираем данные
  Query = Format("select NameVid, REPLACE(REPLACE(NameAn, CHAR(13), ''), CHAR(10), ' ') as NameAn, KodAn, NameRecv from [%s].tmpIspAn
                  order by NameVid, NameAn"; CurrentUserName())
...
// формируем JSON
    sl.Add(Format('{"VidName": "%s", "NameRec": "%s", "KodRec": "%s", "Name": "%s" }'; ArrayOf(VidName; NameRec; KodRec; Name))) 

Потом выводим JSON с помощью Angular всё в Bootstrap CSS шаблон:

    <div class="row" ng-repeat="vid in data">
        <h3>{{vid.VidName}}</h3>
        <div class="col-sm-6" ng-repeat="el in vid.data">
            <a href="" onclick="preventd(e);" ng-click="showCard(vid.VidName, el.KodRec)">{{el.NameRec}}</a>, поле {{el.Name}}
        </div>
    </div>

А функция показа карточки вызывает другой сценарий:

$scope.showCard = function(ref, code) {
        var script = window.external.Folder.Application.ScriptFactory.GetObjectByName('RMKShowCard');
        var objParams = script.Params;
        objParams.Add('VidName', ref);
        objParams.Add('KodRec', code);
        script.Execute();
}
// RMKShowCard

  VidName = GetComponentLaunchParam("VidName"; '')
  Code = GetComponentLaunchParam("KodRec"; '')
  
  if VidName == 'Электронный документ'
    Doc = EDocuments.GetObjectByID(Code)
    Doc.Form.ShowModal
  else
    sql = "select Kod from MBVidAn where Name = '" & VidName & "'"
    RefCode = SQL(sql)
    Ref = References.ReferenceFactory(RefCode).GetObjectByCode(Code)
    Ref.Form.ShowModal
  endif

Для больших объёмов данных скрипт совсем не подходит, так как в IE начинается безумное потребление памяти. Поэтому всё это надо переделать на генерацию готового html на сервере через c#/php.

Плюс варианта с Angular - нет необходимости в серверной части, там статический html/css/js, данные передаются через ScriptFactory, подходит даже сервер гиперссылок.

Поток данных примерно такой: расчёт отчёта -> tmpIspAn, показываем edmsExplorer, onload = загрузка сценария, он забирает данные из tmpIspAn и отдаёт в JS, JS рендерит текст.

Схема понятна, спасибо.

"Для больших объёмов данных скрипт совсем не подходит, так как в IE начинается безумное потребление памяти. Поэтому всё это надо переделать на генерацию готового html на сервере через c#/php."
- можно прямо в SQL-запросе формировать содержимое HTML таблиц с помощью FOR XML. Так не надо париться с экранированием символов (в "формируем JSON" не увидел экран кавычки), не надо использовать никакие библиотеки и промежуточные JSON (соответственно IE не тормозит) и не надо серверную часть делать. Да и вообще всё намного проще и быстрее стало, когда переделал в автоклассификаторе на такую схему работы.

Роман, а зачем вообще была вся эта возня с папками, EdmsExplorer, если не используется главное преимущество обложек - нативное контекстное меню? Можно же было просто сформировать HTML и открыть в браузере, в href прописывать Hyperlink объекта, что по клику открывать объект через обработчик гиперссылок (да, это чуть дольше).

Роман Деменков

Это тестировали как только EdmsExplorer стал доступен в 5.0

Ну и скорость без открытия внешних программ в разы быстрее. Сейчас вообще можно сразу FOR JSON использовать.

Сделали, пользователи стали пользоваться. Большего и не требовалось.

А реализаций может быть множество, когда есть browser.

Роман,
1) IEdmsExplorer был до 5.0
2) IEdmsExplorer у меня на компе открывается в минимум в 2 раза медленнее Chrome и IE (я выше уже писал что IEdmsExplorer медленный жуть). Учитывая что в большинстве случаев у пользователей уже открыт браузер (то есть старт не холодный), то скорость открытия браузера в десяток раз больше открытия IEdmsExplorer. 
3) Вы написали что у Вас IE жрет много памяти когда из JSON заполняет страницу. Так причем тут что FOR JSON появился в 2016 SQL? Нам нужен именно for xml, так как он позволяет обойтись без промежуточных стадий и сделать так, чтобы скрипт работал "Для больших объёмов данных".

Так почему всё-таки не стали делать просто ссылки, чтобы работало нативное контекстное меню?

Роман Деменков

Нет. Александр нам не нужен for xml ) Любое решение может быть сделано различными способами.

Точно в 4.9 уже был, но меню не отключалось вроде. Зато кнопка отчёты была сразу на ленте справочника, а не на дополнительной закладке.

А вот то что у вас он дольше открывается, очень странно. У сотрудников обычно моментально появляется.Если через ссылки всегда будет цепочка: скачивается файл, explorer запускает отдельный процесс isbexec как сопоставление с .isb фалами, isbexec парсит файл и передаёт контроль sbrte, sbrte уже открывает форму с поиском.

В данном же случае у нас объектная модель доступна через window.external и вызовы отрабатывают моментально.

В чём плюс в отличие ссылок через сервер - мгновенное открытие карточек. Особенно помогает если надо открывать не одну, а несколько (например РКК).

Вы можете сделать сравнение (через объектную модель vs isb файлы) и выложить результаты сюда. Будет интересно посмотреть.

 

У нас некоторые пользуются этим вместо поиска по связанным записям. Прям из одной обложки сразу переключаемся по различным справочникам.

Решение было сделано по принципу:

 - простота в обслуживании - нет динамических файлов на сервере, весь код входит на два экрана, при обновлении максимум пять минут на адаптацию отчёта.

 - простота в использовании - пользователям показывается сразу карточка.

И про много записей: это если пользователь делает отчёт по основной нашей организации или по гендиректору. Тысячи и тысячи объектов. Даже Word вариант отчёта может повиснуть.

Роман, 
1) Вы написали что "Для больших объёмов данных скрипт совсем не подходит" - я предложил вариант решения этой проблемы с помощью for xml. То, что Вам это не нужно, потому что у вас не строят отчеты с таким огромным количеством данных, теперь понятно. Я не говорил что это единственный способ реализации. Но для решения проблемы с памятью IE - имхо единственный быстрый, простой и надежный способ.
2) "У сотрудников обычно моментально появляется" - кто появляется? IEdmsExplorer или объект, который открывают по клику на веб-странице? Я говорил что IEdmsExplorer открывается сам по себе долго, там кучка запросов на сервер отправляется и сам он тупит. А про использование ссылок, которые будут обрабатываться обработчиком я выше сразу указал: "да, это чуть дольше". И то, процесс можно попробовать сильно ускорить, не выполняя запрос на сервер, а формируя файл локально в веб-странице (формат-то мы знаем) и скачивая его (я не уверен, что автооткрытие в таком случае сработает, но в принципе должно). По поводу открытия сразу карточек - в гиперссылку можно передавать параметры. То есть гиперссылки (или сразу isb, если получиться) можно делать на запуск сценария, аналогичного Вашему, а он уже откроет карточку нужного объекта (о котором узнает из параметра). Так что, в принципе, можно и без IEdmsExplorer то же самое сделать (чуть-чуть медленнее, да).
3) "Точно в 4.9 уже был, но меню не отключалось вроде" - какое меню не отключалось?

Можно много чего придумать и долго дискутировать и уйти от сути. А суть в том, что вместо ответа на один мой простой вопрос пишется простыня воды или он просто игнорируется. Почему мне не отвечают на вопросы? Вам, Роман, я задал один простой вопрос: почему Вы отказались от нативного контекстного меню? Ведь по нему можно сразу удалять объекты, открывать тело или карточку в зависимости от того, что нужно пользователю, открывать связанные справочники и т.д. Александр вот мне не ответил зачем ему VBScript.

Проверил я теорию с формированием isb-файла прямо на странице, "скачиванием" и автоматическим запуском обработки файла isbexec. В Chrome всё завелось с полпинка, а вот для работы в IE (ну за что нам это мучение?) придется использовать js-библиотеки типа download. Работает мгновенно. 

Вот пример для открытия задачи с ID 123456

<html><head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<script type="text/javascript">
function openCard(id) {
var link = document.createElement('a');
link.download = 'openCard.isb';
link.href = "data:text/plain;charset=utf-8,Version%3DISB7%0D%0ASystemCode%3Ddirectum%0D%0AComponentType%3D9%0D%0AID%3D" + id +"%0D%0AViewCode%3D";
link.click();
}
script>
head>
<body>
<a href="#" onclick="openCard(123456);">Open Task 123456a>
body>html>

ISB-файл для запуска сценария с переданным параметром должен выглядеть примерно так:

Version=ISB7
SystemCode=directum
ComponentType=2
ComponentCode=MyScriptName
ID=
ViewCode=
CustomParam=123456

 

Александр Чугунов: обновлено 06.05.2017 в 16:45

Авторизуйтесь, чтобы написать комментарий