Изменения документа Инструкция по работе с разделом Трудозатраты
Редактировал(а) Кристина Гришкина 10.10.2025
От версии 3.1
отредактировано Кристина Гришкина
на 10.10.2025
на 10.10.2025
Изменить комментарий:
К данной версии нет комментариев
К версии 2.1
отредактировано Alexey Semenihin
на 10.10.2025
на 10.10.2025
Изменить комментарий:
Загрузить новое вложение Инструкция по работе с разделом Трудозатраты.docx
Сводка
-
Свойства страницы (3 изменено, 0 добавлено, 0 удалено)
Подробности
- Свойства страницы
-
- Автор документа
-
... ... @@ -1,1 +1,1 @@ 1 -xwiki:XWiki. grishkinakn1 +xwiki:XWiki.semenihinaa - Теги
-
... ... @@ -1,1 +1,0 @@ 1 -Списанное время|утвердить трудозатраты|фактические трудозатраты|экспорт трудозатрат|фактические часы|факт по задачам|фактическая стоимость|таймшиты|переработки - Содержимое
-
... ... @@ -1,5 +1,36 @@ 1 1 {{velocity}} 2 +## Макрос для отображения подстраниц с отображаемыми именами в алфавитном порядке 3 +#macro(displayDirectChildrenClean) 4 + #set ($currentPage = $doc.fullName) 5 + #set ($children = $xwiki.getDocument($currentPage).getChildren()) 6 + #if ($children.size() > 0) 7 + ## Создаем список для хранения пар (отображаемое имя, полное имя) 8 + #set ($childList = []) 9 + #foreach ($child in $children) 10 + #set ($childDoc = $xwiki.getDocument($child)) 11 + ## Получаем отображаемое имя (title), если оно не пустое, иначе используем имя документа 12 + #set ($displayName = $childDoc.getPlainTitle()) 13 + #if ($displayName == '') 14 + #set ($displayName = $childDoc.getName()) 15 + #end 16 + ## Добавляем пару в список 17 + #set ($discard = $childList.add({"displayName": $displayName, "fullName": $child})) 18 + #end 19 + ## Сортируем список по displayName 20 + #set ($sortedChildren = $sorttool.sort($childList, "displayName:asc")) 21 + ## Выводим отсортированный список 22 + #foreach ($item in $sortedChildren) 23 + [[$item.displayName>>$item.fullName]] 24 + #end 25 + #end 26 +#end 27 +## Выводим список 28 +#displayDirectChildrenClean() 29 +{{/velocity}} 2 2 31 + 32 +{{velocity}} 33 + 3 3 ## Подключаем необходимые JS/CSS для работы вкладок 4 4 $xwiki.jsfx.use('uicomponents/widgets/tabView.js', {'forceSkinAction': true, 'language': 'xwiki/2.1'}) 5 5 $xwiki.ssfx.use('uicomponents/widgets/tabView.css', true) ... ... @@ -15,12 +15,6 @@ 15 15 attachmentsTab.click(); 16 16 } 17 17 // Альтернативный вариант (если не сработал ID): 18 - else { 19 - var tabs = $$('.tab-menu a').find(function(tab) { 20 - return tab.textContent.trim().includes('Вложения'); 21 - }); 22 - if (tabs && tabs.length > 0) tabs[0].click(); 23 - } 24 24 }); 25 25 </script> 26 26 {{/html}} ... ... @@ -27,63 +27,227 @@ 27 27 {{/velocity}} 28 28 29 29 {{velocity}} 55 +=== Прикрепите вложения и используйте кнопки для навигации === 56 +#set($spaceRef = $doc.documentReference.lastSpaceReference.name) 57 +#set($pageName = $doc.documentReference.name) 58 +#set($docFullName = "${spaceRef}.${pageName}") 30 30 #set($attachments = $doc.getAttachmentList()) 31 -#foreach($attachment in $attachments) 32 - #set($filename = $attachment.filename) 33 - #set($fileurl = $doc.getAttachmentURL($filename)) 34 - #set($fileExt = $filename.substring($filename.lastIndexOf('.') + 1).toLowerCase()) 35 - 36 - ## Определяем тип файла 37 - #set($isPdf = $fileExt == 'pdf') 38 - #set($isImage = $fileExt == 'png' || $fileExt == 'jpg' || $fileExt == 'jpeg' || $fileExt == 'gif' || $fileExt == 'bmp' || $fileExt == 'svg') 39 - #set($isOffice = $fileExt == 'doc' || $fileExt == 'docx' || $fileExt == 'xls' || $fileExt == 'xlsx' || $fileExt == 'ppt' || $fileExt == 'pptx' || $fileExt == 'odt' || $fileExt == 'ods' || $fileExt == 'odp') 40 - 41 - ## Обрабатываем только поддерживаемые форматы 42 - #if($isPdf || $isImage || $isOffice) 43 - 44 - 45 - #if($isPdf) 60 +#set($itemsPerPage = 1) 61 +#set($totalPages = ($attachments.size() + $itemsPerPage - 1) / $itemsPerPage) 62 +#set($currentPage = 1) 63 +#if("$!request.page" != "") 64 + #set($currentPage = $mathtool.toInteger($request.page)) 65 +#end 66 +#set($startIndex = ($currentPage - 1) * $itemsPerPage) 67 +#set($endIndex = $startIndex + $itemsPerPage - 1) 68 +#if($endIndex >= $attachments.size()) 69 + #set($endIndex = $attachments.size() - 1) 70 +#end 71 + 72 +{{html}} 73 +<div class="navigation-controls"> 74 + #if($attachments && !$attachments.isEmpty()) 75 + <!-- Выпадающий список для выбора вложения --> 76 + <div class="attachment-selector"> 77 + <label for="attachment-select">Выберите вложение:</label> 78 + <select id="attachment-select"> 79 + #foreach($attachment in $attachments) 80 + <option value="$attachment.filename" #if($velocityCount == $currentPage)selected#end> 81 + $attachment.filename 82 + </option> 83 + #end 84 + </select> 85 + </div> 86 + 87 + <!-- Пагинация --> 88 + <div class="pagination-controls"> 89 + #if($currentPage > 1) 90 + #set($prevPage = $currentPage - 1) 91 + <a href="$doc.getURL('view', "page=${prevPage}")" class="btn btn-primary">Назад</a> 92 + #else 93 + <span class="btn btn-disabled">Назад</span> 94 + #end 95 + 96 + <span class="page-info">Страница $currentPage из $totalPages</span> 97 + 98 + #if($currentPage < $totalPages) 99 + #set($nextPage = $currentPage + 1) 100 + <a href="$doc.getURL('view', "page=${nextPage}")" class="btn btn-primary">Далее</a> 101 + #else 102 + <span class="btn btn-disabled">Далее</span> 103 + #end 104 + </div> 105 + #else 106 + <div class="no-attachments-message"> 107 + Нет прикрепленных вложений. Пожалуйста, добавьте файлы для просмотра. 108 + </div> 109 + #end 110 +</div> 111 +{{/html}} 112 + 113 +#if($attachments && !$attachments.isEmpty()) 114 + #foreach($i in [$startIndex..$endIndex]) 115 + #set($attachment = $attachments.get($i)) 116 + #set($filename = $attachment.filename) 117 + #set($fileurl = $doc.getAttachmentURL($filename, "download")) 118 + #set($fileExtension = $filename.substring($filename.lastIndexOf('.') + 1).toLowerCase()) 119 + 120 + === Документ: $filename === 121 + 46 46 {{html}} 47 - <div class="pdf-viewer-container"> 48 - <iframe 49 - src="/resources/pdfjs/web/viewer.html?file=${fileurl}" 50 - width="100%" 51 - height="600px"> 52 - </iframe> 123 + <div class="document-viewer-container" id="document-viewer"> 124 + #if($fileExtension == 'pdf') 125 + <!-- PDF Viewer --> 126 + <iframe 127 + id="document-frame" 128 + src="/resources/pdfjs/web/viewer.html?file=${escapetool.url($fileurl)}" 129 + width="100%" 130 + height="600px"> 131 + </iframe> 132 + #elseif($fileExtension == 'doc' || $fileExtension == 'docx' || $fileExtension == 'ppt' || $fileExtension == 'pptx' || $fileExtension == 'xls' || $fileExtension == 'xlsx' || $fileExtension == 'mp4') 133 + #if($fileExtension == 'doc' || $fileExtension == 'docx' || $fileExtension == 'ppt' || $fileExtension == 'pptx' || $fileExtension == 'xls' || $fileExtension == 'xlsx') 134 + <!-- Office Viewer --> 135 + #set($officeViewerUrl = "${doc.getURL('view')}?xpage=office&attachment=${escapetool.url($filename)}") 136 + <iframe 137 + id="document-frame" 138 + src="$officeViewerUrl" 139 + width="100%" 140 + height="600px"> 141 + </iframe> 142 + #end 143 + #if($fileExtension == 'mp4') 144 + ==ВИДЕО== 145 + <video id="myvideo" width="920" controls> 146 + <source src="${fileurl}" type="video/$fileExtension"> 147 + Ваш браузер не поддерживает видео. 148 + </video> 149 + #end 150 + #else 151 + ==Конец== 152 + <div class="unsupported-format"> 153 + Формат файла (${fileExtension}) не поддерживается для просмотра. 154 + <a href="${fileurl}">Скачать файл</a> 155 + </div> 156 + #end 53 53 </div> 54 54 {{/html}} 55 - 56 - #elseif($isImage) 57 - [[image:${attachment.filename}]] 58 - 59 - #elseif($isOffice) 60 - {{office attachment="${attachment.filename}" filterStyles="false"/}} 61 - 62 62 #end 63 - #end 160 +#else 161 + {{html}} 162 + <div class="no-attachments-message"> 163 + Нет доступных вложений для отображения. 164 + </div> 165 + {{/html}} 64 64 #end 65 65 66 66 {{html}} 67 67 <style> 68 - .pdf-viewer-container { 170 + .navigation-controls { 171 + display: flex; 172 + flex-direction: column; 173 + gap: 15px; 174 + margin-bottom: 20px; 175 + } 176 + .attachment-selector { 177 + display: flex; 178 + align-items: center; 179 + gap: 10px; 180 + } 181 + .attachment-selector select { 182 + padding: 8px; 183 + border-radius: 4px; 184 + min-width: 300px; 185 + } 186 + .document-viewer-container { 69 69 margin: 20px 0; 70 70 border: 1px solid #eee; 71 71 padding: 10px; 72 72 background: #f9f9f9; 73 73 } 74 - 75 - /* Стили для изображений */ 76 - .image-wrapper { 77 - max-width: 100%; 78 - margin: 10px 0; 192 + .pagination-controls { 193 + margin: 20px 0; 194 + display: flex; 195 + justify-content: center; 196 + align-items: center; 197 + gap: 20px; 79 79 } 80 - 81 - /* Стили для офисных документов */ 82 - .office-document { 83 - border: 1px solid #ddd; 84 - margin: 15px 0; 85 - min-height: 500px; 199 + .btn { 200 + padding: 8px 16px; 201 + border-radius: 4px; 202 + text-decoration: none; 86 86 } 204 + .btn-primary { 205 + background-color: #3366cc; 206 + color: white; 207 + } 208 + .btn-disabled { 209 + background-color: #eee; 210 + color: #999; 211 + cursor: not-allowed; 212 + } 213 + .page-info { 214 + font-weight: bold; 215 + } 216 + .unsupported-format { 217 + padding: 20px; 218 + text-align: center; 219 + color: #666; 220 + } 221 + .no-attachments-message { 222 + padding: 20px; 223 + text-align: center; 224 + color: #666; 225 + font-style: italic; 226 + border: 1px dashed #ccc; 227 + background-color: #f5f5f5; 228 + } 87 87 </style> 230 + 231 +<script> 232 +//<![CDATA[ 233 +document.addEventListener('DOMContentLoaded', function() { 234 + const select = document.getElementById('attachment-select'); 235 + const viewerContainer = document.getElementById('document-viewer'); 236 + 237 + if (select && viewerContainer) { 238 + select.addEventListener('change', function() { 239 + const filename = this.value; 240 + const fileExtension = filename.split('.').pop().toLowerCase(); 241 + const fileurl = "${doc.getURL('download')}" + "/" + encodeURIComponent(filename); 242 + const pdfViewerUrl = "/resources/pdfjs/web/viewer.html?file=" + encodeURIComponent(fileurl); 243 + const baseUrl = "${doc.getURL('view')}"; 244 + 245 + let viewerHtml = ''; 246 + 247 + if (fileExtension === 'pdf') { 248 + viewerHtml = '<iframe id="document-frame" ' + 249 + 'src="' + pdfViewerUrl + '" ' + 250 + 'width="100%" height="600px"></iframe>'; 251 + } else if (['doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx'].indexOf(fileExtension) >= 0) { 252 + viewerHtml = '<iframe id="document-frame" ' + 253 + 'src="' + baseUrl + '?xpage=office&attachment=' + encodeURIComponent(filename) + '" ' + 254 + 'width="100%" height="600px"></iframe>'; 255 + } else if (fileExtension === 'mp4'||fileExtension === 'mov') { 256 + viewerHtml = '<video width="920" controls>' + 257 + '<source src="' + fileurl + '" type="video/' + fileExtension + '">' + 258 + 'Ваш браузер не поддерживает видео.</video>'; 259 +} else { 260 + viewerHtml = '<div class="unsupported-format">' + 261 + 'Формат файла (' + fileExtension + ') не поддерживается для просмотра. ' + 262 + '<a href="' + fileurl + '">Скачать файл</a></div>'; 263 + } 264 + 265 + viewerContainer.innerHTML = viewerHtml; 266 + 267 + // Обновляем заголовок документа 268 + const titleElement = viewerContainer.previousElementSibling; 269 + if (titleElement && titleElement.tagName === 'H3') { 270 + titleElement.textContent = 'Документ: ' + filename; 271 + } 272 + }); 273 + } 274 +}); 275 +//]]> 276 +</script> 88 88 {{/html}} 89 89 {{/velocity}}