| Добро пожаловать, Гость |
Вам необходимо зарегистрироваться перед тем, как пытататься написать сообщение.
|
| Пользователи в сети |
Сейчас 2 пользователей в сети. » 0 Участник(-ов) | 2 Гость(-ей)
|
| Последние темы |
Как получить документацию...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
09-24-2025, 09:28 AM
» Ответы: 1
» Просмотры: 311
|
Панель с кнопками для 3D ...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: nponyatov
09-19-2025, 09:32 AM
» Ответы: 0
» Просмотры: 368
|
Панель с кнопками для 3D ...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: nponyatov
09-19-2025, 08:31 AM
» Ответы: 0
» Просмотры: 331
|
Добавление библиотеки в п...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
08-22-2025, 07:18 AM
» Ответы: 0
» Просмотры: 300
|
WinnumAjaxAuthHandler - П...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
05-27-2025, 09:15 AM
» Ответы: 0
» Просмотры: 404
|
Эффективность работы опер...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Сергей Борисов
04-28-2025, 01:18 PM
» Ответы: 1
» Просмотры: 470
|
Переход на страницу
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
03-18-2025, 09:32 AM
» Ответы: 0
» Просмотры: 331
|
Убрать все всплывающие по...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
03-18-2025, 08:42 AM
» Ответы: 0
» Просмотры: 342
|
График работы оборудовани...
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
02-20-2025, 01:05 PM
» Ответы: 0
» Просмотры: 483
|
Выбор объекта
Сообщество: Динамические приложения в WINNUM Platform
Последнее сообщение: Lamantur
01-21-2025, 12:23 PM
» Ответы: 0
» Просмотры: 357
|
|
|
| Кнопки |
|
Автор: Lamantur - 04-12-2024, 11:21 AM - Сообщество: Динамические приложения в WINNUM Platform
- Нет ответов
|
 |
В динамических приложениях довольно часто используются кнопки.
Кнопки позволяют передать контроль над элементами приложения пользователю, или действуют как ссылки на другие страницы.
В данном посте я хотел бы рассказать не только о том, как использовать кнопки, но и показать несколько визуальных приемов, которые помогут стилизовать приложение и улучшить восприятие.
Начнем с самого начала:
Создание кнопки
Вы можете создать кнопку, перейдя в инструменты и выбрав одну из готовых кнопок. В этом случае вы создадите элемент, у которого уже будет сгенерирован “id”, “class”, и несколько готовых параметров. В настройках элемента можно удобно для себя настроить цвет, фон, текст и рамку, однако кнопка будет статичной и пака еще ничего не делает при нажатии.
создание кнопки.bmp (Размер: 1.69 KB / Загрузок: 40)
Если посмотреть на код созданного элемента, мы увидим все параметры, сгенерированные автоматически:
Есть и второй способ создать кнопку так, через html. Для того чтобы разместить html элемент для него нужен пустой контейнер, в поле данных мы создадим элемент <button>. Для того чтобы он мог быть не только учтен браузером, но и виден – нужен минимальный набор параметров, но, если оставить все в стандарте – можно просто вписать текст в элемент и его уже будет видно.
В данном случае применятся все встроенные библиотеки, которые могут на нее повлиять, и мы получим стандартную кнопку с надписью, при этом у нее даже будет анимация при наведении и нажатии (на самом деле просто изменение фона).
События
Все слушатели событий так же применимы и к кнопкам, и мы точно так же, как для любого другого элемента можем создать слушатель события через интерфейс, а можем прописать его в коде приложения в одном из подключенных файлов .js
Далее в примерах кода будем использовать id = "btn" для всех кнопок, если создавать событие через интерфейс, то id будет сгенерированным
Код: $('#btn').mousedown(function(event){
this.style.borderStyle = 'inset'
});
Это открывает для нас возможность изменять стили или вызывать визуальные функции или анимации, которых в интернете бесчисленное количество с готовым кодом и примерами.
Но вернемся к стандартной кнопке, она сейчас просто нарисована и имеет стандартные настройки. Если мы еще раз посмотрим в настройки элемента, то увидим опцию, которая называется «стиль рамки». Последние два варианта выбора называются «выдавленная» и «вдавленная»
выдавленнаяивдаленная.bmp (Размер: 3.33 KB / Загрузок: 39)
Если мы хотим создать эффект объема на кнопке, то нам нужно сделать ее выдавленной, а при нажатии она будет становиться вдавленной. Поэтому оставляем этот параметр в позиции «выдавленная».
За стиль рамки отвечает атрибут “border-style”, и значение, которое он принимает: outstet – выдавленная, inset – вдавленная.
Код: $('#btn').mousedown(function(event){
this.style.borderStyle = 'inset'
});
Теперь кнопка проваливается и залипает. Поставим пружинку, чтобы она возвращалась на место:
Код: $('#btn').mouseup(function(event){
this.style.borderStyle = 'outset';
});
Если кнопка создана через интерфейс, то у нее будет уникальный id, который повторится автоматически при добавлении события, а если вы сами написали кнопку, то обращаться к ней нужно по ее уникальному id.
Аналогичным образом работают и другие события, вот список событий для хорошо анимированной кнопки:- Под указателем мыши – mouseover
- Вне указателя мыши – mouseout
- Нажата кнопка мыши – mousedown
- Отпущена кнопка мыши – mouseup
Активность кнопки
Активность кнопки задается ее атрибутом disabled. По умолчанию он выключен и кнопка активна.
btn.disabled = true;
активность.bmp (Размер: 1.51 KB / Загрузок: 39)
У неактивной кнопки пропадает возможность взаимодействия, она перестанет нажиматься, перестанут работать события на нажатие, но события mouseover и mouseout продолжат работать, если не указать иное, например написать условие в самих событиях.
Код: if(!this.disabled){
this.style.background = 'green';
}
Для стилизации можно изменить ее цвет, или сделать полупрозрачной:
btn.style.opacity = "0.5";
Этого достаточно, чтобы кнопка выглядела приятнее, но это далеко не все возможности по стилизации кнопок. Так же как и для любого другого объекта применимы анимации, стили для кнопок можно применять с помощью css, так же существуют css анимации и многое другое. Но стоит отметить, что не все практики, применимые для веб-дизайна подойдут для использования в динамических приложениях, все таки стоит учитывать это при выборе анимации или слишком замысловатого стиля и сделать выбор в пользу более сдержанного и функционального дизайна.
|
|
|
| Градусник |
|
Автор: Lamantur - 03-20-2024, 10:04 AM - Сообщество: Динамические приложения в WINNUM Platform
- Ответы (1)
|
 |
Для того чтобы добавить в приложение такой градусник нам понадобится несколько простых действий.
- Скачать изображение градусника, либо нарисовать самостоятельно
- Удалить из него заполненную шкалу, если такая имеется
- Загрузить изображение в динамическую библиотеку
- Создать пустой контейнер и вставить код html в поле "Данные"
Код: <div style = 'background:url(/Winnum/resources/themes/current/images/app/ui/designer/media/24/Weather-Thermometer-Clipart-Black-and-White-1.png); width:100%; height:100%; background-size: 100% 100%'>
<div id = 'termometr' style = 'background:red; width:25%; height:61%;position: absolute;top:20%;left:36%'>
<div id = 'temperature' style = 'background:white;width:100%; height:50%;position: absolute;top:0%;left:0%'>
</div>
</div>
<div style = 'width:55%; height:25%;position: absolute;top:74%;left:21%'>
<svg width=100% height = 100%>
<ellipse id = "ellipce" fill = "red" cx=50% cy=50% rx=46% ry=41% />
</svg>
</div>
</div>
- Отредактировать ширину и высоту шкалы (откалибровать градусник). Редактировать нужно <div id = 'termometr'> подстроить параметры ширины и высоты шкалы, и ее расположение (top, left). Для того чтобы термометр растягивался вместе с контейнером, и шкала не съезжала все параметры должны быть указаны только в %.
- Что касается красного круга - то это svg рисунок, он векторный, а значит может растягиваться без потери качества, rx/ry - радиусы эллипса, а позицию ему задает его контейнер, его также нужно выставить на нужное место.
- Подключить к действующему сигналу для изменения шкалы градусника
Код: function termoparameter(t,color){
document.getElementById('termometr').style.background = color;
document.getElementById('ellipce').style.fill = color;
document.getElementById('temperature').style.height = 50 - t + '%';
}
- Параметр t - это и есть значение температуры, color - это цвет шкалы и эллипса. Значение сигнала можно получить как через интерфейс редактора, так и с помощью baseSdkUtils.service.WNConnectorHelper.getSignal, или вы получаете температуру каким-либо еще способом.
Вы можете использовать изображение, прикрепленное к этому посту, тогда настраивать ничего не нужно, только загрузить изображение в библиотеку и вставить код.
|
|
|
| Резиновая верстка |
|
Автор: Lamantur - 03-18-2024, 08:17 AM - Сообщество: Динамические приложения в WINNUM Platform
- Нет ответов
|
 |
Код: function setWidth() {
$('#541F4705-D07A-447F-B8AD-009CAFF336BD').css({
width: $('#FDBDB71A-029E-4C4F-9CB5-E4EEBA50771C').width()/2 + 'px', //ширина элемента
height: $('#FDBDB71A-029E-4C4F-9CB5-E4EEBA50771C').height()/2 + 'px', //высота элемента
top: '0px', // расстояние от верхнего края
left: $('#FDBDB71A-029E-4C4F-9CB5-E4EEBA50771C').width()/2 + 'px', // расстояние от левого края
overflow: 'hidden', // полоса прокрутки скрыта, элемент не выходит за край или обрезается
fontSize: $('#FDBDB71A-029E-4C4F-9CB5-E4EEBA50771C').height()/10 + 'px' // отдельно настраиваем размер шрифта
});
}
setWidth(); // устанавливаем высоту окна при первой загрузке страницы
$(window).resize( setWidth ); // обновляем при изменении размеров окна
Если есть необходимость настроить страницу так, чтобы при изменении размера окна она менялась, можно применить подобную функцию. Помимо этого можно вынести переменные в аргументы и применять одну функцию для всех элементов.
При создании резиновой верстки нужно чтобы все элементы имели размеры либо в процентах, либо в виде размера окна, умноженного на коэффициент, поскольку изначально все элементы имеют абсолютное позиционирование по умолчанию и размеры все задаются в пикселях. Пример готового универсального кода:
Код: function setWidth( element, width , height , top , left , fontSize , over) {
// element - id html элемента
$('#' + element).css({
width: $( window ).width() * ( width /100) + 'px', // width ширина элемента %
height: $( window ).height() * ( height /100) + 'px', // height высота элемента %
top: $( window ).height() * ( top /100) + 'px', // top расстояние от верхнего края %
left: $( window ).width() * ( left /100) + 'px', // left расстояние от левого края %
overflow: over, // полоса прокрутки, элемент выходит за край или обрезается 'str'
fontSize: $( window ).height() * ( fontSize /100) + 'px' // fontSize отдельно настраиваем размер шрифта %
});
}
function setElastic() {
setWidth( 'mychart1', 50, 50, 0, 0, 5, 'hidden');
setWidth( 'mychart2', 50, 50, 0, 50, 5, 'hidden');
setWidth( 'mytable', 100, 50, 0, 0, 6, 'visible');
}
setElastic(); // устанавливаем высоту окна при первой загрузке страницы
$(window).resize( setElastic ); // обновляем при изменении размеров окна
|
|
|
| Получение значений сигналов тега, если в теге больше одного сигнала |
|
Автор: Сергей Соловьев - 03-15-2024, 01:23 PM - Сообщество: Динамические приложения в WINNUM Platform
- Нет ответов
|
 |
Если в теге больше одного сигнала, то функция WNApplicationTagHelper.getLastTagValue возвращает значение только того сигнала, у которого стоит галочка "Определяет значение тега".
Если в теге заполнено поле "Значение при выполнении условий", то функция WNApplicationTagHelper.getLastTagValue возвращает то, что заполнено в этом поле.
Если нужно получать значения всех сигналов, то нужно последовательно выполнить getLastTagValue, затем получить имена сигналов тега через WNModelingHelper.getSignals, затем для каждого сигнала получить значения WNConnectorHelper.getSignal.
Ниже пример функции, которая вернет и текущее состояние тега, и значение, и значения каждого сигнала тега.
Код: thisGetLastTagValue( appid, pid, tid, startTime, endTime, timeout_mills, function ( result ){
console.log ( result );
});
function thisGetLastTagValue( appid, pid, tid, startTime, endTime, timeout_mills, callBackFunc){
var result = {};
result.data = [];
baseSdkUtils.service.WNApplicationTagHelper.getLastTagValue(appid, pid, tid, endTime, timeout_mills, function( data ){
if ( baseSdkUtils.isSuccess( data ) ){
var item = data.getElementsByTagName('item')[ 0 ];
var tag_status = baseSdkUtils.decode(item.getAttribute('success'));
var tag_value = baseSdkUtils.decode(item.getAttribute('value'));
result.tagStatus = tag_status;
result.tagValue = tag_value;
thisGetSignals( pid , tid, function ( signals ){
if ( baseSdkUtils.isSuccess( signals ) ){
var index = 0;
for ( var i = 0; i < signals.getElementsByTagName('item').length; i++ ){
var item = signals.getElementsByTagName('item')[ i ];
var asciiPartNumber = baseSdkUtils.decode(item.getAttribute('asciiPartNumber'));
thisGetLastSignal( pid, asciiPartNumber, timeout_mills, function( signals_value ){
index++;
result.data.push( signals_value );
if ( index == signals.getElementsByTagName('item').length ){
if ( callBackFunc ){
callBackFunc.call( this, result );
}
}
});
}
}
});
}
});
}
function thisGetSignals( pid, tid, callBackFunct){
baseSdkUtils.service.WNModelingHelper.getSignals(
pid,
tid,
function( data ){
if ( callBackFunct ){
callBackFunct.call( this, data);
}
});
}
function thisGetLastSignal( pid, ascii, timeout_mills, callBackFunct){
var result = {};
var nDate = new Date();
baseSdkUtils.service.WNFactory.getPersistable( pid , function( product_data ){
if ( baseSdkUtils.isSuccess( product_data ) ){
var item = product_data.getElementsByTagName('item')[ 0 ];
var ProductUUID = baseSdkUtils.decode(item.getAttribute('ProductUUID'));
baseSdkUtils.service.WNConnectorHelper.getSignal(
ProductUUID,
ascii,
true,
true,
'',
'',
1,
function( data ){
if ( baseSdkUtils.isSuccess( data ) ){
var item = data.getElementsByTagName('item')[ 0 ];
result.value = baseSdkUtils.decode(item.getAttribute('value'));
result.event_time = baseSdkUtils.decode(item.getAttribute('event_time'));
result.signal_id = item.getAttribute('signal_id');
var event_time_date = Date.parse( result.event_time );
var diff = nDate.getTime() - event_time_date;
if ( diff > timeout_mills){
result.value = undefined;
}
if ( callBackFunct ){
callBackFunct.call( this, result);
}
}
}
);
}
});
}
Формат ответа функции thisGetLastTagValue следующий:
Код: {
"data": [
{
"value": "35",
"event_time": "2024-03-15 16:21:53.000",
"signal_id": "A397"
},
{
"value": "29",
"event_time": "2024-03-15 16:21:53.000",
"signal_id": "A398"
}
],
"tagStatus": "true",
"tagValue": "2"
}
|
|
|
| Преобразование времени из строки в тип Date |
|
Автор: Сергей Соловьев - 03-15-2024, 01:02 PM - Сообщество: Динамические приложения в WINNUM Platform
- Ответы (2)
|
 |
Функции WINNUM JavaScript SDK возвращает время сигналов в строку формата 'yyyy-MM-dd hh:mm: ss.SSS'.
При необходимости преобразовать в тип Date можно использовать Date.parse:
Код: var currentTime = Date.parse( '2024-02-15 9:5:1' ); // вернет время в миллисекундах с 1970 года - 1707977101000
var currentDate = new Date( currentTime ); // вернет дату - Thu Feb 15 2024 09:05:01 GMT+0300 (Москва, стандартное время)
Функция baseSdkUtils.toDateObject дает некорректный результат, если часов, минут, или секунд меньше 10.
baseSdkUtils.toDateObject( '2024-02-15 9:5:1' ); // вернет ошибку
|
|
|
| Как получить расчеты тегов за длительные периоды |
|
Автор: Lamantur - 02-16-2024, 12:59 PM - Сообщество: Динамические приложения в WINNUM Platform
- Нет ответов
|
 |
Для построения отчетов за длительные периоды в WINNUM используется блокчейн.
Длительности тегов рассчитываются в конце каждого дня для построения длительных отчетов.
Эти же значения можно использовать в динамических приложениях, что позволяет использовать данные вместо многочисленных запросов и сокращать время выполнения команд.
Так, например, для получения суммарного времени работы под нагрузкой для конкретного станка можно использовать функцию getPriorityTagDuration, в результате мы получим массив из промежутков, когда тег выполнялся с учетом приоритетности, но если временной интервал указать больше двух-трех дней, то результатом будет огромный массив и выполнятся такой запрос может достаточно долго, может даже не хватить оперативной памяти, выделенной под работу браузера и получить зависание всей страницы.
Что же делать, если нас интересует график загрузки оборудования за год? Для этого работают роботы приложений. Рассчитанное значение тегов за каждый день уже с учетом приоритетности и календаря записано роботом. Для получения этих значений достаточно воспользоваться стандартной функцией getSignal, и указать вместо сигнала адрес в структуре блокчейн.
Общая структура запроса:
•[App ID].[Tag ID].[тип расчета].[тип значения] = значение
•Типы расчета:
•SCHED_PRIO – с приоритетностью по календарю
•SCHED_NOPRIO - без приоритетности по календарю
•REG_NOPRIO - без приоритетности без календаря
•Типы значений:
•PER – проценты, HOUR – часы
Пример: •17.145.SCHED_PRIO.HOUR
•17 – ID приложения
•145 – ID тега
•SCHED_PRIO – расчет по календарю с учетом приоритетности
HOUR – результат получить в миллисекундах суммарно по всем сменам
Код: var UUID = "GHIKFKGL-IR85-85JR-JGHUTKOL" ;// UUID - это ключ идентификатор продукта (станка)
var tagsPriorityID = '6.1.SHED_PRIO.HOUR'; //Из приложение 6 получаем тег NC_WIP с учетом приоритетности по календарю в миллисекундах
var dateFrom = "2022-12-12 00:00:00";
var dateTo = "2024-02-26 15:40:00";
var wipResult; // Результат за все время положим сюда
baseSdkUtils.service.WNConnectorHelper.getSignal(UUID, tagsPriorityID, false, false, dateFrom, dateTo,'',function(data){
if (baseSdkUtils.isSuccess(data) ){
for (var t = 0; t < data.getElementsByTagName('item').length; t++){
var itemT = data.getElementsByTagName('item')[t];
var valueT = Math.round((((parseFloat(itemT.getAttribute('value'))/3600000); //Получаем отдельно значение в округленном виде, в часах
wipResult += valueT; // находим сумму за все время
}
}
});
Еще быстрее можно посчитать значения за несколько месяцев, если нас интересуют все дни месяца:
Тогда нужно просто добавить "m", значения появляются в первый день следующего месяца, поэтому его нужно тоже захватить во временной промежуток
Код: var tagsPriorityID = '6.1.m.SHED_PRIO.HOUR';
var dateFrom = "2022-12-01 00:00:00";
var dateTo = "2024-02-01 15:40:00";
Разница во времени выполнения ощущается даже при построения отчета за несколько дней.
|
|
|
| Как получить список всех сигналов изделия |
|
Автор: Сергей Соловьев - 02-09-2024, 01:17 PM - Сообщество: Динамические приложения в WINNUM Platform
- Нет ответов
|
 |
Пример получения списка сигналов изделия (сначала получить по class:id изделия шаблон, затем по class:id шаблона сигналы):
Код: function thisGetProductTemplate(){
var pid = 'winnum.org.product.WNProduct:48'; // class:id изделия
baseSdkUtils.service.WNProductHelper.getProductTemplate(
pid,
function( data ){
var item = data.getElementsByTagName('item')[0];
var oid = baseSdkUtils.decode(item.getAttribute('id')); // class:id шаблона
thisGetSignalsByProductTemplate( oid );
});
}
function thisGetSignalsByProductTemplate( oid ){
baseSdkUtils.service.WNProductHelper.getSignalsByProductTemplate(
oid,
function( data ){
console.log( data ); // список сигналов шаблона
});
}
|
|
|
| Создание своей страницы |
|
Автор: wnadmin - 02-08-2024, 02:59 PM - Сообщество: Разработка собственных приложений в WINNUM Platform
- Ответы (1)
|
 |
Для создания своих приложений первое, что нужно научиться делать - это создавать свои страницы.
Создание страниц происходит в Java с использованием WINNUM SDK. SDK содержит кучу всего полезного, включая элементы пользовательского интерфейса (меню, формы, кнопки и тд). Все для того, чтобы максимально ускорить и упросить разработку своих приложений.
Созданные страницы на Java компилируются и копируются в специальные папки (в зависимости от назначения). Отрисовка страниц (написанных на Java) выполняется с помощью т.н. agw (application gateway), который с сумасшедшей скоростью печатает страницы в браузере.
Давайте создадим первую страницу на Java в WINNUM Platform. Для этого создадим новый класс, назовем его MaPage, в пакете winnum.views.my_app, пример:
Код: package winnum.views.my_app;
import io.undertow.servlet.spec.*;
import winnum.system.config.ConfigHelper;
import winnum.system.exception.WNException;
import winnum.web.base.*;
public class MyPage {
//----------------------------------------------------------------------------------------
public static void processPage(HttpServletRequestImpl request, HttpServletResponseImpl response) throws WNException {
PageMeta.streamHead(request, response, "Page Title", null);
UIHelper.streamOut(response, "<body>", false);
PageHeader.streamAuthorizedHeader(request, response, true);
UIHelper.streamOut(response, "Hello World!", false);
UIHelper.streamOut(response, "</body></html>", true);
}
//----------------------------------------------------------------------------------------
}
Для компиляции нам потребуются следующие библиотеки:- winnum-platform.system-5.0.0.jar
- winnum-platform.web-5.0.0.jar
- undertow-servlet-1.3.15.Final.jar
Эти и другие библиотеки можно найти в <WINNUM Platform>/srclib.
После того, как наша первая страница готова, скомпилируем ее и скопируем в папку <WINNUM Platform>/views/winnum/views/my_app.
Все, на этом создание нашей страницы закончено, проще не бывает)
Для просмотра страницы в браузере вызываем ее через agw:
http://localhost/Winnum/views/pages/app/agw.jsp?rpc=winnum.views.my_app.MyPage&men=processPage&mode=yes
|
|
|
|