This commit is contained in:
msyu
2025-08-19 17:18:23 +03:00
commit 7dfd93d699
91 changed files with 7376 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
<cfsilent>
<!---Замещает любую переменную (*** небезопасно) тега layout:page --->
<!---Тег layout:page проглатывает собственный контент, и вместо него после закрытия выводит разметку на основании атрибутов (при открытии тега он формирует переменные - фрагменты разметки - по шаблону) и вложенных тегов layout:attribute (которые по закрытии тега на самом деле перезаписывают переменные в layout:page).
Вложенные теги удобны, чтобы передавать читабельную разметку, а не строку в кавычках.--->
<cfparam name="ATTRIBUTES.name"/><!---имя переменной layout:page, чаще всего title, controls--->
<!--- ATTRIBUTES.value --->
<cfparam name="ATTRIBUTES.append" default=""/><!---before,after--->
<cfif thisTag.executionMode IS "end">
<cfassociate basetag="cf_page"/>
<cfset layoutTemplate=getBaseTagData('cf_page',1)/>
<cfif structKeyExists(ATTRIBUTES, "value")>
<cfset value=ATTRIBUTES.value/>
<cfelse>
<cfset value=thisTag.generatedContent/>
</cfif>
<!---ниже в комментариях предполагается, что мы меняем фрагмент разметки, например, controls, но на самом деле это может быть любая переменная тега layout:page--->
<cfif structKeyExists(layoutTemplate,"#ATTRIBUTES.name#") AND lcase(ATTRIBUTES.append) EQ "before">
<!---дописать в начало фрагмента разметки с именем name, сгенерированного layout:page, например, controls--->
<cfset "layoutTemplate.#ATTRIBUTES.name#" = value & layoutTemplate["#ATTRIBUTES.name#"]/>
<cfelseif structKeyExists(layoutTemplate,"#ATTRIBUTES.name#") AND lcase(ATTRIBUTES.append) EQ "after">
<!---дописать в конец фрагмента разметки с именем name,, сгенерированного layout:page, например, controls--->
<cfset "layoutTemplate.#ATTRIBUTES.name#" = layoutTemplate["#ATTRIBUTES.name#"] & value/>
<cfelse>
<!---заменить фрагмент разметки с именем name, сгенерированный layout:page--->
<cfset "layoutTemplate.#ATTRIBUTES.name#"= value/>
</cfif>
<cfset thisTag.generatedContent=""/>
</cfif>
</cfsilent>
+43
View File
@@ -0,0 +1,43 @@
<cfsilent>
<cfimport prefix="m" taglib="../lib"/>
<cfimport prefix="c" taglib="../lib/controls"/>
<!---*** идея включить титул в метаданные была не совсем пустой, но когда титул определяется в селекте, это не слишком удобно --->
<cfassociate basetag="cf_grid_head" datacollection="headersArray"/>
<cfset envelope=getBaseTagData('cf_grid_head',1)/>
<cfparam name="ATTRIBUTES.title" type="string" default="#envelope.ATTRIBUTES.titleMap[ATTRIBUTES.name].title#"/>
<cfparam name="ATTRIBUTES.name" type="string"/><!--- Заголовок указвается на том поле, по которому будет сортировка, а не на том, которе отображается --->
<cfparam name="ATTRIBUTES.arrows" type="boolean" default="Yes"/>
<cfset attributeList="name,arrows,title"/>
<!--- В данном случае реализован подход: дополнительные атрибуты передаются вниз.
Другой вариант - создавать атрибут extra, в который писать суффикс QueryString.
Первый подход, использованный здесь, позволяет иметь доступ к дополнительным атрибутам, но непонятно, зачем - ведь их имена все равно неизвестны.
Очевидный минус этого подхода - возможный конфликт имен с именами существующих атрибутов --->
<cfset extraAttributes=structNew()/>
<!--- дополнительные атрибуты родительского тега--->
<cfif StructKeyExists(envelope, "extraAttributes") AND isStruct(envelope.extraAttributes)>
<cfloop collection=#envelope.extraAttributes# item="attr">
<cfif NOT listFindNoCase(attributeList, attr)><!--- проверка относительно локальных атрибутов, чтобы их не перетереть--->
<cfset val="#structFind(envelope.extraAttributes, attr)#"/>
<cfif IsSimpleValue(val)>
<cfset structInsert(extraAttributes, attr, val)/>
</cfif>
</cfif>
</cfloop>
</cfif>
<cfloop collection=#ATTRIBUTES# item="attr">
<cfif NOT listFindNoCase(attributeList, attr)>
<cfset val="#structFind(ATTRIBUTES, attr)#"/>
<cfif IsSimpleValue(val)>
<cfset structInsert(extraAttributes, attr, val, "Yes")/><!--- локальные атрибуты перетрут родительские --->
</cfif>
</cfif>
</cfloop>
</cfsilent><cfif thisTag.executionMode is "end"><cfoutput>#ATTRIBUTES.title#
<cfif ATTRIBUTES.arrows><c:order_arrows sortArray=#envelope.ATTRIBUTES.sortArray# n=#envelope.ATTRIBUTES.titleMap[ATTRIBUTES.name].ordinal# attributeCollection=#extraAttributes#/></cfif></cfoutput></cfif>
+10
View File
@@ -0,0 +1,10 @@
<!--- It is strongly recommended to keep this tag closed. Unclosed tag generates output into the variable ATTRIBUTES.output only, which may be confusing --->
<cfif thisTag.executionMode IS "end" OR NOT thisTag.hasEndTag>
<cfparam name="ATTRIBUTES.backUrl" type="string" default="."/>
<cfparam name="ATTRIBUTES.enable" type="boolean" default="No"/>
<cfoutput>
<button type="submit" name="save" class="maincontrol"<cfif NOT ATTRIBUTES.enable> disabled</cfif>>#request.i18("Сохранить","Save")#</button>
<button type="submit" name="saveAndClose" class="maincontrol"<cfif NOT ATTRIBUTES.enable> disabled</cfif>>#request.i18("Сохранить и закрыть","Save and Close")#</button>
<button type="button" name="close" class="maincontrol" onClick="document.location.href='#ATTRIBUTES.backUrl#'">#request.i18("Закрыть","Close")#</button>
</cfoutput>
</cfif>
+10
View File
@@ -0,0 +1,10 @@
<cfsilent>
<cfparam name="ATTRIBUTES.title" default=""/>
<!---
<cfset var content=thisTag.generagedContent/>
--->
</cfsilent><!---
---><cfif thisTag.executionMode is "start"><div class="tr">
<div class="th"><cfoutput>#ATTRIBUTES.title#</cfoutput></div><div class="td">
<cfelseif thisTag.executionMode is "end"></div></div></cfif>
+8
View File
@@ -0,0 +1,8 @@
<!--- It is strongly recommended to keep this tag closed. Unclosed tag generates output into the variable ATTRIBUTES.output only, which may be confusing --->
<cfif thisTag.executionMode IS "end" OR NOT thisTag.hasEndTag>
<cfparam name="ATTRIBUTES.backUrl" type="string" default=""/>
<cfoutput>
<button type="submit" name="saveAndClose" class="maincontrol">#request.i18("Применить","Apply")#</button>
<button type="submit" name="resetAndClose" class="maincontrol">#request.i18("Снять","Reset")#</button>
<button type="button" name="close" onClick="document.location.href='#ATTRIBUTES.backUrl#'" class="maincontrol">#request.i18("Закрыть","Close")#</button></cfoutput>
</cfif>
+24
View File
@@ -0,0 +1,24 @@
<!--- It is strongly recommended to keep this tag closed. Unclosed tag generates output into the variable ATTRIBUTES.output only, which may be confusing --->
<!---v0.2 10:07 02.01.2019 - skipped url params--->
<cfif thisTag.executionMode IS "end" OR NOT thisTag.hasEndTag>
<cfparam name="ATTRIBUTES.filterUrl" type="string" default=""/>
<cfparam name="ATTRIBUTES.filter" type="struct" default=#structNew()#/>
<cfparam name="ATTRIBUTES.fwx" type="string" default=""/>
<cfset qString="#ATTRIBUTES.fwx#"/>
<!---Чтобы передавать параметры в URL (и не пользоваться сессией), надо правильно форматировать параметры всех типов--->
<!--- <cfloop collection=#ATTRIBUTES.filter# item="item">
<cftry>
<cfset fltr=structFind(ATTRIBUTES.filter,item)/>
<cfset qString=listAppend(qString, "#item#=#fltr.val#", "&")/>
<cfcatch type="ANY"></cfcatch>
</cftry>
</cfloop>--->
<cfset filterOn=request.filterOn(ATTRIBUTES.filter)/>
<!--- actually, any non-empty string can be assigned to reset_filter --->
<cfoutput><a href="#ATTRIBUTES.filterUrl#?#qString#"><cfif filterOn><b>#request.i18("Фильтр...","Filter")#</b><cfelse>#request.i18("Фильтр","Filter")#</cfif></b></a>
<cfif filterOn><a href="#request.thisPage#?reset_filter=yes">(#request.i18("снять","reset")#)</a></cfif></cfoutput>
</cfif>
+18
View File
@@ -0,0 +1,18 @@
<cfsilent>
<cfparam name="ATTRIBUTES.titleMap" default=#structNew()#/>
<cfparam name="ATTRIBUTES.sortArray" default=#arrayNew(1)#/>
<cfset attributeList="titleMap,sortArray"/>
<cfset extraAttributes=structNew()/>
<cfloop collection=#ATTRIBUTES# item="attr">
<cfif NOT listFindNoCase(attributeList, attr)>
<cfset val="#structFind(ATTRIBUTES, attr)#"/>
<cfif IsSimpleValue(val)>
<cfset structInsert(extraAttributes, attr, val)/>
</cfif>
</cfif>
</cfloop>
</cfsilent><!---
---><cfif thisTag.executionMode is "start"><tr><cfelseif thisTag.executionMode is "end"></tr></cfif>
+82
View File
@@ -0,0 +1,82 @@
<cfsilent>
<cfimport prefix="m" taglib="../lib"/>
<cfimport prefix="c" taglib="../lib/controls"/>
<cfparam name="ATTRIBUTES.useSummary" default="yes"/>
<cfparam name="ATTRIBUTES.addtionalUrlParams" type="string" default=""/>
<cfparam name="ATTRIBUTES.self" default=""/>
<cfparam name="ATTRIBUTES.recordCount" default="0"/>
<cfparam name="ATTRIBUTES.totalCount" default="0"/>
<cfparam name="ATTRIBUTES.recordsPerPage" default="500"/>
<cfparam name="ATTRIBUTES.footerOut" default=""/>
<cfparam name="ATTRIBUTES.excelLink" default="No"/>
<cfparam name="ATTRIBUTES.jsonLink" default="No"/>
<cfparam name="ATTRIBUTES.buttonNew" default="No"/>
<cfparam name="ATTRIBUTES.buttonNewTitle" default="Создать"/>
<cfparam name="ATTRIBUTES.urlNew" default=""/>
<cfset UrlSuffix=""/>
<cfif len(ATTRIBUTES.addtionalUrlParams) GT 0>
<cfset UrlSuffix="&#ATTRIBUTES.addtionalUrlParams#"/>
</cfif>
<cfif len(ATTRIBUTES.self) GT 0>
<cfset UrlSuffix="&track=#ATTRIBUTES.self#"/>
</cfif>
<c:paginator
thisPage=#request.thisPage#
recordCount=#ATTRIBUTES.recordCount#
recordsPerPage=#ATTRIBUTES.recordsPerPage#
self=#ATTRIBUTES.self#
addtionalUrlParams=#ATTRIBUTES.addtionalUrlParams#
output="paginator"/>
</cfsilent>
<cfoutput>
<cfif ATTRIBUTES.useSummary>
<div class="table wide" style="margin:3px 0;">
<div class="td" style="height:2em; line-height:2em; padding-left:0; vertical-align:middle;">
<cfif ATTRIBUTES.buttonNew>
<button type="button" class="maincontrol" onclick="document.location.href='#ATTRIBUTES.urlNew#'" style="margin:.0 1.5em 0 0;">
<a href="#ATTRIBUTES.urlNew#">#ATTRIBUTES.buttonNewTitle#</a>
</button>
<cfelse>
<div style="display:inline-block; width:1em;"/>&nbsp;</div>
</cfif>
<cfif (ATTRIBUTES.recordCount GE 0)>
Выбрано <b>#ATTRIBUTES.recordCount#</b>
<cfif (ATTRIBUTES.totalCount GE 0)>
из <b>#ATTRIBUTES.totalCount#</b>
</cfif>
</cfif>
<cfif ATTRIBUTES.excelLink>
<a href="#request.thisPage#?output_xls#UrlSuffix#" title="экспорт в Excel" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/xls.gif" style="vertical-align:text-bottom;"/></a>
</cfif>
<cfif ATTRIBUTES.jsonLink>
<a href="#request.thisPage#?output_json#UrlSuffix#" title="экспорт в json" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/json.svg" style="vertical-align:text-bottom;" width="13" height="13"/></a>
</cfif>
</div>
<div class="td r">
#paginator.links#
</div>
</div>
</cfif>
</cfoutput>
<cfif len(ATTRIBUTES.footerOut)>
<cfsavecontent variable="CALLER.#ATTRIBUTES.footerOut#">
<cfoutput>
<div class="wide r" style="margin:0.3em">
#paginator.links#
</div>
</cfoutput>
</cfsavecontent>
</cfif>
<cfexit method="exittag"/>
+99
View File
@@ -0,0 +1,99 @@
<cfsilent>
<cfparam name="ATTRIBUTES.qRead" type="query"/>
<cfparam name="ATTRIBUTES.convertSnakeToCamel" type="boolean" default=true/>
<!---<cfdump var=#qRead#/>
<cfdump var=#ATTRIBUTES.titleMap#/>
<cfabort/>--->
<cffunction name="snake2camel"
returntype="string"
output="false"
hint="convert snake style name to camel style name">
<cfargument name="snake" type="string" required="true" />
<cfreturn #reReplace(ARGUMENTS.snake,"_([a-z])","\u\1","ALL")#/>
</cffunction>
<cffunction name="camel2snake"
returntype="string"
output="false"
hint="convert camel style name to snake style name">
<cfargument name="camel" type="string" required="true" />
<cfreturn #reReplace(ARGUMENTS.camel,"([A-Z])","_\l\1","ALL")#/>
</cffunction>
<!--- <cffunction name="escape4json"
returntype="string"
output="false"
hint="escape string for json format">
<cfargument name="s" type="string" required="true" />
<cfreturn #reReplace(ARGUMENTS.camel,"([A-Z])","_\l\1","ALL")#/>
</cffunction> --->
<!--- <cffunction name="query2array">
<cfargument name="qry" type="query" required="true"/><!--- column names should not contain commas --->
<cfargument name="convertSnakeToCamel" type="boolean" default=true/><cfsilent>
</cffunction> --->
<!--- <cffunction name="query2json"
output="true"
hint="print query in json format as array of structures">
<cfargument name="qry" type="query" required="true"/><!--- column names should not contain commas --->
<cfargument name="convertSnakeToCamel" type="boolean" default=true/><cfsilent>
<cfset var columnsIn=#qry.columnList()#/>
<cfset var columnsOut=""/>
<cfif arguments.convertSnakeToCamel>
<cfloop list=#columnsIn# item="col">
<cfset columnsOut=listAppend(columnsOut,snake2camel(col))/>
</cfloop>
<cfelse>
<cfset columnsOut=#columnsIn#/>
</cfif>
</cfsilent>[<cfoutput query=#qry#>{<cfloop index="i" from="1" to=#listLen(columnsOut)#>"#listGetAt(#columnsOut#,i)#":"#qry[listGetAt(#columnsIn#,i)]#"<cfif #i# LT #listLen(columnsOut)#>,</cfif></cfloop>}<cfif #qry.currentRow()# LT #qry.recordCount()#>,</cfif></cfoutput>]
</cffunction> --->
<cffunction name="query2json"
output="false"
hint="print query in json format as array of structures">
<cfargument name="qry" type="query" required="true"/><!--- column names should not contain commas --->
<cfargument name="convertSnakeToCamel" type="boolean" default=true/>
<cfset var columnsIn=#arguments.qry.columnList()#/>
<cfset var columnsOut=""/>
<cfif arguments.convertSnakeToCamel>
<cfloop list=#columnsIn# item="col">
<cfset columnsOut=listAppend(columnsOut,snake2camel(col))/>
</cfloop>
<cfset var outArray=arrayNew(1)/>
//copy fields to structure, renaming fields, this preserves data type
<cfloop query=#arguments.qry#>
<cfset var structRow=structNew()/>
<cfloop index="i" from="1" to=#listLen(columnsOut)#>
<cfset structInsert(structRow,"#listGetAt(#columnsOut#,i)#",arguments.qry["#listGetAt(#columnsIn#,i)#"])/>
</cfloop>
<cfset arrayAppend(outArray,structRow)/>
</cfloop>
<cfreturn serializeJSON(outArray)/>
<cfelse>
<cfreturn serializeJSON(arguments.qry,"struct")/>
</cfif>
</cffunction>
<!--- <cfset request.camel2snake = camel2snake/> --->
<!---<cfsavecontent variable="strXmlData">--->
<!--- <cfif ATTRIBUTES.snake2camel>
<cfloop collection=#ATTRIBUTES.qRead.columnList# item="col">
<cfset queryRenameColumn(ATTRIBUTES.qRead,col,snake2camel(col))/>
<cfset ATTRIBUTES.qREAD.
</cfloop>
</cfif> --->
<cfset msStartAt=getTickCount()/>
</cfsilent><cfcontent
type="application/json"
/><cfoutput>#query2json(ATTRIBUTES.qRead,ATTRIBUTES.convertSnakeToCamel)#</cfoutput><!---
,<cfoutput>"duration":"#(getTickCount()- msStartAt)#"</cfoutput>} --->
<cfexit method="exittag"/>
+9
View File
@@ -0,0 +1,9 @@
<cfif thisTag.executionMode IS "end" OR NOT thisTag.hasEndTag>
<cfoutput>
&nbsp;
&nbsp;
&nbsp;
<a href="?language=ru"<cfif request.language EQ 'ru'> style="font-weight:bold;"</cfif>>Ru</a>
<a href="?language=en"<cfif request.language EQ 'en'> style="font-weight:bold;"</cfif>>En</a>
</cfoutput>
</cfif>
+240
View File
@@ -0,0 +1,240 @@
<cfsilent><!--- *** http://www.bennadel.com/blog/457-a-case-against-coldfusion-custom-tag-page-wrappers.htm--->
<cfimport prefix="layout" taglib="../layout"/>
<cfimport prefix="c" taglib="../lib/controls"/>
<cfparam name="ATTRIBUTES.section" type="string"/>
<cfparam name="ATTRIBUTES.closeForm" type="boolean" default="No"/>
<cfparam name="title" default=""/><!---заголовок страницы, отображаемый в теле например, <h1>--->
<cfparam name="pageTitle" default="PAYG"/><!---заголовок окна браузера, в теге <title>--->
<cfparam name="controls" default=""/>
</cfsilent><cfsilent>
<!---Тег layout:page проглатывает собственный контент, и вместо него после закрытия выводит разметку на основании атрибутов (при открытии тега он формирует переменные - фрагменты разметки - по шаблону) и вложенных тегов layout:attribute (которые по закрытии тега на самом деле перезаписывают переменные в layout:page).
Вложенные теги удобны, чтобы передавать читабельную разметку, а не строку в кавычках.--->
<cfif thisTag.executionMode IS "start">
<!--- Формируется значение переменной controls--->
<!--- Но оно может быть переопределено вызовом layout:attribute в теле тега <layout:page>--->
<cfif #ATTRIBUTES.section# EQ "header">
<cfparam name="ATTRIBUTES.pageInfo" type="struct"/><!--- инициализируется вызывающей страницей --->
<cfsavecontent variable="controls">
<cfoutput>
<cfswitch expression=#ATTRIBUTES.pageInfo.getType()#>
<cfcase value="ls">
<layout:filter_link filterUrl="#ATTRIBUTES.pageInfo.entity#_filter.cfm" filter=#ATTRIBUTES.pageInfo.settings.filter# fwx="#ATTRIBUTES.pageInfo.track.fwx#" />
</cfcase>
<cfcase value="detail">
<layout:detail_buttons backUrl="#ATTRIBUTES.pageInfo.track.backUrl#" enable="#ATTRIBUTES.pageInfo.writePermitted()#"/>
<!---<cfset ATTRIBUTES.form="1"/>--->
</cfcase>
<cfcase value="filter">
<layout:filter_buttons backUrl="#ATTRIBUTES.pageInfo.track.backUrl#"/>
<!---<cfset ATTRIBUTES.form="1"/>--->
</cfcase><!--- *** not implemented
<cfcase value="del">
<layout:del_buttons backUrl="#ATTRIBUTES.pageInfo.track.backUrl#"/>
<cfset ATTRIBUTES.form="1"/>
</cfcase>--->
<cfdefaultcase>
<!---<cfthrow message="Unsupported page type" detail="Supported page types are ls, detail, filter, del"/>--->
</cfdefaultcase>
</cfswitch>
<!---<layout:language_switch/>--->
</cfoutput>
</cfsavecontent>
</cfif>
</cfif>
<!--- Переменную (фрагмент разметки) title по традиции заполняем в вызывающей странице через layout:attribute--->
</cfsilent><!---
<!---*******************************************--->
---><cfif thisTag.executionMode IS "end"><!---
---><cfsilent>
<!---никакая разметка из тела даннного тега не выводится,
вместо этого по закрытии тега им генерируется собственный контент--->
<!---внутри тега на странице определяются его параметры, некорректно названные атрибутами--->
<cfset thisTag.generatedContent=""/><!---
---></cfsilent><!---
---><cfswitch expression=#ATTRIBUTES.section#><!---
---><cfcase value="header"><cfsilent>
</cfsilent><!--- ----------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
---><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en" xml:lang="en" xmlns= "http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/><!--- this should be the first line in head --->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script type="text/javascript">
var timerStart = Date.now();
</script>
<!---<cfquery name="qUsr" datasource="#request.DS#">
select login, firstname, middlename, lastname from worker where id='#request.usr_id#'
</cfquery>--->
<title><cfoutput>#pageTitle#</cfoutput></title>
<link rel="shortcut icon" href="img/favicon.ico"/>
<!--- <link rel="stylesheet" href="style/fontawesome-all.css"/> --->
<link rel="stylesheet" type="text/css" href="style/web.css"/>
<!--- override layout header style --->
<!--- <cfswitch expression=#request.STAND#>
<cfcase value="DEV">
<style>.title, .main-controls {background-color:#aaf}</style>
</cfcase>
<cfcase value="TEST">
<style>.title, .main-controls {background-color:#9e9}</style>
</cfcase>
<cfcase value="PROD">
<style>.title, .main-controls {background-color:#faa}</style>
</cfcase>
<cfdefaultcase>
<style>.title, .main-controls {background-color:#aaa}</style><!--- без изменений --->
</cfdefaultcase>
</cfswitch> --->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.searchabledropdown.js"></script>
<script>
function resetListsById(id){
for (var i = 0, j = arguments.length; i < j; i++) {
try {
document.getElementById(arguments[i]).selectedIndex=-1;
} catch (e) {}
}
}
window.onload=function(){document.body.style.cursor='default';}
</script>
</head>
<body style="cursor:wait;"><a name="up"></a> <!--- <cfdump var=#ATTRIBUTES.pageInfo.writePermitted()#/> --->
<div class="page">
<div class="page-main">
<div class="menu noprint" style="margin:0; padding:0;/*border:1px solid red;*/">
<div class="fixed-menu" style="width:145px; height:100%; padding:0 0 0 0; --border:1px solid blue;" />
<a name="up"></a>
<!---<a id="lime_ref" href="http://root" style="display:inline-block; margin: 0; padding: 0 6px; height: 30px; width: 48px; margin: 5px 0 0 0;" title="Home"><img src="img/alarm-arrow-up-icon.png" style="margin: 0; padding: 0; height: 30px; margin: 5px 0 0 0;"/></a>
--->
<!--- <div style="width:20px; height:30px; margin: 5px; background: url('img/logo0.png') 0 0 no-repeat; background-size:contain; display:inline-block;"></div>--->
<div style="width:138px; height:30px; margin: 5px 0 0 5px; background: url('img/logo0.png') 0 0 no-repeat; background-size:contain; display:inline-block; -border:1px solid red;">
<p class="b r" style="color:white; margin:0 10px 10px 10px; font-size:130%;">
Отчет PAYG
</p>
</div>
<p style="color:lightgray; margin:10px 12px; text-align:right;">
<cfoutput>v.#request.APP_VERSION#</cfoutput>
</p>
<style>
.menu-items-container::-webkit-scrollbar {width: 10px; margin:10px;}
}
.menu-items-container::-webkit-scrollbar-track {
background-color: lightgray;
}
.menu-items-container::-webkit-scrollbar-thumb {
--background-color: rgb(97,127,136);/*lightgray*/;
--border-radius: 2px;
--border: 1px solid white;
}
</style>
<div class="menu-items-container" style="width:100%; height:100%; overflow:auto; scrollbar-width:thin; --border:1px solid green;">
<cfmodule template="../inc/menu.cfm" fwx="#ATTRIBUTES.pageInfo.track.fwx#" thisUrl="#ATTRIBUTES.pageInfo.track.thisUrl#"/>
<br/>
<br/>
<br/>
</div>
</div>
</div>
<!-- content -->
<div class="content">
<cfif isInstanceOf(ATTRIBUTES.pageInfo, "form_page_info")>
<cfoutput>
<form name="#ATTRIBUTES.pageInfo.formName#" action="#ATTRIBUTES.pageInfo.formAction#" method="#ATTRIBUTES.pageInfo.formMethod#" <!---style="height:100%;"---><cfif len(ATTRIBUTES.pageInfo.formEncType)> enctype="#ATTRIBUTES.pageInfo.formEncType#"</cfif>><!--- height:100% is required to make inner elements fill the container vertically ---><!--- but if we close the form in the middle of the page, layout is broken --->
</cfoutput>
</cfif>
<div class="header">
<div class="control-bar">
<!--- <div style="display:table-cell; width:23px; background: #ccc/*rgb(117,147,156)*/; border: 1px solid #bbb;"> --->
<!--- <div style="display:table-cell; width:23px; background: #0078c9; border: 1px solid #000;"> --->
<!--- <div style="display:table-cell; width:23px; background: #07b; border: 1px solid #000;"></div> --->
<!--- <div style="display:table-cell; width:3px;"></div> --->
<div class="title">
<cfoutput>#title#</cfoutput>
</div>
<div class="main-controls">
<cfoutput>#controls#</cfoutput>
</div>
</div><!--- control-bar --->
</div>
<div class="layout_vspacer"></div>
<cfif len(ATTRIBUTES.pageInfo.status.errorState)>
<span style="color:red"><cfoutput>#ATTRIBUTES.pageInfo.status.errorMessage#</cfoutput></span>
<cfexit method="exittag"/>
</cfif>
<!-- content -->
</cfcase><cfcase value="extension"><!--- -------------------------------------------------------------------------------------------- --->
<cfif ATTRIBUTES.closeForm></form></cfif>
</cfcase><cfcase value="footer"><!--- -------------------------------------------------------------------------------------------- --->
<!--/content -->
<cfif ATTRIBUTES.closeForm></form></cfif>
</div>
<!--/content -->
</div><!--- page main --->
<div class="page-footer noprint">
<div style="display:table-cell; padding:.5em; background-color:#555;">
<cftry>
<cfset pageTimeMs=GetTickCount()-request.startTickCount/>
<cfoutput><span title="page generation time">#pageTimeMs# ms</span></cfoutput>
<cfcatch type="any">request.startTickCount undefined</cfcatch>
</cftry>
<span id="load-time" title="page loading time"></span>
<script type="text/javascript">
window.onload=function() {
document.body.style.cursor='default';
document.getElementById("load-time").innerHTML = (Date.now()-timerStart) + " ms";
};
<!---alert(document.documentMode);// IE troubles --->
</script>
</div>
<div style="display:table-cell; padding: 3px;">
<div class="footer">
<cftry>
<cflock scope="session" type="readonly" timeout="3">
<cfif len(session.authentication_source)>
<cfoutput>authentication:#session.authentication_source#</cfoutput>&nbsp;
</cfif>
</cflock><cfcatch type="ANY"></cfcatch></cftry>
<a href="#up" class="up">вверх</a>
</div>
</div>
</div>
</div><!--- page --->
<!--- fixed-menu class is defined at the bottom of page, so in case of unhandled error menu is not fixed --->
<style>
div.fixed-menu { position:fixed;}
</style>
</body>
</html><!---
---></cfcase><cfdefaultcase><cfthrow message="Unsupported 'section' attribute value" detail="Supported section values are 'header','extension','footer'"></cfdefaultcase></cfswitch><!---
---></cfif>
+55
View File
@@ -0,0 +1,55 @@
<!---https://www.bennadel.com/blog/461-creating-microsoft-excel-documents-with-coldfusion-and-xml.htm--->
<!---*** locale-specific--->
<cfparam name="ATTRIBUTES.qRead" type="query"/>
<cfparam name="ATTRIBUTES.titleMap" type="struct"/>
<cfparam name="ATTRIBUTES.sheetTitle" type="string" default="Sheet1"/>
<cfparam name="ATTRIBUTES.filename" type="string" default="export.xls"/>
<cfset fieldArray=structSort(ATTRIBUTES.titleMap, "numeric", "ASC", "ordinal")/>
<cfsavecontent variable="strXmlData">
<cfoutput>
<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'><meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8"><meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>#ATTRIBUTES.sheetTitle#</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table><!---
<cfloop index="i" from="1" to=#structCount(ATTRIBUTES.titleMap)#>
<Column ss:Index="#i#"/>
</cfloop>
--->
<tr>
<cfloop from=1 to=#arrayLen(fieldArray)# index="i">
<cfset title=structFind(ATTRIBUTES.titleMap, fieldArray[i]).title/>
<th><cfif len(title)>#title#<cfelse>#fieldArray[i]#</cfif></th>
</cfloop>
</tr>
<cfloop query=#ATTRIBUTES.qRead#>
<tr>
<cfloop from=1 to=#arrayLen(fieldArray)# index="i">
<cfset data=#ATTRIBUTES.qRead[fieldArray[i]]#/>
<cftry>
<cfif isDate(data)><td>#dateFormat(data,'YYYY-MM-DD')#<cfif hour(data) GT 0 OR minute(data) EQ 0> #timeFormat(data,'HH:mm')#</cfif></td><cfelseif isNumeric(data)><td>#Replace(data, '.', ',')#</td><cfelse><td>#data#</td></cfif>
<cfcatch type="Any"><td>#data#</td></cfcatch>
</cftry>
</cfloop>
</tr>
</cfloop>
</table></body></html>
</cfoutput>
</cfsavecontent>
<cfheader
name="content-disposition"
value="attachment; filename=#ATTRIBUTES.filename#"
/>
<!---
When streaming the Excel XML data, trim the data and
replace all the inter-tag white space. No need to stream
any more content than we have to.
--->
<cfcontent
type="application/msexcel"
variable="#ToBinary( ToBase64( strXmlData.Trim().ReplaceAll( '>\s+', '>' ).ReplaceAll( '\s+<', '<' ) ) )#"
/><cfabort/>
<cfexit method="exittag"/>
+49
View File
@@ -0,0 +1,49 @@
<!---https://www.bennadel.com/blog/461-creating-microsoft-excel-documents-with-coldfusion-and-xml.htm--->
<cfparam name="ATTRIBUTES.qRead" type="query"/>
<cfparam name="ATTRIBUTES.titleMap" type="struct"/>
<cfparam name="ATTRIBUTES.sheetTitle" type="string" default="Sheet1"/>
<cfparam name="ATTRIBUTES.filename" type="string" default="export.xlsx"/>
<cfsavecontent variable="strXmlData">
<cfoutput>
<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>
<meta http-equiv="content-type" content="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
<head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>xlsWorksheetName</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head>
<body>
<table>
<tr>
<cfloop struct=#ATTRIBUTES.titleMap# item="field">
<th>#structFind(ATTRIBUTES.titleMap,field).title#</th>
</cfloop>
</tr>
<cfloop query=#ATTRIBUTES.qRead#>
<tr>
<cfloop struct=#ATTRIBUTES.titleMap# item="field">
<td>
#ATTRIBUTES.qRead[field]#
</td>
</cfloop>
</tr>
</cfloop>
</table>
</body>
</html>
</cfoutput>
</cfsavecontent>
<cfheader
name="content-disposition"
value="attachment; filename=#ATTRIBUTES.filename#"
/>
<!---
When streaming the Excel XML data, trim the data and
replace all the inter-tag white space. No need to stream
any more content than we have to.
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
--->
<cfcontent
type="application/vnd.ms-excel"
variable="#ToBinary( ToBase64( strXmlData.Trim().ReplaceAll( '>\s+', '>' ).ReplaceAll( '\s+<', '<' ) ) )#"
/>
<cfexit method="exittag"/>
+239
View File
@@ -0,0 +1,239 @@
<cfsilent>
<!---https://www.bennadel.com/blog/461-creating-microsoft-excel-documents-with-coldfusion-and-xml.htm--->
<!---порядок колонок, как в селекте, не управляется никак
Для определения порядка колонок используется поле ATTRIBUTES.titleMap.ordinal, возможно, не самый надежный способ
Можно попробовать использовать порядок колонок в массиве query --->
<cfparam name="ATTRIBUTES.qRead" type="query"/>
<cfparam name="ATTRIBUTES.titleMap" type="struct"/><!---see ../lib/data/field_set.cfm--->
<cfparam name="ATTRIBUTES.sheetTitle" type="string" default="Sheet1"/>
<cfparam name="ATTRIBUTES.filename" type="string" default="export.xlsx"/>
<cfset AVG_SYMBOL_WIDTH=6.5/>
<cfset MAX_COL_LENGTH=30/>
<cfset qRead=ATTRIBUTES.qRead/>
<!---<cfdump var=#qRead#/>
<cfdump var=#ATTRIBUTES.titleMap#/>
<cfabort/>
--->
<!---<cfsavecontent variable="strXmlData">--->
</cfsilent><cfheader
name="content-disposition"
value="attachment; filename=#ATTRIBUTES.filename#"
/><cfcontent
type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
/><cfoutput><?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<!---
This is the Workbook root element. This element
stores characteristics and properties of the
workbook, such as the namespaces used in
SpreadsheetML.
--->
<Workbook
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<!---
The first child element of the WorkBook element
is DocumentProperties. Office documents store
metadata related to the document&#8212;for example,
the author name, company, creation date, and
more in the DocumentProperties element.
--->
<DocumentProperties
xmlns="urn:schemas-microsoft-com:office:office">
<Author>xls-generator</Author>
<Company></Company>
</DocumentProperties>
<!---
The Styles node represents information related
to individual styles that can be used to format
components of the workbook.
--->
<Styles>
<!--- Basic format used by all cells. --->
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Top"/>
<Borders/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11"/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
<Style ss:ID="Th">
<Alignment ss:Horizontal="Center" ss:Vertical="Top"/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Bold="1"/>
</Style>
<Style ss:ID="Int">
<NumberFormat ss:Format="0" />
</Style>
<Style ss:ID="DateTime">
<NumberFormat ss:Format="dd/mm/yyyy\ hh:mm;@"/>
</Style>
<!---
<Style ss:ID="ShortDate">
<NumberFormat ss:Format="[ENG][$-409]d\-mmm\-yyyy;@" />
</Style>
<Style ss:ID="YesNo">
<NumberFormat ss:Format="Yes/No" />
</Style>
--->
</Styles>
<!---
This defines the first worksheeet and it's name.
We are only using one worksheet in this example,
but you could add more Worksheet nodes after
this one for multiple tabs. The "Name" attribute
here is the name that shows up in the tab.
--->
<Worksheet ss:Name="#ATTRIBUTES.sheetTitle#">
<Table
<!---
We need a column for each column of the
query. This attribute is required to be
correct. If the value here does NOT
match the data in Excel file, the
document will not render properly.
--->
ss:ExpandedColumnCount="#ListLen(qRead.ColumnList)#"
<!---
We need a row for every query record
plus one for the header row. Again, if
this value does not match what is in the
document, the excel file will not
render properly.
--->
ss:ExpandedRowCount="#(qRead.RecordCount + 1)#"
x:FullColumns="1"
x:FullRows="1">
<!---
Here, we can define general properties
regarding each column in the data output.
<Column ss:Index="1" ss:Width="30" />
<Column ss:Index="2" ss:Width="100" />
<Column ss:Index="3" ss:Width="42" />
<Column ss:Index="4" ss:Width="84" />
<Column ss:Index="5" ss:Width="66" />
<Column ss:Index="6" ss:Width="70" />--->
<cfsilent>
<cfset columns=arrayNew(1)/>
<cfset i=1/>
<cfloop struct=#ATTRIBUTES.titleMap# item="field">
<cfset col=structNew()/>
<cfset fieldSpec=structFind(ATTRIBUTES.titleMap, field)/>
<cfset col.name=field/>
<cfset col.title=fieldSpec.title/>
<cfif len(col.title) EQ 0>
<cfset col.title=col.name/>
</cfif>
<cfset col.titleLength=len(col.title)/>
<cfquery name="qLen" dbtype="query">
select coalesce(max(length(#field#)),0) as maxlen from qRead
</cfquery>
<cfset col.length=max(col.titleLength, qLen.maxLen)/>
<cfset col.cfSqlType="CF_SQL_VARCHAR"/>
<cfif structKeyExists(fieldSpec,"cfSqlType")>
<cfset col.cfSqlType=#fieldSpec.cfSqlType#/>
</cfif>
<cfswitch expression=#col.cfSqlType#><!---should use ## around variable name--->
<cfcase value="CF_SQL_BIGINT,CF_SQL_INTEGER,CF_SQL_SMALLINT,CF_SQL_TINYINT,CF_SQL_BIT,CF_SQL_NUMERIC,CF_SQL_DECIMAL,CF_SQL_REAL,CF_SQL_FLOAT,CF_SQL_DOUBLE">
<cfset col.ssType="Number"/>
</cfcase>
<cfcase value="CF_SQL_TIMESTAMP,CF_SQL_DATE,CF_SQL_TIME,CF_SQL_DATETIME">
<cfset col.ssType="DateTime"/>
</cfcase>
<cfdefaultcase>
<cfset col.ssType="String"/>
</cfdefaultcase>
</cfswitch>
<cfset columns[fieldSpec.ordinal]=col/><!---new col created at each iteration, so we have valid references--->
<cfset i=i+1/>
</cfloop>
</cfsilent>
<cfloop from=1 to=#arrayLen(columns)# index="i">
<cfif columns[i].ssType EQ "DateTime"><!--- timestamp string representation is too long, --->
<Column ss:Index="#i#" ss:Width="#round(min(columns[i].titleLength, MAX_COL_LENGTH)*AVG_SYMBOL_WIDTH)#" ss:AutoFitWidth="1"/>
<cfelse>
<Column ss:Index="#i#" ss:Width="#round(min(columns[i].length, MAX_COL_LENGTH)*AVG_SYMBOL_WIDTH)#" ss:AutoFitWidth="1"/>
</cfif>
</cfloop>
<!---
This is our header row. All cells in the
header row will be of type string.
--->
<Row>
<cfloop from=1 to=#arrayLen(columns)# index="i">
<Cell ss:StyleID="Th">
<Data ss:Type="String">#columns[i].title#</Data>
</Cell>
</cfloop>
</Row>
<cfflush/>
<cfloop query=#qRead#><!---
---><Row><!---
---><cfloop from=1 to=#ArrayLen(columns)# index="i"><!---
---><cfset field=columns[i].name/><!---
---><Cell<cfif columns[i].ssType EQ "DateTime"> ss:StyleID="DateTime"</cfif>><!---
---><cfif len(qRead[field])><Data ss:Type="#columns[i].ssType#"><!---no extra whitespace allowed here---><!---
---><cfswitch expression=#columns[i].ssType#><!---
---><cfcase value="DateTime"><!---
--->#dateFormat(qRead[field],"YYYY-MM-DD")#T#timeFormat(qRead[field],"HH:mm:ss.l")#<!---
---></cfcase><!---
---><cfcase value="Number"><!---
--->#qRead[field]#<!---
---></cfcase><!---
---><cfdefaultcase><!---
---><![CDATA[#request.clean4CDATA(qRead[field])#]]><!---
---></cfdefaultcase><!---
---></cfswitch><!---
---></Data></cfif><!---
---></Cell><!---
---></cfloop><!---
---></Row><!---
---></cfloop><!---
---></Table>
</Worksheet>
</Workbook>
</cfoutput>
<!---</cfsavecontent>--->
<!---
Define the way in which the browser should interpret
the content that we are about to stream.
--->
<!---<cfheader
name="content-disposition"
value="attachment; filename=#ATTRIBUTES.filename#"
/>--->
<!---
When streaming the Excel XML data, trim the data and
replace all the inter-tag white space. No need to stream
any more content than we have to..ReplaceAll( '>\s+', '>' ).ReplaceAll( '\s+<', '<' )
--->
<!---<cfcontent
type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
variable="#ToBinary( ToBase64( strXmlData.Trim()))#"
/>---><!---<cfabort/>--->
<cfexit method="exittag"/>