Инструменты пользователя

Инструменты сайта


rowset-definition

Это старая версия документа!


Декларативное описание набора строк rowset

lss

Введение

Декларативное описание набора строк rowset - XML описание, по которому строются экземпляры наборов строк, привязанные к экранной форме. Описание набора строк – это описание поддерживаемых им запросов и список полей.

Подробнее

При создании набора строк на клиенте у сервера запрашивается его описание. Декларативное описание набора строк rowset запрашивается у сервера 2 раза

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

Ориентировочный вид декларативного описания таков:

<rowset 
  (name|rowset)="<имя набора строк>" 
  datasource="<имя источника данных>" 
  readonly="0|1"
  js_readonly="<JavaScript выражение>"

<!---
  autorefresh="<автоперечитка в секундах>"
  autorefreshrow="<автоперечитка в секундах>"
  ignoreerror="0|1"
-->

  js_refresh="<JavaScript выражение, изменение которого автоматически вызывает перечитку>"

  parent.row.type="<допустимый row.type узла родительского набора строк>"
  parent.sync.row.type="<допустимые дочерние типы узлов через ;>"
  parent.sync.field.icon="<имя поля, задающего иконку синхронизируемого узла>"
  parent.sync.field.empty="<имя поля, задающего признак row.empty синхронизируемого узла>"
  parent.sync.field.final="<имя поля, задающего признак row.final синхронизируемого узла>"

  anketa="0|1"
  
  filter="0|1"
  filter.autorefresh="1|0"
  
  paginator.count="0|<кол-во строк в странице>"
  
  row.focus.id="<id для первого позиционирования>"
  row.focus.path="<path для первого позиционирования (через ;)>"
  
  evt_onnavigate="<имя запроса>"
  js_onnavigate="<JavaScript выражение>"
  
  mark.rowset="<имя источника данных для хранения пометок>"
  mark.rowset.fieldmark="<имя поля для id пометки>"
  mark.rowset.fieldtype="<имя поля для row.type>"

  mark.all="0|1 (пометить все после первого refresh)"
>
  
  <autoexec
    enabled="1|0"
    request="refresh|refreshrow|<любой запрос>"
    mode="timeout|polling|socket"
    timeout="<кол-во секунд между перечитками, для method=timeout>"
    url="<url соединения, для mode=polling или socket>"
    ignoreerror="0|1"
  >
    <param name="<имя параметра>" value="<значение параметра>"/>
    ...
    <param name="<имя параметра>" value="<значение параметра>"/>
  </autoexec>
  
  <section 
    row.type="<тип узла>"
    field.name="<имя поля>"
    field.description="<имя поля>"
    field.form="<имя поля>"
    field.params="<имя поля>"
    default.icon="<иконка по умолчанию>" 
    default.final="0|1"
  >

    <requests>
      <params>
        <param 
          (name|param)="<имя параметра>" 
          value="<значение>" 
          js_value="<JavaScript выражение>" 
          type="string|memo|date|num|check|ref"
          enabled="1|0" 
          js_enabled="<JavaScript выражение>"
          (skipempty|notempty)="0|1"
        />
        ...
        <param/>
      </params>
    
      <request 
        (name|request)="<имя запроса>" 
        mode="<подрежим запроса>"
        enabled="0|1" 
        js_enabled="<JavaScript выражение>" 
        js_caption="<JavaScript выражение>" 
        js_icon="<JavaScript выражение>" 
        caption="<текст>" 
        icon="<иконка>" 
        timeout="<время ожидания ответа>"
        sync="0|1"
      >
        <params>
          <param 
            (name|param)="<имя параметра>" 
            value="<значение>"
            js_value="<JavaScript выражение>" 
            type="string|memo|date|num|check|ref"
            enabled="1|0" 
            js_enabled="<JavaScript выражение>"
            (skipempty|notempty)="0|1"
          />
          ...
          <param/>
        </params>
      </request>
      ...
      <request/>
    </requests>
    
    <fields>
      <field
        (name|field)="<имя поля>"
        enabled="0|1"
        type="string|password|memo|date|num|check|ref|list|radio|icons|multilist|multicheck|multitree|html"
        list="code=value;item1;item2;item3;...;itemN"
        listfield="<имя поля со списком допустимых значений id=value;id=value>"
        listrowset="<имя источника данных, со списком допустимых значений>"
        basetype="string|num"
        triplex="0|1"
        dlgstyle="auto|list|check"
        size="small|medium|large"
        caption="<заголовок>"
        visible="0|1"
        js_visible="<JavaScript выражение>"
        readonly="0|1"
        js_readonly="<JavaScript выражение>"
        notnull="0|1"
        maxlength="<максимальное кол-во символов>"
        width="<ширина при отображении: px, pt или %>"
        dlgwidth="<ширина диалога при отображении: px, pt или %>"
        len="<длина для отображения, в символах>"
        default="<значение по умолчанию>"
        rows="<высота в строках для многострочных редакторов>"
        maxrows="<максимально допустимая высота в строках для многострочных редакторов>"
        dec="<кол-во знаков после запятой>"
        hidezero="0|1"
        stretch="0|1"
        refid="<имя поля справочника>"
        refname="<имя поля в источнике данных справочника - для переноса>"
        reftext="<имя поля в источнике данных справочника - для отображения в списке>"
        save="0|1"
        enter="0|1" - для memo Enter как перевод строки (иначе переход на следующее поле)
        nowrap="0|1" - отображать без переноса (в grid одной строкой)
        
        onaction="<текст запроса>"
        js_onaction="<JavaScript выражение>"
      >
        <ref 
          datasource="<имя источника>" 
          row.type="<для деревьев, подходящие типы узлов через ;>" 
          
          form="<имя модальной формы справочника>"
          form.result.mode="result_mode"
          form.result.value="result_value"
        >
          <param (name|param)="<имя параметра>" js_value="<JavaScript выражение>"/>
          ...
          <param/>
          
          <result name="<имя возвращаемого параметра>" value=""/>
          ...
          <result/>
        </ref>
        <change>
          <clear (name|field)="<имя очищаемого поля>"/>
          ...
          <clear/>
          
          <param (name|param)="<имя параметра>" js_value="<JavaScript выражение>"/>
          ...
          <param/>
        </change>
      </field>
      ...
      <field/>
    </fields>
    
    <marked>id1,id2,id3,...,idN</marked>
	
  </section>
  
  <childs>
    Список дочерних наборов строк
  </childs>
  
</rowset>

Атрибуты набора строк

Атрибуты набора строк имеют следующий смысл:

  • readonly - если параметр равен 1 то набор строк нельзя править. Часто формируется внутри скрипта источника данных, исходя из информации о правах текущего пользователя.
  • filter - если 1, то набор строк используется как фильтр, задающий условия для дочерних наборов строк. Его особенности:
    • Никак напрямую не взаимодействует с сервером (на сервере ему не соответствует никакого источника данных)
    • Полностью описывается в экранной форме
    • Всегда корневой: не может иметь родительского набора строк
    • Содержит одну и только одну строку, запрещена вставка и удаление строк
    • Значения полей проинициалезированны параметрами default из описаний полей
    • На каждое изменение любого поля автоматически производится перечитка дочерних наборов строк, такое поведение можно отменить параметром filter.autorefresh=0

Секция <scripts>

Секция <scripts> предназначена для описания кода JavaScript функций, нужных для вычисления динамических выражений. Обычно бывает ненужна.

Секция <requests>

Секция <requests> предназначена для описания поддерживаемых источником данных запросов. Там должны быть перечислены все допустимые для источника данных запросы. Единственное исключение - запрос request name=«change» может быть описан внутри поля, изменение которого должно инициализировать выполнение этого запроса.

В описании запроса используются следующие атрибуты:

  • name|request - имя запроса
  • enabled – доступность выполнения запроса, по умолчанию доступно
  • js_ensbled – выражение JavaScript динамически определяющее доступность выполнения запроса для текущего контекста.
  • icon - иконка для обозначения операции

Передаваемые запросу параметры описываются в секциях <params> запроса.

Особым образом обрабатываются параметры секции <params> набора строк. Описанные там параметры передаются всем запросам, и их описания имеют более высокий приоритет, чем описание параметров внутри запроса. Эту секцию добно использовать для подстройки поведения набора строк под контекст использования в экранной форме.

Атрибуты узла <param> имеют следующий смысл:

  • name|param – имя параметра
  • value - значение параметра
  • js_value – выражениена JavaScript, позволяющее динамически вычислить значение параметра по контексту.
  • type - тип для приведения

Для упрощения описания источника данных, при объявлении параметров действуют следующие умолчания:

  • Значение id=«id текущей строки» всегда автоматически вычисляется и передается запросу, его не надо специально объявлять.
  • Для запроса save значения отредактированных и еще пока не сохраненных полей, текущей строки источника данных, автоматически вычисляются и передаются в запрос, их не надо специально объявлять.
  • Для передачи запросу значения поля текущей строки источника данных достаточно в атрибуте name указать имя поля, а js_value не указывать.

Запрос change описывается внутри поля, при изменении которого вызывается. Его не нужно описывать в списке операций. Ему всегда передается текущее значение поля, в котором он объявлен

Описание полей источника данных

Имя поля задается значением атрибута field

Рассмотрим особенности реализации типов данных для полей:

  • string – строка, просмотр и редактирование однострочным редактором
  • memo – многострочная строка
  • num – число в LSS формате
  • date – дата в LSS формате
  • check – логическое значение в LSS формате
  • refname – поле выбирается из справочника, для описания необходимо задать refid – имя поля ссылки на строку справочника и refname – имя поля внутри справочника.
  • refid – поле ссылки на строку справочника. Обязательно должен присутствовать дочерний узел <ref> с описанием обращения к источнику данных (запрос request=«select»), возвращающего строки справочника.
  • multilist, multicheck – поле содержит значения ссылок на строки справочника, через запятую.
    • допустимые значения могут быть заданы параметром list в виде: id1=value1;id2=value2;id3=value3;…;idN=valueN
    • допустимые значения могут быть заданы параметром listfield, содержащем имя поля, в котором хранятся значения в виде: id1=value1;id2=value2;id3=value3;…;idN=valueN
    • допустимые значения могут быть заданы посредством дочернего узла <ref> с описанием обращения к источнику данных (запрос request=«refresh»), возвращающего строки справочника. Используются параметры: refname, reftext
    • допустимые значения могут быть заданы параметром listrowset, содержащим имя источника данных, содержащего начитанные значения. Используются параметры: refname, reftext.

Атрибут visible задает значение по умолчанию для видимости поля во всех строках. Если параметр не задан, то считается 1 (поле видимо). Если видимость поля зависит от контекста, то в атрибутах конкретного поля внутри конкретной строки можно задать параметр visible, который перешибет в этой строке значение, заданное для всей колонки.

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

Атрибут notnull задает требование непустого значения для поля.

Атрибут save=«1» - принудительное сохранение строки при изменении поля

Раздел autoexec

Этот раздел позволяет периодически вызывать указанный в разделе запрос

  <autoexec
    enabled="1|0"
    request="<имя запроса>"
    mode="timeout|polling|socket"
    timeout="<кол-во секунд>"
    url="<url соединения, для mode=polling или socket>"
    ignoreerror="0|1"
  >
    <param name="<имя параметра>" value="<значение параметра>"/>
    ...
    <param name="<имя параметра>" value="<значение параметра>"/>
  </autoexec>

Описание параметров

  • enabled=«1|0» - по умолчанию включен, позволяет заблокировать autoexec
  • request=«<имя запроса>» - выполняемый запрос, обычно refresh или refreshrow, но можно любой другой, например объявленный на уровне формы
  • ignoreerror=«0|1» - по умолчанию выключен, позволяет игнорировать ошибки сервера, возникающие при выполнении запроса
  • mode - способ управления вызовом запроса

mode=timeout

В этом режиме запрос вызывается периодически, через каждые timeout секунд

  <autoexec
    enabled="1|0"
    request="refresh|refreshrow|<любой запрос>"
    mode="timeout"
    timeout="<кол-во секунд между перечитками>"
    ignoreerror="0|1"
  >
  </autoexec>

mode=polling

В этом режиме запрос вызывается по указанию сервера, longpolling. Для реализации такого способа достаточно Apache + PHP, оповещение работает по http

Клиент создает и держит с сервером продолжительное, заданное параметром timeout (30-300 секунд) http соединение. Сервер периодически, например раз в секунду, проверяет наличие интересующего клиента события. При возникновении события, возвращает клиенту строку 1 и завершается. Если за заданное timeout время событие не возникло, то серверное соединение завершается, ничего не сообщая клиенту. А клиент повторно создает новое соединение и ждет ответа.

  <autoexec
    enabled="1|0"
    request="<имя запроса>"
    mode="polling"
    timeout="<время ожидания polling запроса>"
    url="<url polling соединения>"
    ignoreerror="0|1"
  >
    <param name="<имя параметра>" value="<значение параметра>"/>
    ...
    <param name="<имя параметра>" value="<значение параметра>"/>
  </autoexec>
  • url - http адрес polling соединения
  • timeout - время ожидания для polling соединения
  • параметры param - добавляются в url polling запроса

Пример реализации polling сервиса на PHP

<?php
class ServiceAutoExecPolling extends ServiceController{
	public function getParams() {
		$result=array();
		$result['format']='text';
		$result['timeout']=$_REQUEST['timeout']??30;
		return $result;
	}
	
/** Формирование результата запроса
 *
 * @param	array	$params параметры
 * @return	string	результат
 */
	public function getResult($params) {
		$result='';
		$timeout=$params['timeout'];
		//предельное время выполнения скрипта
		ini_set('max_execution_time', $timeout+5);

		for($i=0; $i<$timeout; $i++) {
			//проверка на наличие соединения, прекращение выполнения скрипта при разрыве
			echo ''; ob_flush(); flush();
			
			if ($this->test()) {
				$result=1;
				break;
			}
			sleep(1);
		}
		return $result;
	}
	
/** Проверка возникновения события
 *
 * @return	boolean	наличие интересующего клиента события
 */
	protected function test() {
		return false;
	}
}
return new ServiceAutoExecPolling();

Некоторые важные особенности реализации на PHP:

  • На входе в сервис автоматически приходит параметр timeout - время выполнения в секундах. Под него сервис должен подстроиться
  • Необходимо предотвратить остановку работы PHP скрипта Apache по max_execution_time, для этого max_execution_time должно быть больше, чем timeout
  • Необходимо останавливать PHP скрипт при разрыве соединения с клиентом. Для этого надо тестировать наличие соединения, пытаясь отправить клиенту сообщения, пустое сообщение достаточно для тестирования соединения.
  • При возникновении события надо послать клиенту 1 и остановить выполнение PHP скрипта
  • При превышении времени необходимо остановить работу PHP скрипта, ничего не отправляя клиенту
rowset-definition.1772039544.txt.gz · Последнее изменение: 2026/02/25 20:12 — madmin

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki