Javascript и 1С. Кросс-платформенное взаимодействие




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

49 Comments

  1. VitaliyCeban

    Еще один интересный приём передачи данных JavaScript -> 1C, работающий только в тонком/толстом клиентах на Windows.

    function call1C()
    {
    var obj = externalForm.ВычислитьКод1СИзJavascript(«Новый Структура»);
    obj.Вставить(«ПолеСтруктуры», «Значение поля стурктуры»);
    externalForm.МетодВызываемыйИз1С(obj);
    }
    
    &НаКлиенте
    Функция ВычислитьКод1СИзJavascript(Код) Экспорт
    
    Возврат Вычислить(Код);
    
    КонецФункции
    
    &НаКлиенте
    Функция МетодВызываемыйИз1С(Данные) Экспорт
    
    Сообщить(Данные.ПолеСтруктуры);
    
    КонецФункции
    

    Показать

    Reply
  2. kote

    Прочитал с большим интересом 🙂 В своё время «подружил» HTML-форму c Flash элементом на нём — с передачей данных туда и обратно.. но потом flash умер и всё как то сошло на нет 🙂

    В общем, управляемые формы уже не мучал в этом отношении.

    Пишите еще. Интересно, насколько можно улучшить UI у 1С с помощью js — фото и видео бы добавить в следующих статьях.. и посмотреть работу таких фреймворков в окне 1С, как Angular/React/.. и т.п.

    Жму руку и буду ждать продолжения..

    Reply
  3. json

    Очень интересная статья. Автору респект за развитие направления по расширению возможностей 1С.

    Не смог понять из описания, где хранится код на жабаскрипте.

    Если я хочу объявить, например, javascript-функцию, то где конкретно я должен прописать ее код?

    Reply
  4. vano-ekt

    ПолеHTMLДокумента ис суксь, ибо ie6 или какой там

    Reply
  5. VitaliyCeban

    (2) kote, Постараюсь написать полезный материал.

    (3) yurii_host, Функции javascript объявляются в HTML документе, между тегами <sc ript> </sc ript>

    Простейший пример https://learn.javascript.ru/hello-world.

    Исходный код HTML документа можно хранить в макете типа ТекстовыйДокумент. Хотя есть и макет типа Документ HTML, с мгновенным просмотром результата изменений, но хранить код в нем не советую, так как конфигуратор портит код, работающий с новыми версиями браузеров.

    Создаете реквизит формы, с типом Строка, переностите его на форму, изменяете тип элемента с Поле ввода на Поле HTML документа. Получаете содержимое макета ТекстовыйДокумент и присваиваете его созданному реквизиту с типом Строка.

    (4) vano-ekt, Нужно указывать мета-тег x-ua-compatible для перевода браузера в Standards mode, тогда документ будет отображаться в режиме версии, установленной на компьютере. Тег присутствует в статье. Проблема реальна, когда сборка Windows на компьютере старая, и установлен IE8, или IE7. Поэтому нужно писать разметку HTML таким образом, чтобы обеспечивать совместимость и с этими браузерами.

    Для решения которое я разрабатываю, я выбрал минимальный порог — IE8. То есть, если хотите чтобы приложение работало, обновите ваш IE6/7 до IE8, так как для поддержки IE7 нужно слишком много костылей. Такой же порог выбрали и разработчики 1С для веб-клиента.

    Надо сделать коллективное обращение в 1С, об отказе использования IE WebContol в толстом/тонком клиентах под Windows, и переход на Webkit, с вшитием его в платформу, то есть чтобы версия Webkit не зависела от того что установлено на компьютере.

    Reply
  6. vandalsvq

    (5) указание совместимости — это лишь костылек, который в полной мере не решит проблему. Большинство современных java- библиотек поддерживаться будут крайне ограниченно или вообще никак (поскольку большинству надо хотя бы IE8+). На текущий момент работу в 1С с java лично для себя немного закрыл, в пользу связки web-приложение + http сервисы. Да есть ряд неудобств, но пережить можно. По крайней мере пока webkit не появится. Хотя тут тоже такой нюанс, пока 1С добавит, пока платформа выйдет, пока займет значимую часть среди пользователей ))))). В общем не скоро будет оное ))))

    Reply
  7. minimajack

    (7) vandalsvq, ХВАТИТ ПУТАТЬ.

    java — никакого отношения к javascript не имеет ВООБЩЕ.

    Reply
  8. json

    (6) logarifm,

    javascript — это не педаль и не костыль. Разработчики из фирмы 1С тоже используют javascript в типовых конфигурациях (БП 2.0, ЗУП). Некоторые вещи 1с-кой не реализуешь (например, предпросмотр при наведении, некоторые виды диаграмм и др.) типовыми средствами. Но применение таких рюшечек повышает привлекательность и удобство интерфейса.

    и еще один факт. Над улучшением возможностей платформы 1С работает только одна фирма 1С, а сообщество javascript — по всему миру. Очевидно, что javascript — развивается интенсивнее.

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

    Reply
  9. VitaliyCeban

    (7) vandalsvq, Указание использовать последний доступный Standards mode решает проблемы. Библиотеки работают, так, как нужно.

    Как я описал выше, проблема действительно присутствует когда у пользователя просто не установлен на компьютере IE8+.

    (6) logarifm, Успокойтесь, отбросьте негатив, попробуйте javascript, весьма вероятно — Вам понравится.

    Reply
  10. vandalsvq

    (8) minimajack, слушай, если я для упрощения печатания написал java (хотя понятно контексту общения о чем идет речь) что теперь на гильотину? Сейчас уже исправить не могу, но сразу говорю, что имел в виду javascript.

    (10) ну вот не знаю, не знаю. Ты это, например, ангулару (1.4) скажи с его директивами вроде ng-if, которые при использовании вываливают 1С на бок. Тестил правда всего на нескольких релизах (8.3.6.2ххх, 8.3.5.ххх — не помню точно), но так и было. На компе стоит ie «припоследнейший», вот винда только 7-я, но она то не при чем? Кстати эти же странички прекрасно работают в ie (правда как всегда для оформления в css приходится хаки использовать), про гугл и сафари молчу, там понятно что все путем. Так что, по чем купил, по тому и отдаю.

    Готов предоставить для тестирования код.

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

    Reply
  11. tunesoft

    Интересно, но всё это неактуально для мобильного приложения на 1С 🙁

    Reply
  12. Makushimo

    Наконец-то появляются статьи на тему использования html в 1C.

    Автор, спасибо

    Вопрос, на который не могу найти ответ. Может подскажете

    Как в 1С в поле html документа сделать раскрывающийся текст ?

    ну вот как на этом сайте цитаты кода 1С отображаются:

    небольшой спойлер, нажимаешь на «показать» или на заголовок спойлера и разворачивается весь текст внутри.

    Reply
  13. kvovka

    (12) tunesoft, вот именно. Ждем, когда заработает на мобильной платформе.

    Reply
  14. iliabvf

    Большое спасибо! Как раз была идея полностью заменить интерфейс Такси на дизайнерский из html + css + js.

    Как заметили выше, с мобильным приложением все хуже.

    Буду ждать продолжения.

    Reply
  15. vandalsvq

    (13) Makushimo, jQuery тебе в помощь. Там есть метод show смотри в его сторону.

    В html будет примерно так

    // HTML
    <h1 id=’blockctrl’>Показать</h1>
    <div id=’hideblock’ style=’display:none’>Тут содержимое блока</div>
    
    // JS
    $(«#blockctrl»).click(
    function() {
    $(«#hideblock»).show(«slow»);
    }
    );

    Показать

    Reply
  16. kote

    (5)

    Надо сделать коллективное обращение в 1С, об отказе использования IE WebContol в толстом/тонком клиентах под Windows, и переход на Webkit, с вшитием его в платформу, то есть чтобы версия Webkit не зависела от того что установлено на компьютере.

    .. и более того — учитывая сколько геморроя.. не СКОЛЬКО ГЕМОРРОЯ доставляет web-клиент, когда у пользователей постоянно обновляется Хром/Фаерфокс.. может, вообще стоит выпустить СВОЮ СБОРКУ хрома/фаерфокса — которая будет гарантированно работать с 1С через web?

    Ведь загвоздка, на самом деле — хоть тонкий клиент и весит меньше, чем дистрибутив броузера — проблема в правах на установку и зависимости тонкого клиента от версии платформы на сервере.. Ну сделали бы как то — вариантов море — например, тонкий клиент, портабельный/не требующий установки — распаковал и работай.. или обновление чтобы не требовало прав на установку ПО.. или вообще — чтоб тонкий клиент не требовал соответствия версии сервера и своей (т.е. по сути специализированный такой броузер базы 1С)..

    Reply
  17. unpete

    (5)

    Надо сделать коллективное обращение в 1С, об отказе использования IE WebContol

    Подобные обращения писались многократно. Цитирую дословно ответ С. Нуралиева с весеннего партнерского семинара 2015 года: «Это сложно и очень опасно».

    и переход на Webkit

    Лучше, не базовый Webkit, а Blink с движком V8 (Chromium) — поддержка ES6-ES7 там намного лучше. Например, Object.Observe() или ServiseWorkers работают только в V8. В других javascript движках еще даже не анонсированы.

    (7) vandalsvq,

    указание совместимости — это лишь костылек, который в полной мере не решит проблему

    Проблему подтверждаю. Платформа 1С аварийно завершает работу при нетривиальных манипуляциях с DOM внутри поля HTMLДокумента.

    (6) logarifm,

    Так почему продолжаем стонать и упорно лезть на кактус, работайте на других системах

    Платформа 1С содержит гениальные объекты данных. Про регистр, документ, справочник и ссылочную типизацию можно говорить только в превосходной степени.

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

    почему не стать одним из разработчиков

    Так и поступили. См. metadata.js

    Reply
  18. unpete

    (12) tunesoft, (14) kvovka,

    Ждем, когда заработает на мобильной платформе

    Два вопроса:

    • Можно пример задачи для которой из мобильной платформы нужен доступ к браузеру?
    • Почему бы эту задачу не решить прямо в браузере?
    Reply
  19. olbu

    открываю под 8.2 обычное приложение вот это <Окно документа>.funcName(funcArgs);, у меня вываливается ошибка

    {Форма.Форма.Форма(153)}: Метод объекта не обнаружен (fff)

    Браузер.fff(«ГГГГГ»);

    получается в моем случае не видно функции fff…

    <script>

    function fff(M) {alert(M);}

    </script>

    Reply
  20. VitaliyCeban

    (20) olbu, Загрузите обработку на файловый хостинг, могу посмотреть в чём проблема. И напишите версию IE, установленную на компьютере. А также, через какой клиент запускаете.

    Reply
  21. kote

    for all, (18) unpete,

    Всем рекомендую посмотреть на metadata.js — из 18 поста.. И задумка и исполнение на высоте. Правда, не бесплатно для коммерческого использования — но посмотреть стоит.

    Reply
  22. unpete

    (1) Ремарка: события на вебстранице возникают асинхронно, форма 1С, в общем случае, может какие-то из виртуальных кликов пропустить. Тип переменной interactionVariable лучше сделать строкой и не просто присваивать, а дописывать в неё json очередного сообщения. На стороне формы 1С реализовать очередь, в которую складывать элементы массива из interactionVariable и последовательно обрабатывать.

    Reply
  23. VitaliyCeban

    (23) unpete, Хоть и не замечал пропусков, но ваш метод всё же, более надёжен, спасибо. Одно непонятно, как поведет себя одновременный .pop() у этого стека в 1С, и .push() в javascript, при отсутствии mutex’ов.

    Reply
  24. unpete

    (24) В моих проектах пропуски были решение из практики.

    как поведет себя одновременный .pop() у этого стека в 1С, и .push() в javascript

    Поведёт себя плохо, решение не идеальное, но вероятность проблем ниже.

    Reply
  25. sikuda

    Чашечка с кофе это эмблема java, а не javascript. Не путайте пожалуйста.

    Hitler And The Downfall Of Silverlight

    https://youtu.be/RRFiu0xfQzw

    Reply
  26. kvovka

    (19) unpete, клиентов все устраивает в мобильном, кроме интерфейса.

    Reply
  27. quick

    превосходный пример, как раз то что нужно. Надоело писать интерфейсы под все версии.

    Reply
  28. alprk
    ПараметрыКнопки = buttonsArray.Получить(i);

    var ПараметрыКнопки

    Reply
  29. VitaliyCeban

    (29) alprk, Дополнено, спасибо.

    Reply
  30. anig99

    Для УФ (управляемых форм) есть одно замечание.

    ОкноПервогоБраузера.externalForm = ЭтаФорма;

    использовать нельзя. Это циклическая ссылка и при закрытии клиента всё остается висеть в памяти и на сервере. Неизвращенными способами обойти это нельзя. Гораздо проще переделать на ПриНажатии, как описано здесь http://infostart.ru/public/338126/

    Для простых форм циклическая ссылка — тоже зло, но там реально наплодить костылей, чтобы циклическую ссылку устранить при закрытии клиента.

    Reply
  31. VitaliyCeban

    (31) А если в ПередЗакрытием вызвать ОкноПервогоБраузера.externalForm = null; ? Счетчик ссылок должен уменьшиться.

    Метод ПраНажатии описан в этой статье, правда уклон я сделал на его кроссплатформенность. В тиражном решении использую только его (из за упомянутой кроссплатформенности).

    Reply
  32. anig99

    (32) если есть циклическая ссылка, то окно закрывается только визуально, т.к. закрывается родительское окно клиента 1с. Фактически же окно не закрывается, оставаясь в памяти компьютера и сервера. Соответственно ни ПередЗакрытием, ни ПриЗакрытии не запускаются. Я несколько часов потратил на обдумывание, как это можно обойти в тонком клиенте, но понял, что эффективнее потратить время на переделку на ПриНажатии.

    Reply
  33. Alxby

    (23), (24) Хотел было написать комментарий о механизме обмена, но потом решил оформить его отдельной статьей http://infostart.ru/public/570446/

    Reply
  34. Lord_Alexandr

    Пытаюсь в браузере Chrome v55.x.x.x вызвать глобальную javascript-функцию через

    ДокументПервогоБраузера.defaultView.<ИмяМетода>();

    Получил сообщение 1С: Метод объекта не обнаружен <ИмяМетода>.

    При этом доступ к глобальным javascript-переменным есть. А с вызовами ошибка.

    Что я делаю не так?

    Через ДокументПервогоБраузера.parentWindow в IE и тонком/толстом клиентах работает все прекрасно.

    Reply
  35. json

    (35) очень интересно. А можно вас попросить выложить пример кода по созданию ком объекта хрома?

    Насколько мне известно сам хром (и другие браузеры кроме ие) не имеют ком интерфейса. Вы наверное какую-нибудь стороннюю dll используете?

    Я бы тоже поэкспериментировал в этом направлении

    Reply
  36. VitaliyCeban

    (35) Если выложите обработку, в которой воспроизводится проблема, смогу посмотреть.

    Reply
  37. VitaliyCeban

    (36) COMОбъект в случае веб-клиента (не IE) не используется. Насколько помню, ДокументПервогоБраузера.defaultView имеет тип ВнешнийОбъект.

    Reply
  38. Lord_Alexandr

    (36) Я использую механизм описанный в данной статье, никакого com-объекта тут нет. Обращение в web-клиенте идет через iframe.

    Проблема в том, что в W3C браузерах document ничего не знает о window, поэтому о parentWindow не может быть и речи, а defaultView немного иной объект. Видимо потому вызов глобальных функций не работает у меня.

    Reply
  39. Lord_Alexandr

    (37) Обработка изначальна была проста как валенок, т.к. делал исходя из статьи.

    Сейчас уже решил проблему не через вызов глобальных функций window, а через запись всех параметров в глобальную javascript-переменную и генерацию события click специальной скрытой кнопки. А уже в javascript-обработчике click анализирую содержимое глобальной переменной и выполняю необходимые действия.

    Reply
  40. pencil

    (33) Проверил, ПередЗакрытием прекрасно запускается. Да и было бы странно, если бы нет, это же ПЕРЕД закрытием, оно в принципе должно запускаться когда объект формы еще существует.

    К сожалению, вызов функций 1С через ПриНажатии не всегда возможно использовать. Обнаружил тут, что если веб-документ построен на фреймах (не в смысле <iframe> используется, а на <frameset>. Да, есть извращенцы, которые до сих пор так делают) то это событие у поля HTML вообще не вызывается.

    Reply
  41. fillin
    Reply
  42. kadild

    Плюс за статью.

    Только уберите, пожалуйста, лого чашки кофе. Java к JavaScript’у никакого отношения не имеет. У JavaScripta есть свое лого. Из-за таких вот ляпов в других ресурсах ржут над одинэсниками.

    Reply
  43. TylerDerdenIII

    В веб-клиенте Элементы.ДокументHTML.Документ = Неопределено. В толстом/тонком все норм. В чем может быть дело?

    Reply
  44. json

    (44) Возможно, что Поле HTML не отображается на форме (либо Видимость = ЛОЖЬ, либо располагается на невидимой закладке).

    Reply
  45. frkbvfnjh
    &НаКлиенте
    Процедура ПервыйБраузерДокументСформирован(Элемент)
    
    …
    ОкноПервогоБраузера.externalForm = ЭтаФорма;
    
    КонецПроцедуры

    В тонком клиенте, на платформе 8.3.15.1565 (даже под Windows) — не работает! Значение не меняется при присвоении формы, но если к примеру присвоить простой тип (число или строку), то значение в переменной меняется, так что прикрыли лавочку походу…

    Reply
  46. vladnet

    (46) Скорее всего это из за того что сейчас используется webkit, он не может так как эксплорер ссылки поддерживать на непонятные объекты

    Reply
  47. vladnet

    (44) Никто не нашел решения данной проблемы?

    В веб-клиенте Элементы.ДокументHTML.Документ = Неопределено

    это просто засада, все работает в а веб клиенте нет

    Reply
  48. Бэнни

    (47) и чего делать в таком случае?

    Reply
  49. Бэнни

    (49)разобрался, проще генерить события в js, и программно нажимать на невидимую кнопку, а она уже сама вызовет событие элемента «ПриНажатии» и там уже все разруливать.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *