Добро пожаловать, Гость
Вам необходимо зарегистрироваться перед тем, как пытататься написать сообщение.

Имя пользователя
  

Пароль
  





Поиск по сообществам

(Расширенный поиск)

Статистика сообществ
» Участники: 95
» Последний участник: VaniaAchen
» Темы сообществ: 38
» Сообщения сообществ: 64

Полная статистика

Пользователи в сети
Сейчас 3 пользователей в сети.
» 0 Участник(-ов) | 2 Гость(-ей)
Google

Последние темы
Как получить документацию...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
09-24-2025, 09:28 AM
» Ответы: 1
» Просмотры: 310
Панель с кнопками для 3D ...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: nponyatov
09-19-2025, 09:32 AM
» Ответы: 0
» Просмотры: 367
Панель с кнопками для 3D ...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: nponyatov
09-19-2025, 08:31 AM
» Ответы: 0
» Просмотры: 330
Добавление библиотеки в п...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
08-22-2025, 07:18 AM
» Ответы: 0
» Просмотры: 298
WinnumAjaxAuthHandler - П...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
05-27-2025, 09:15 AM
» Ответы: 0
» Просмотры: 403
Эффективность работы опер...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Сергей Борисов
04-28-2025, 01:18 PM
» Ответы: 1
» Просмотры: 468
Переход на страницу
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
03-18-2025, 09:32 AM
» Ответы: 0
» Просмотры: 329
Убрать все всплывающие по...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
03-18-2025, 08:42 AM
» Ответы: 0
» Просмотры: 340
График работы оборудовани...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
02-20-2025, 01:05 PM
» Ответы: 0
» Просмотры: 481
Выбор объекта
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
01-21-2025, 12:23 PM
» Ответы: 0
» Просмотры: 355

 
Photo Временная шкала
Автор: Lamantur - 11-14-2024, 02:57 PM - Сообщество: Динамические приложения в WINNUM Platform - Ответы (1)

Код:
// Создать векторную шкалу времени в зависимости от смены
// 1 аргумент - класс
// 2 аргумент - время начала смены
// generateTimeline("class", 20);
//h графикa  = 94,864%, и отступить от левого края 12px
function generateTimeline(c, start){
    var elements = document.getElementsByClassName(c);
    var e;
    for(let ii=0; ii<elements.length; ii++){
        e = elements[ii];
        var str = '<line y1=40% x1=1px y2=40% x2=94.864% style=\'stroke:black;stroke-width:0.2%\' />';
        var text, res;
        var all_h = e.getBoundingClientRect().height;
        var all_w = e.getBoundingClientRect().width;
        var textsize = all_h/2;
        for(var i=0;i<=6;i++){
            // Делим на 12 частей
            let t = i*7.9*2;
            let s = t;
            let timeText = i*2 + start;
            if(timeText > 23) timeText = i*2 - 4;
            str = str + '<line y1=40% x1=' +s+ '% y2=0% x2=' +s+ '% style=\'stroke:black;stroke-width:0.3%\' />';
            text = text + "<text y=100% x=" +t+ "% class=\'small\'>" +timeText+ ":00</text>";
        }
        res = "<svg style = 'width:100%;height:100%;margin-left: 12px;' >" +str+ "</svg>";
        var ret = "<svg width = 100% height = 100%>" +text+ "</svg>";
        var d = "<div style = 'width:100%;height:100%;display:grid'>"+res+ret+"</div>";
        e.innerHTML = d;
    }
}
   

Распечатать этот элемент

  Эффективность работы операторов
Автор: Lamantur - 09-13-2024, 02:49 PM - Сообщество: Динамические приложения в WINNUM Platform - Ответы (1)

В приложении файл для экспорта приложения, анализирующее работу операторов.
1. Должен быть подключен сигнал с именем оператора. Указать сигнал можно в коде. 
2. Данные берутся из приложения 1 - Работа под нагрузкой.
3. Приложение работает с сигналами, поэтому при выборе длительного периода формирование отчета занимает время, но все равно строится.
4. При построении таблиц используется встроенная функция baseUtils.createTable

.zip   Эффективность операторов.zip (Размер: 7.85 KB / Загрузок: 8)

Изменяя параметры в функции  createTable можно изменить внешний вид таблицы.

КПД - это параметр, характеризующий загруженность оператора на конкретном станке - определяется временем регистрации, деленном на время выполнения программы станка.



Файлы вложений Эскизы(ов)
   
Распечатать этот элемент

  График работы оборудования на chart.js v4
Автор: Сергей Соловьев - 09-06-2024, 12:54 PM - Сообщество: Динамические приложения в WINNUM Platform - Ответы (2)

Во вложении пример приложения с использованием chart.js v4 и дополнительных плагинов для графика работы оборудования. Для версии платформы 5.4.5 и выше.



Файлы вложений
.zip   DayWorkChart.zip (Размер: 48.08 KB / Загрузок: 21)
Распечатать этот элемент

Lightbulb Telegram Bot для получения последнего бюллетеня
Автор: lunula - 08-03-2024, 12:09 PM - Сообщество: Интеграция WINNUM Platform с другими информационными системами - Нет ответов

Всем привет!

Недавно в WINNUM Platform появился новый функционал - бюллетени, в следствии чего захотелось его дополнить.

Ниже представлен код на C# с использованием .NET 6 и библиотекой Telegram.Bot 18.0.0, который позволяет на любой сгенерированный бот в telegram отправлять последнюю бюллетень полученную от publisher:

Код:
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Exceptions;
using Telegram.Bot.Polling;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.InputFiles;
using Telegram.Bot.Types.ReplyMarkups;

class PublisherBot
{
    private static ITelegramBotClient botClient;

    static async Task Main(string[] args)
    {
        botClient = new TelegramBotClient("5687077362:AAExWWUSdtVLmjYsKqnND7o6CoqFx****"); //bot_token

        var cts = new CancellationTokenSource();

        var receiverOptions = new ReceiverOptions
        {
            AllowedUpdates = Array.Empty<UpdateType>() // получение всех типов обновлений
        };

        botClient.StartReceiving(
            HandleUpdateAsync,
            HandleErrorAsync,
            receiverOptions,
            cancellationToken: cts.Token
        );

        Console.WriteLine("Бот запущен и работает. Нажмите Enter, чтобы выйти.");
        Console.ReadLine();

        cts.Cancel();
    }

    static async Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
    {
        if (update == null) return;

        if (update.Message != null)
        {
            var message = update.Message;
            if (message.Text != null)
            {
                if (message.Text.Equals("/start"))
                {
                    await SendWelcomeMessageAsync(message.Chat.Id);
                }
            }
        }
        else if (update.CallbackQuery != null)
        {
            var callbackQuery = update.CallbackQuery;
            if (callbackQuery.Data != null && callbackQuery.Data.Equals("get_file"))
            {
                await SendLatestPdfFileAsync(callbackQuery.Message.Chat.Id);
            }
        }
    }

    static async Task SendWelcomeMessageAsync(long chatId)
    {
        var button = InlineKeyboardButton.WithCallbackData("Получить файл", "get_file");

        var keyboard = new InlineKeyboardMarkup(new[] { new[] { button } });

        await botClient.SendTextMessageAsync(chatId, "Нажмите кнопку ниже, чтобы получить последний бюллетень:", replyMarkup: keyboard);
    }

    static async Task SendLatestPdfFileAsync(long chatId)
    {
        string directoryPath = @"C:\\Winnum\\WinnumPlatform\\publisher\\cache\\temp"; // Путь до temp у publisher
        var latestPdfFile = GetLatestPdfFile(directoryPath);

        if (latestPdfFile != null)
        {
            try
            {
                using var stream = new FileStream(latestPdfFile.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
                var inputOnlineFile = new InputOnlineFile(stream, latestPdfFile.Name);
                await botClient.SendDocumentAsync(chatId, inputOnlineFile);
            }
            catch (Exception e)
            {
                Console.WriteLine($"Ошибка при отправке файла: {e.Message}");
                await botClient.SendTextMessageAsync(chatId, "Ошибка при отправке файла.");
            }
        }
        else
        {
            await botClient.SendTextMessageAsync(chatId, "Нет доступных бюллетеней.");
        }
    }

    static FileInfo GetLatestPdfFile(string directoryPath)
    {
        var directory = new DirectoryInfo(directoryPath);
        if (!directory.Exists) return null;

        return directory.GetFiles("*.pdf")
            .OrderByDescending(f => f.LastWriteTime)
            .FirstOrDefault();
    }

    static Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, CancellationToken cancellationToken)
    {
        var errorMessage = exception switch
        {
            ApiRequestException apiRequestException
                => $"Telegram API Error:\n[{apiRequestException.ErrorCode}]\n{apiRequestException.Message}",
            _ => exception.ToString()
        };

        Console.WriteLine(errorMessage);
        return Task.CompletedTask;
    }
}

На данный момент сделан bild под windows (скриншот во вложении) и протестирована работа бота(скриншот во вложении).

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

Во вложении .zip архив проекта без bild под Windows, так как с ним он просто слишком большой и не отправляется.

Для тех кто будет продолжать работать с проектом подмечу, важно использовать .NET 6 и выше, так как библиотека поддерживает работу от 6 версии и очень важно использовать версию библиотеки 18.0.0 , так как при работе с 19 версией будут проблемы с пространством имен Telegram.Bot.Types.ImputFiles в следствии чего будет невозможна работа с ImputOnlineFile.



Файлы вложений Эскизы(ов)
       

.zip   TelegramBotWinnum.zip (Размер: 514.97 KB / Загрузок: 5)
Распечатать этот элемент

Question Как создать параметры для своего приложения с помощью хэлперов?
Автор: Сергей Борисов - 07-29-2024, 10:56 AM - Сообщество: Разработка собственных приложений в WINNUM Platform - Нет ответов

Добрый день!

В процессе разработки собственных приложений на JAVA, используя Winnum.SDK, появилась необходимость создания параметров и групп параметров для управления поведением приложения. У всех стандартных приложений имеются свои параметры и группы параметров, которые доступны по адресу:

Код:
http://127.0.0.1/Winnum/views/administration/parameters/list.jsp?cid=winnum.org.app.WNApplicationInstance:1&mode=yes

Подскажите, пожалуйста, как правильно создавать свои параметры, группы параметров и вложенные группы в группу параметров с использованием хэлперов Winnum.SDK.

Распечатать этот элемент

  Повторяющиеся сигналы
Автор: Lamantur - 07-16-2024, 11:36 AM - Сообщество: Динамические приложения в WINNUM Platform - Ответы (1)

Повторяющийся сигнал - это сигнал, который записывается автоматически с определенным интервалом и значением. Такие сигналы могут быть использованы для ввода ручных значений. Рассмотрим вариант использования, в котором стоит задача авторизовать пользователя, привязав его к определенному изделию и снять авторизацию когда это потребуется. Альтернативой этому может быть любой вводимый пользователем сигнал, например текущая операция или причина простоя.
Для работы с повторяемыми сигналами существует системный робот Repeatable Signal Worker. В настройках этого робота можно указать интервал для повторения всех сигналов.
 Для контроля и управления всеми повторяющимися сигналами достаточно перейти в Настройки>Администрирование>Повторяющиеся сигналы.
В WINNUM JavaScriptSDK для работы с управляемыми сигналами предусмотрены следующие функции:

Код:
baseSdkUtils.service.WNRepeatableSignalHelper.createRepeatableSignal(uuid, prefix, signal, counter, function(data) {})
Создание нового повторяемого сигнала. Если повторяемый сигнал с заданными параметрами уже есть, то он будет остановлен и использован
Параметр uuid – UUID продукта
Параметр qualifiedPrefix – блокчайн префикс (допускается только кодировка ASCII) - Допустимо оставить пустым
Параметр qualifiedName – квалифицированное имя сигнала (допускается только кодировка ASCII)
counter - тип используемого счетчика, если сигнал используется не для счетчиков указывается "",

baseSdkUtils.service.WNRepeatableSignalHelper.startRepeatableSignal(oid, value, function(data) {})
Запуск созданного заранее повторяемого сигнала
Параметр oid – идентификатор повторяемого сигнала (class name: id), его можно найти в адресной строке при открытии информации о повторяемом сигнале.
Параметр value – повторяемое значение

baseSdkUtils.service.WNRepeatableSignalHelper.stopRepeatableSignal(oid, function(data) {})
Остановка повторяемого сигнала
Параметр oid – идентификатор повторяемого сигнала (class name: id), его можно найти в адресной строке при открытии информации о повторяемом сигнале.

baseSdkUtils.service.WNRepeatableSignalHelper.getRepeatableSignal(uuid, function(data) {})
Получение перечня повторяемых сигналов по UUID продукта
Параметр uuid – UUID продукта

Для проверки действия функции достаточно вызвать ее, а полученный ответ записать в консоль:
Код:
baseSdkUtils.service.WNRepeatableSignalHelper.createRepeatableSignal(uuid, "", "A100", "", function(data) {console.log(data)})
После этого можно проверить, что в списке повторяемых сигналов появилось новое значение. 
Важные моменты:
1. Управлять повторяемыми сигналами может только Администратор Устройств или Администратор в Организации.
2. Создавая повторяемый сигнал - не создайте его на месте реального сигнала с тем же именем. В этом случае сигнал будет подмешивать значения в приходящий сигнал.
3. Чтобы увидеть сигнал на устройстве нужно создать Шаблон Объекта Данных, назначить его Шаблону Устройств и Прикрепить этот Шаблон Устройств к Шаблону Изделий (на ваше усмотрение как именно организовать Шаблон Изделия).

Создать и запустить:
Код:
function createSignalOperator(uuid, signal, value){
    baseSdkUtils.service.WNRepeatableSignalHelper.createRepeatableSignal(uuid, "", signal ,"",function(data){
         for(var i = 0; i < data.getElementsByTagName('item').length ; i++ ) {
            var item = data.getElementsByTagName('item')[i];
            var oid = baseSdkUtils.decode(item.getAttribute("id"));
           
            baseSdkUtils.service.WNRepeatableSignalHelper.startRepeatableSignal(oid, value);
         }
    });
}


Во вложении шаблон, который позволяет назначать станкам операторов в виде повторяющегося сигнала. Для этого получаем список установленных и доступных пользователю приложений - их выведем в виде выпадающего списка, оттуда сразу берем список станков и запускаем вывод значений сигналов в таблицу:
Код:
function getApplication(){
   
    baseSdkUtils.service.WNApplicationHelper.getApplicationInstance('', function (data){
        if ( baseSdkUtils.isSuccess(data) ){
            var namesApp = [];
            var idApp = [];
            for (var i = 0; i < data.getElementsByTagName('item').length; i++){
                var item = data.getElementsByTagName('item')[i];
                var name = baseSdkUtils.decode(item.getAttribute('name'));
                namesApp.push(name);
                var id = item.getAttribute('id');
                idApp.push(id);
            }
            uniqueNames = new Set(namesApp);
            uniqueId = new Set(idApp);
            var ApplicationNames = Array.from(uniqueNames);
            var ApplicationID = Array.from(uniqueId);
           
            for(s=0;s<ApplicationNames.length;s++){ApplicationNames[s]='<option value=\'' + ApplicationID[s] + '\'>' + ApplicationNames[s] + '</option>';}
            ApplicationNames.sort();
            document.getElementById('appid').innerHTML = ApplicationNames.join("");
            var yourSelect = document.getElementById( "appid" );
            var _appid_ = yourSelect.value;
            //console.log(_appid_);
            startFunction(_appid_);
           
            baseSdkUtils.service.WNApplicationHelper.getProduct(_appid_, function(data){
                if ( baseSdkUtils.isSuccess(data) ){
                   
                   
                   
                    for(var i = 0; i < data.getElementsByTagName('item').length ; i++ ) {
                        var item = data.getElementsByTagName('item')[i];
                        var product_UUID = item.getAttribute('ProductUUID');
                       
                        setTimeout(getRSignal, 200 * (i), product_UUID, i);
                    }
                }
            });
           
        }
    });
}

.zip   Авторизация операторов R5.zip (Размер: 8.52 KB / Загрузок: 5)

Распечатать этот элемент

Photo Стрелочные индикаторы (transform+rotate)
Автор: Lamantur - 06-24-2024, 02:15 PM - Сообщество: Динамические приложения в WINNUM Platform - Нет ответов

Добрый день, коллеги!
Сегодня мы рассмотрим такую тему как трансформации объектов на странице. 
Вращение объекта на странице — без преувеличения одна из самых полезных функций. Этот эффект, будучи простым в понимании, содержит некоторые хитрости, о которых не стоит забывать во время разработки приложения.
Вращение объекта достигается путём использования функции rotate() свойства transform. В отличие от функции перемещения, вращение не может быть описано пикселями, процентами и другими привычными единицами измерения. Для вращения объекта используются специальные «угловые» единицы, среди которых:
deg — Градусы. Знакомая многим единица измерения, по которой можно указать, на какой угол повернуть объект относительно его начального положения .
grad — Градианы. Отличительной особенностью такой единицы является количество град на один квадрант — 100. То есть полный круг описывается в 400 град.
rad — Радианы. Мера, при которой за одну единицу принимается угол дуги, длина которой равна радиусу окружности.
turn — Оборот. Количество оборотов окружности, где единица равна одному полному обороту.
Если пользоваться CSS, то функция выглядит следующим образом:

 transform: rotate(15deg); // поворот на 15 градусов по часовой стрелке
 transform: translate(-50%, -50%); // перемещение на 50% вверх и 50% влево

Зная это мы можем написать функцию, которая будет менять угол и положение объекта в зависимости от внешних параметров. 
Для дальнейших экспериментов поставим задачу - оживить индикатор от 0 до 100%, в качестве сигнала возьмем загрузку процессора и выведем информацию в виде красивого индикатора, который соберем сами из нескольких элементов.

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


   

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


   

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

Когда два элемента подготовлены - можно переходить в редактор динамических приложений.

Создаем контейнер, назначаем ему фон - сам индикатор. Настраиваем, чтобы фон был посередине и не повторялся.
Внутри этого контейнера будет еще два: первый - это стрелочка, ему также настраиваем фон, второй контейнер - цифровая индикация.

Я настроил сигнал на странице при помощи стандартного интерфейса, сигнал назвал "Processor". Теперь я могу вызвать его из любого места страницы. 
Начнем с простого отображения сигнала, заодно проверим, что все правильно.
В контейнере, предназначенном для цифровой индикации создаем событие "Проигрывание в цикле".

Код:
//page id:C18FB6C5-962B-4EB6-9F78-716E2EABD2E3
//element id:0DE1C71A-E5AC-4698-AAE5-97AEC1E8E8BA
//LOOP_PLAY
function loop_0DE1C71A_E5A(){
   try {
    let elem = document.getElementById('0DE1C71A-E5AC-4698-AAE5-97AEC1E8E8BA');
    let value = baseSdkUtils.data['Processor'].value;
    elem.innerHTML = value;
   } catch ( e ) {
   }
   setTimeout(loop_0DE1C71A_E5A, 1000);
}
loop_0DE1C71A_E5A();
Очень важный момент - у вас element id будет другим, если вы создаете приложение самостоятельно.
Теперь запускаем экземпляр приложения и видим значение сигнала. 
Настало время заставить стрелку двигаться вместе со значением.
В поле html вставляем следующий код:
Код:
<div class='pivont-point'>&bull;</div>
<style>
.pivont-point {
  position: absolute;
  top: 50%;
  left: 79%;
  color: #363636;
  font-size: 30px;
  transform: translate(-50%, -50%);
}

</style>
Этот элемент мы создаем для того, чтобы "откалибровать нашу стрелку. 
Мы сразу увидим, что на нашей стрелке появилась точка - это и есть ось вращения. Изменяя элементы top и left - переместим точку в нужное нам место.
В данном случае  transform: translate(-50%, -50%) - переворачивает систему координат для того чтобы как раз параметры  top и left соответствовали оси вращения, которую мы уже будем задавать в событии.
Создаем событие "Проигрывание в цикле":
Код:
//page id:C18FB6C5-962B-4EB6-9F78-716E2EABD2E3
//element id:681DB916-6405-408C-8480-C5AEB30EF032
//LOOP_PLAY
function loop_681DB916_640(){
   try {
    let elem = document.getElementById('681DB916-6405-408C-8480-C5AEB30EF032');
    let value = (baseSdkUtils.data['Processor'].value);
   
    elem.style.transform = 'rotate(' + (16 + (value * 1.48)) + 'deg)';
    elem.style.transformOrigin = '79% 50%';
   } catch ( e ) {
   }
   setTimeout(loop_681DB916_640, 1000);
}
loop_681DB916_640();
elem.style.transformOrigin = '79% 50%' - эти параметры совпадают с ранее выбранными left И top
Теперь рассмотрим предыдущую строчку:
elem.style.transform = 'rotate(' + (16 + (value * 1.48)) + 'deg)';
Мы используем функцию rotate, в качестве единиц измерения я выбрал градусы, а значит полный круг = 360.
Путем подбора вычисляем, что стрелка показывает на 0 при значении 16 градусов. На 100 она показывает при значении 164 градуса. Таким образом вся шкала составляет 164 - 16 = 148. Делим на 100%  и получаем  (16 + (value * 1.48)) - теперь стрелка показывает на нужный параметр.
Если вы делаете индикатор с другим фоном или стрелка у вас находится в другом месте (выше или ниже), то числа у вас будут другие.
Шаблон приложения: 
.zip   export (14).zip (Размер: 362.35 KB / Загрузок: 4)
На последок небольшой бонус: 
В скрипт, который мы создали для анимации стрелки добавим еще одну команду:
elem.style.transition = '1s';
И тогда изменение значения сигнала будет сопровождаться плавным переходом к следующему значению.
У свойства  transition есть еще много атрибутов, позволяющих делать нелинейные анимации или более сложные.
Спасибо за внимание.

Распечатать этот элемент

  Как получить xls файл с таблицей из приложения
Автор: Lamantur - 05-08-2024, 01:27 PM - Сообщество: Динамические приложения в WINNUM Platform - Нет ответов

Для того чтобы оформить выгрузку в Excel уже существующей таблицы в динамическом приложении нужно обратиться к ней, перевести в UTF-8 и сформировать ссылку.

1) Возьмём таблицу html, ее можно создать готовую, или сделать самому, назначив id, наполнить ее всеми необходимыми данными, далее будем ее сохранять в xls.

   

2) сделаем обычную кнопку с надписью скачать и внутри нее создадим событие "нажата кнопка мыши"

Код:
$('#buttonID').click(function(event){
   function exportTableToExcel(tableId, filename = 'the_data_you_needed.xls') {
    let dataType = 'application/vnd.ms-excel';
    let tableSelect = document.getElementById(tableId);
   
    let tableHTML = encodeURIComponent(tableSelect.outerHTML.replace(/ or .*?>/g, '>'));
    let link = document.createElement('a');
    link.setAttribute('href', 'data:text/csv;charset=utf-8,%EF%BB%BF' + tableHTML);
    link.download = filename;
    link.click();
}
exportTableToExcel('tableID');
});
Вот и всё!
В этой функции подставляем:
buttonID - ID кнопки, которую нажимаем
tableID - ID таблицы, которую выгружаем
the_data_you_needed.xls - название файла, который получим

Распечатать этот элемент

  injectIntoPage
Автор: Lamantur - 05-03-2024, 01:41 PM - Сообщество: Динамические приложения в WINNUM Platform - Нет ответов

Задача: У нас есть стандартный отчет по работе оборудования, он нас устраивает, но при формировании этого отчета необходимо указывать дату и выбирать наш цех. Мы хотим приложение, в котором отчет будет открываться сразу за сегодняшнее число, за наш цех, и показывал всегда актуальную информацию, мы его повесим на телевизор в цеху и трогать не будем.
Решение:
Создаем пустое приложение из шаблона, или просто пустое приложение.
Добавляем пустой контейнер. Для удобства прописываем в поле данные еще один контейнер:

Код:
<div width = '100%' height = '100%' id = fullscreen></div>

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

Для того чтобы вставить в приложение готовый отчет используется функция baseUtils.injectIntoPage, 

ƒ injectIntoPage(
url – берем из параметра injectedurl на том элементе, который хотим повторить, я взял отчет по загрузке и меняю в нем параметры, а так же дату
, injectId – куда будем вставлять результат
, checkAuth – нужно ли быть авторизованным для получения результата (если поставить false, то функция будет работать только там, где не требуется авторизация, в нашем случае используются данные из приложения, а у него есть пользователи)
 
, callBack – далее все как обычно
, callBackError)

Теперь рассмотрим атрибут  injected_url, в нем написан адрес запроса, его же мы и будем использовать как параметр url.
/Winnum/views/pages/app/agw.jsp?rpc=winnum.views.pages.app.cnc.reports.calendar.TagPriorityWorkReport
&men=streamWorkReportsTable
&appid=winnum.org.app.WNApplicationInstance:8
&oid=winnum.org.domain.WNAdministrativeDomain%3A1
&oid_id=__ref_inputoid&oid_type=text_reference&oid_value2=
&date=03.05.2024
&date_id=__text_date_inputdate
&date_type=text-date
&date_value2=
&formid=report_settings_form
&count=2
&mode=yes
Очевидно, что его можно исправить в таких аргументах как date,  oid,  appid.
oid и appid нас устраивает, осталось только сделать сегодняшний день и запустить отчет в цикле, обновляя его каждые пять минут. Значит создаем событие loop (проигрывание в цикле) и пишем:

Код:
//get today
    var today = new Date();
    var dd = today.getDate();
    if (dd < 10){dd = '0' + dd}
    var mm = today.getMonth() + 1;
    if (mm < 10){mm = '0' + mm}
    var yyyy = today.getFullYear();
    var thisday = dd + '.' + mm + '.' + yyyy;
   
    var appid = 'winnum.org.app.WNApplicationInstance:8';
    var oid = 'winnum.org.domain.WNAdministrativeDomain%3A1';
    var containerId = fullscreen.id;
   
    baseUtils.injectIntoPage('/Winnum/views/pages/app/agw.jsp?rpc=winnum.views.pages.app.cnc.reports.calendar.TagPriorityWorkReport&men=streamWorkReportsTable&appid=' + appid + '&oid=' + oid + '&oid_id=__ref_inputoid&oid_type=text_reference&oid_value2=&date=' + thisday + '&date_id=__text_date_inputdate&date_type=text-date&date_value2=&formid=report_settings_form&count=2&mode=yes', containerId, true);

Теперь сделаем все на весь экран: 
Создаем событие "изменен размер"

Код:
//page id:7CB5B62C-0810-4735-8936-E43D6BDA422F
//element id:FA74BB0F-2A80-4EDB-8E86-5CF88D21D7AC
//ON_RESIZE
$(window).resize(function(event){
    $('#FA74BB0F-2A80-4EDB-8E86-5CF88D21D7AC').css({
        width: $(window).width()  + 'px',
        height: 85 + 'px',
        left: $(window).width()*0 + 'px',
        top: $(window).height()*0 + 'px',
        overflow: 'visible',
       
    });
    $('#882AEF86-12F4-4383-977F-DAC9FC53FEC7').css({overflow: 'visible'}); // слой
    $('#7CB5B62C-0810-4735-8936-E43D6BDA422F').css({overflow: 'visible'}); // страница
    $('#63EC5ED4-9C93-4EA2-9EDF-36573CB1EEFC').css({width: $(window).width()  + 'px'}); // верхнее меню
   
   
});
В данном случае нужно прописать id нашего контейнера, центрального слоя и верхнего меню, для того чтобы все было "резиновым" и на своих местах. Еще в самом начале поменять id контейнера на window.

В результате получится приложение, которое открывает отчет по нагрузке за весь домен и обновляет его каждые 300 секунд, данные берутся из приложения 8. Чтобы получить свой цех - нужно поменять oid на соответствующую ему папку.

Во вложении самообновляемый отчет, который позволяет выбрать участок или весь цех, а так же выбрать приложение для построения графика из выпадающего списка



Файлы вложений
.zip   export (1).zip (Размер: 94.17 KB / Загрузок: 15)
Распечатать этот элемент

  [Вопрос] Корректность данных получаемых функцией getPriorityTagDuration()
Автор: Сергей Борисов - 04-22-2024, 03:07 PM - Сообщество: Динамические приложения в WINNUM Platform - Ответы (14)

В процессе разработки динамического приложения появилась необходимость получать все статусы оборудования с учётом приоритетности за текущий день/смену в режиме реального времени. Используя метод getPriorityTagDuration() WINNUM JavaScript SDK получаю данные, которые не соответствуют данным в отчетах. 

Например, в приложенном скриншоте №1 с данными полученные функцией getPriorityTagDuration() видны частые появления тега статуса "Станок выключен", хотя в приложенном скриншоте №2 видно, что в отчёте по работе оборудования за текущий день, статуса "Станок выключен" нет. Также не совпадают временные метки старта и окончания действия тегов, например, тег "М0 останов", см. скриншот №3.

В чём может быть причина таких расхождений? Или расчёт длительности тегов, выполняемый в функции getPriorityTagDuration() отличается от методов расчётов для стандартных отчётов? Или требуется какая-то настройка платформы для получения корректных данных?



Файлы вложений Эскизы(ов)
           

Распечатать этот элемент