| | | 1 | | @using OzonOrdersWeb.ViewModels.MatchFileDataViewModel |
| | | 2 | | |
| | | 3 | | @model MatchFileDataViewModel |
| | | 4 | | |
| | | 5 | | @{ |
| | 0 | 6 | | ViewData["Title"] = "Сопоставление файлов"; |
| | 0 | 7 | | Layout = "~/Views/Shared/_Layout.cshtml"; |
| | 0 | 8 | | string errorResult = ViewData["ErrorResult"] as string ?? ""; |
| | | 9 | | } |
| | | 10 | | |
| | | 11 | | <style> |
| | | 12 | | .card { |
| | | 13 | | border: none; |
| | | 14 | | box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); |
| | | 15 | | border-radius: 0.5rem; |
| | | 16 | | margin-bottom: 1.5rem; |
| | | 17 | | } |
| | | 18 | | |
| | | 19 | | .card-header { |
| | | 20 | | background-color: #f8f9fa; |
| | | 21 | | border-bottom: 1px solid #e9ecef; |
| | | 22 | | padding: 1.25rem 1.5rem; |
| | | 23 | | } |
| | | 24 | | |
| | | 25 | | .card-body { |
| | | 26 | | padding: 1.5rem; |
| | | 27 | | } |
| | | 28 | | |
| | | 29 | | .form-group { |
| | | 30 | | margin-bottom: 1rem; |
| | | 31 | | } |
| | | 32 | | |
| | | 33 | | .form-label { |
| | | 34 | | font-weight: 600; |
| | | 35 | | color: #495057; |
| | | 36 | | margin-bottom: 0.25rem; |
| | | 37 | | display: block; |
| | | 38 | | font-size: 0.9rem; |
| | | 39 | | } |
| | | 40 | | |
| | | 41 | | .form-control, .form-select { |
| | | 42 | | border: 1px solid #e9ecef; |
| | | 43 | | border-radius: 0.25rem; |
| | | 44 | | padding: 0.5rem 0.75rem; |
| | | 45 | | font-size: 0.9rem; |
| | | 46 | | transition: border-color 0.15s ease-in-out; |
| | | 47 | | } |
| | | 48 | | |
| | | 49 | | .form-control:focus, .form-select:focus { |
| | | 50 | | border-color: #007bff; |
| | | 51 | | box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); |
| | | 52 | | } |
| | | 53 | | |
| | | 54 | | .btn-primary { |
| | | 55 | | background-color: #007bff; |
| | | 56 | | border-color: #007bff; |
| | | 57 | | padding: 0.5rem 1rem; |
| | | 58 | | font-size: 0.9rem; |
| | | 59 | | } |
| | | 60 | | |
| | | 61 | | .btn-secondary { |
| | | 62 | | background-color: #6c757d; |
| | | 63 | | border-color: #6c757d; |
| | | 64 | | padding: 0.5rem 1rem; |
| | | 65 | | font-size: 0.9rem; |
| | | 66 | | } |
| | | 67 | | |
| | | 68 | | .btn-link { |
| | | 69 | | color: #007bff; |
| | | 70 | | font-size: 0.8rem; |
| | | 71 | | text-decoration: none; |
| | | 72 | | background: transparent; |
| | | 73 | | padding: 0.25rem 0.5rem; |
| | | 74 | | border: none; |
| | | 75 | | } |
| | | 76 | | |
| | | 77 | | .btn-link:hover { |
| | | 78 | | color: #0056b3; |
| | | 79 | | text-decoration: underline; |
| | | 80 | | background-color: #f8f9fa; |
| | | 81 | | border-radius: 0.2rem; |
| | | 82 | | } |
| | | 83 | | |
| | | 84 | | .text-muted-small { |
| | | 85 | | font-size: 0.8rem; |
| | | 86 | | color: #6c757d; |
| | | 87 | | } |
| | | 88 | | |
| | | 89 | | .section-title { |
| | | 90 | | color: #495057; |
| | | 91 | | font-size: 1rem; |
| | | 92 | | margin-bottom: 1rem; |
| | | 93 | | padding-bottom: 0.5rem; |
| | | 94 | | border-bottom: 1px solid #e9ecef; |
| | | 95 | | } |
| | | 96 | | |
| | | 97 | | .file-section { |
| | | 98 | | background-color: #fafbfc; |
| | | 99 | | border: 1px solid #e9ecef; |
| | | 100 | | border-radius: 0.5rem; |
| | | 101 | | padding: 1.5rem; |
| | | 102 | | margin-bottom: 1.5rem; |
| | | 103 | | } |
| | | 104 | | |
| | | 105 | | .form-grid { |
| | | 106 | | display: grid; |
| | | 107 | | grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); |
| | | 108 | | gap: 1rem; |
| | | 109 | | margin-bottom: 1rem; |
| | | 110 | | } |
| | | 111 | | |
| | | 112 | | .matching-row { |
| | | 113 | | border: 1px solid #e9ecef; |
| | | 114 | | border-radius: 0.25rem; |
| | | 115 | | padding: 1rem; |
| | | 116 | | margin-bottom: 1rem; |
| | | 117 | | background-color: #fff; |
| | | 118 | | } |
| | | 119 | | |
| | | 120 | | .dropdown-menu { |
| | | 121 | | max-width: 400px; |
| | | 122 | | box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); |
| | | 123 | | } |
| | | 124 | | |
| | | 125 | | .list-group-item { |
| | | 126 | | border: none; |
| | | 127 | | border-bottom: 1px solid #e9ecef; |
| | | 128 | | padding: 0.75rem 1rem; |
| | | 129 | | } |
| | | 130 | | |
| | | 131 | | .list-group-item:last-child { |
| | | 132 | | border-bottom: none; |
| | | 133 | | } |
| | | 134 | | |
| | | 135 | | .nav-header { |
| | | 136 | | background-color: #f8f9fa; |
| | | 137 | | border-bottom: 1px solid #e9ecef; |
| | | 138 | | padding: 1rem 1.5rem; |
| | | 139 | | } |
| | | 140 | | |
| | | 141 | | .progress { |
| | | 142 | | margin: 20px 0; |
| | | 143 | | } |
| | | 144 | | |
| | | 145 | | /* Модальные окна */ |
| | | 146 | | .modal-content { |
| | | 147 | | border: none; |
| | | 148 | | border-radius: 0.5rem; |
| | | 149 | | box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); |
| | | 150 | | } |
| | | 151 | | |
| | | 152 | | .modal-header { |
| | | 153 | | background-color: #f8f9fa; |
| | | 154 | | border-bottom: 1px solid #e9ecef; |
| | | 155 | | padding: 1.25rem 1.5rem; |
| | | 156 | | } |
| | | 157 | | |
| | | 158 | | .modal-footer { |
| | | 159 | | border-top: 1px solid #e9ecef; |
| | | 160 | | padding: 1rem 1.5rem; |
| | | 161 | | } |
| | | 162 | | </style> |
| | | 163 | | |
| | | 164 | | <!-- Модальное окно сохранения сопоставлений --> |
| | | 165 | | <div class="modal fade" id="saveMappingModal" tabindex="-1" role="dialog" aria-labelledby="saveMappingModalLabel" |
| | | 166 | | aria-hidden="true"> |
| | | 167 | | <div class="modal-dialog" role="document"> |
| | | 168 | | <div class="modal-content"> |
| | | 169 | | <div class="modal-header"> |
| | | 170 | | <h5 class="modal-title" id="saveMappingModalLabel">Сохранить состояние сопоставлений</h5> |
| | | 171 | | <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
| | | 172 | | </div> |
| | | 173 | | <div class="modal-body"> |
| | | 174 | | <p class="mb-3">Введите название для сохранения (необязательно):</p> |
| | | 175 | | <input type="text" id="saveMappingName" class="form-control" placeholder="Название сопоставления"> |
| | | 176 | | </div> |
| | | 177 | | <div class="modal-footer"> |
| | | 178 | | <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button> |
| | | 179 | | <button type="button" class="btn btn-primary" onclick="submitFormWithSave()"> |
| | | 180 | | <i class="fas fa-save me-1"></i>Сохранить и загрузить |
| | | 181 | | </button> |
| | | 182 | | <button type="button" class="btn btn-outline-primary" onclick="submitFormWithoutSave()"> |
| | | 183 | | Продолжить без сохранения |
| | | 184 | | </button> |
| | | 185 | | </div> |
| | | 186 | | </div> |
| | | 187 | | </div> |
| | | 188 | | </div> |
| | | 189 | | |
| | | 190 | | <div class="container"> |
| | | 191 | | <!-- Навигационная панель --> |
| | | 192 | | <div class="nav-header"> |
| | | 193 | | <div class="dropdown"> |
| | | 194 | | <button class="btn btn-outline-secondary dropdown-toggle" type="button" id="savedMappingsDropdown" |
| | | 195 | | data-bs-toggle="dropdown" aria-expanded="false"> |
| | | 196 | | <i class="fas fa-folder-open me-2"></i>Загруженные сопоставления |
| | | 197 | | </button> |
| | | 198 | | <ul class="dropdown-menu" aria-labelledby="savedMappingsDropdown" |
| | | 199 | | style="max-height: 400px; overflow-y: auto;"> |
| | 0 | 200 | | @foreach (var matchedResult in Model.MatchedResults) |
| | | 201 | | { |
| | | 202 | | <li> |
| | | 203 | | <div class="dropdown-item"> |
| | | 204 | | <div class="d-flex w-100 justify-content-between"> |
| | 0 | 205 | | <h6 class="mb-1">@matchedResult.MainFileName / @matchedResult.ScondaryFileName</h6> |
| | 0 | 206 | | <small class="text-muted">@matchedResult.СreationDate.ToString("dd.MM.yyyy")</small> |
| | | 207 | | </div> |
| | | 208 | | <div class="d-flex justify-content-between mt-2"> |
| | | 209 | | <a href="/MatchFileData/GetMatchResult?id=@matchedResult.Id" |
| | | 210 | | class="btn btn-sm btn-outline-primary"> |
| | | 211 | | <i class="fas fa-eye me-1"></i>Просмотр |
| | | 212 | | </a> |
| | | 213 | | <a href="/MatchFileData/ExtendMatchedData?id=@matchedResult.Id" |
| | | 214 | | class="btn btn-sm btn-outline-secondary"> |
| | | 215 | | <i class="fas fa-plus me-1"></i>Дополнить |
| | | 216 | | </a> |
| | | 217 | | <a href="/MatchFileData/DeleteMatchResult?id=@matchedResult.Id" |
| | | 218 | | class="btn btn-sm btn-outline-danger" |
| | | 219 | | data-st2-confirm="Вы уверены, что хотите удалить это сопоставление?" |
| | | 220 | | data-st2-confirm-variant="danger" |
| | | 221 | | data-st2-confirm-text="Удалить"> |
| | | 222 | | <i class="fas fa-trash me-1"></i>Удалить |
| | | 223 | | </a> |
| | | 224 | | </div> |
| | | 225 | | </div> |
| | | 226 | | </li> |
| | | 227 | | <li> |
| | | 228 | | <hr class="dropdown-divider"> |
| | | 229 | | </li> |
| | | 230 | | } |
| | | 231 | | </ul> |
| | | 232 | | </div> |
| | | 233 | | </div> |
| | | 234 | | |
| | | 235 | | <div class="row"> |
| | | 236 | | <div class="col-12"> |
| | | 237 | | <!-- Основная карточка --> |
| | | 238 | | <div class="card"> |
| | | 239 | | <div class="card-header"> |
| | | 240 | | <h2 style="margin: 0; font-size: 1.5rem;">Загрузка файлов для сопоставления</h2> |
| | | 241 | | </div> |
| | | 242 | | <div class="card-body"> |
| | 0 | 243 | | @if (errorResult != null) |
| | | 244 | | { |
| | | 245 | | <div class="alert alert-danger alert-dismissible fade show mb-4" role="alert"> |
| | 0 | 246 | | <i class="fas fa-exclamation-circle me-2"></i>@Html.Raw(errorResult) |
| | | 247 | | <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> |
| | | 248 | | </div> |
| | | 249 | | } |
| | | 250 | | |
| | | 251 | | <!-- Сохраненные сопоставления --> |
| | | 252 | | <div class="form-group mb-4"> |
| | | 253 | | <label for="savedMappings" class="form-label">Выберите сохраненное сопоставление</label> |
| | | 254 | | <select id="savedMappings" class="form-select custom-select-init" onchange="loadSavedMapping(thi |
| | | 255 | | <option value="">-- Выберите сохраненное сопоставление --</option> |
| | 0 | 256 | | @foreach (var mapping in Model.SavedMatchingColumns) |
| | | 257 | | { |
| | 0 | 258 | | <option value="@mapping.Id">@mapping.Name</option> |
| | | 259 | | } |
| | | 260 | | </select> |
| | | 261 | | <div class="text-muted-small mt-1"> |
| | | 262 | | <i class="fas fa-info-circle me-1"></i>Загрузите настройки из ранее сохраненного |
| | | 263 | | сопоставления |
| | | 264 | | </div> |
| | | 265 | | </div> |
| | | 266 | | |
| | | 267 | | <!-- Форма загрузки файлов --> |
| | 0 | 268 | | @using (Html.BeginForm("MatchFiles", "MatchFileData", FormMethod.Post, new { enctype = "multipart/fo |
| | | 269 | | { |
| | | 270 | | <div class="form-grid"> |
| | | 271 | | <!-- Файл 1: Заказы --> |
| | | 272 | | <div class="file-section"> |
| | | 273 | | <h5 class="section-title"> |
| | | 274 | | <i class="fas fa-file-alt me-2"></i>Файл заказов |
| | | 275 | | </h5> |
| | | 276 | | <div class="form-group"> |
| | | 277 | | <label for="fileInput1" class="form-label">Файл заказов</label> |
| | | 278 | | <input type="file" class="form-control" id="fileInput1" name="file1" |
| | | 279 | | accept=".xlsx,.csv" required> |
| | | 280 | | <div class="invalid-feedback"> |
| | | 281 | | Пожалуйста, выберите файл заказов. |
| | | 282 | | </div> |
| | | 283 | | </div> |
| | | 284 | | <div id="startInputs1" style="display: none;"> |
| | | 285 | | <div class="row"> |
| | | 286 | | <div class="col-md-6"> |
| | | 287 | | <label for="startRowInput1" class="form-label">Начальная строка</label> |
| | | 288 | | <input type="number" class="form-control" id="startRowInput1" |
| | | 289 | | name="startRow1" value="1" min="1"> |
| | | 290 | | </div> |
| | | 291 | | <div class="col-md-6"> |
| | | 292 | | <label for="startColumnInput1" class="form-label">Начальный столбец</label> |
| | | 293 | | <input type="number" class="form-control" id="startColumnInput1" |
| | | 294 | | name="startColumn1" value="1" min="1"> |
| | | 295 | | </div> |
| | | 296 | | </div> |
| | | 297 | | </div> |
| | | 298 | | </div> |
| | | 299 | | |
| | | 300 | | <!-- Файл 2: Платежи --> |
| | | 301 | | <div class="file-section"> |
| | | 302 | | <h5 class="section-title"> |
| | | 303 | | <i class="fas fa-file-invoice me-2"></i>Файл платежей |
| | | 304 | | </h5> |
| | | 305 | | <div class="form-group"> |
| | | 306 | | <label for="fileInput2" class="form-label">Файл платежей</label> |
| | | 307 | | <input type="file" class="form-control" id="fileInput2" name="file2" |
| | | 308 | | accept=".xlsx,.csv" required> |
| | | 309 | | <div class="invalid-feedback"> |
| | | 310 | | Пожалуйста, выберите файл платежей. |
| | | 311 | | </div> |
| | | 312 | | </div> |
| | | 313 | | <div id="startInputs2" style="display: none;"> |
| | | 314 | | <div class="row"> |
| | | 315 | | <div class="col-md-6"> |
| | | 316 | | <label for="startRowInput2" class="form-label">Начальная строка</label> |
| | | 317 | | <input type="number" class="form-control" id="startRowInput2" |
| | | 318 | | name="startRow2" value="1" min="1"> |
| | | 319 | | </div> |
| | | 320 | | <div class="col-md-6"> |
| | | 321 | | <label for="startColumnInput2" class="form-label">Начальный столбец</label> |
| | | 322 | | <input type="number" class="form-control" id="startColumnInput2" |
| | | 323 | | name="startColumn2" value="1" min="1"> |
| | | 324 | | </div> |
| | | 325 | | </div> |
| | | 326 | | </div> |
| | | 327 | | </div> |
| | | 328 | | </div> |
| | | 329 | | |
| | | 330 | | <!-- Поля сопоставления --> |
| | | 331 | | <div class="form-group"> |
| | | 332 | | <div class="d-flex justify-content-between align-items-center mb-3"> |
| | | 333 | | <h5 class="section-title mb-0"> |
| | | 334 | | <i class="fas fa-link me-2"></i>Поля для сопоставления |
| | | 335 | | </h5> |
| | | 336 | | <button type="button" id="addMatchingFields" class="btn btn-link"> |
| | | 337 | | <i class="fas fa-plus me-1"></i>Добавить сопоставление |
| | | 338 | | </button> |
| | | 339 | | </div> |
| | | 340 | | |
| | | 341 | | <div id="matchingFieldsContainer"> |
| | | 342 | | <div class="matching-row"> |
| | | 343 | | <div class="row"> |
| | | 344 | | <div class="col-md-6"> |
| | | 345 | | <label class="form-label">Столбец из файла заказов</label> |
| | | 346 | | <input type="text" class="form-control" name="matchingColumns[0].Item1" |
| | | 347 | | required placeholder="Название столбца"> |
| | | 348 | | </div> |
| | | 349 | | <div class="col-md-6"> |
| | | 350 | | <label class="form-label">Столбец из файла платежей</label> |
| | | 351 | | <input type="text" class="form-control" name="matchingColumns[0].Item2" |
| | | 352 | | required placeholder="Название столбца"> |
| | | 353 | | </div> |
| | | 354 | | </div> |
| | | 355 | | </div> |
| | | 356 | | </div> |
| | | 357 | | </div> |
| | | 358 | | |
| | | 359 | | <input type="hidden" id="matchName" name="matchName"> |
| | | 360 | | |
| | | 361 | | <!-- Кнопка отправки --> |
| | | 362 | | <div class="form-group mt-4"> |
| | | 363 | | <button type="button" class="btn btn-primary" id="submitButton" disabled |
| | | 364 | | onclick="showSaveModal()"> |
| | | 365 | | <i class="fas fa-play me-1"></i>Загрузить и сопоставить |
| | | 366 | | </button> |
| | | 367 | | </div> |
| | 0 | 368 | | } |
| | | 369 | | |
| | 0 | 370 | | @if (!string.IsNullOrEmpty(ViewBag.Message)) |
| | | 371 | | { |
| | | 372 | | <div class="alert alert-info mt-4"> |
| | 0 | 373 | | <i class="fas fa-info-circle me-2"></i>@ViewBag.Message |
| | | 374 | | </div> |
| | | 375 | | } |
| | | 376 | | </div> |
| | | 377 | | </div> |
| | | 378 | | </div> |
| | | 379 | | </div> |
| | | 380 | | </div> |
| | | 381 | | |
| | | 382 | | <script> |
| | | 383 | | let matchCount = 1; |
| | | 384 | | |
| | | 385 | | // Показать модальное окно сохранения |
| | | 386 | | function showSaveModal() { |
| | | 387 | | $('#saveMappingModal').modal('show'); |
| | | 388 | | } |
| | | 389 | | |
| | | 390 | | // Отправить форму с сохранением |
| | | 391 | | function submitFormWithSave() { |
| | | 392 | | const matchName = document.getElementById('saveMappingName').value; |
| | | 393 | | document.getElementById('matchName').value = matchName.trim(); |
| | | 394 | | $('#saveMappingModal').modal('hide'); |
| | | 395 | | document.getElementById('uploadForm').submit(); |
| | | 396 | | } |
| | | 397 | | |
| | | 398 | | // Отправить форму без сохранения |
| | | 399 | | function submitFormWithoutSave() { |
| | | 400 | | $('#saveMappingModal').modal('hide'); |
| | | 401 | | document.getElementById('uploadForm').submit(); |
| | | 402 | | } |
| | | 403 | | |
| | | 404 | | // Обновить состояние кнопки отправки |
| | | 405 | | function updateSubmitButtonState() { |
| | | 406 | | const file1 = document.getElementById('fileInput1').files.length > 0; |
| | | 407 | | const file2 = document.getElementById('fileInput2').files.length > 0; |
| | | 408 | | document.getElementById('submitButton').disabled = !(file1 && file2); |
| | | 409 | | } |
| | | 410 | | |
| | | 411 | | // Обработчики файлов |
| | | 412 | | document.getElementById('fileInput1').addEventListener('change', function () { |
| | | 413 | | toggleStartInputs('startInputs1', this.files[0]); |
| | | 414 | | updateSubmitButtonState(); |
| | | 415 | | }); |
| | | 416 | | |
| | | 417 | | document.getElementById('fileInput2').addEventListener('change', function () { |
| | | 418 | | toggleStartInputs('startInputs2', this.files[0]); |
| | | 419 | | updateSubmitButtonState(); |
| | | 420 | | }); |
| | | 421 | | |
| | | 422 | | function toggleStartInputs(inputsId, file) { |
| | | 423 | | const inputs = document.getElementById(inputsId); |
| | | 424 | | if (file) { |
| | | 425 | | const extension = file.name.split('.').pop().toLowerCase(); |
| | | 426 | | inputs.style.display = (extension === 'csv' || extension === 'xlsx') ? 'block' : 'none'; |
| | | 427 | | } else { |
| | | 428 | | inputs.style.display = 'none'; |
| | | 429 | | } |
| | | 430 | | } |
| | | 431 | | |
| | | 432 | | // Добавление полей сопоставления |
| | | 433 | | document.getElementById('addMatchingFields').addEventListener('click', function () { |
| | | 434 | | const container = document.getElementById('matchingFieldsContainer'); |
| | | 435 | | const newRow = document.createElement('div'); |
| | | 436 | | newRow.className = 'matching-row'; |
| | | 437 | | newRow.id = `matchRow${matchCount}`; |
| | | 438 | | newRow.innerHTML = ` |
| | | 439 | | <div class="row"> |
| | | 440 | | <div class="col-md-6"> |
| | | 441 | | <label class="form-label">Столбец из файла заказов</label> |
| | | 442 | | <input type="text" class="form-control" name="matchingColumns[${matchCount}].Item1" required placeho |
| | | 443 | | </div> |
| | | 444 | | <div class="col-md-6"> |
| | | 445 | | <label class="form-label">Столбец из файла платежей</label> |
| | | 446 | | <input type="text" class="form-control" name="matchingColumns[${matchCount}].Item2" required placeho |
| | | 447 | | </div> |
| | | 448 | | </div> |
| | | 449 | | <div class="text-end mt-2"> |
| | | 450 | | <button type="button" class="btn btn-link btn-sm text-danger" onclick="removeMatchingField(${matchCount} |
| | | 451 | | <i class="fas fa-times me-1"></i>Удалить |
| | | 452 | | </button> |
| | | 453 | | </div> |
| | | 454 | | `; |
| | | 455 | | container.appendChild(newRow); |
| | | 456 | | matchCount++; |
| | | 457 | | }); |
| | | 458 | | |
| | | 459 | | // Удаление поля сопоставления |
| | | 460 | | function removeMatchingField(index) { |
| | | 461 | | const row = document.getElementById(`matchRow${index}`); |
| | | 462 | | if (row) row.remove(); |
| | | 463 | | } |
| | | 464 | | |
| | | 465 | | // Загрузка сохраненного сопоставления |
| | | 466 | | function loadSavedMapping(mappingId) { |
| | | 467 | | if (!mappingId) return; |
| | | 468 | | |
| | | 469 | | fetch(`/MatchFileData/GetMappingById?id=${mappingId}`) |
| | | 470 | | .then(response => response.json()) |
| | | 471 | | .then(data => populateMatchingFields(data)) |
| | | 472 | | .catch(error => console.error('Ошибка:', error)); |
| | | 473 | | } |
| | | 474 | | |
| | | 475 | | function populateMatchingFields(data) { |
| | | 476 | | const container = document.getElementById('matchingFieldsContainer'); |
| | | 477 | | container.innerHTML = ''; |
| | | 478 | | |
| | | 479 | | // Установка начальных позиций |
| | | 480 | | document.getElementById('startRowInput1').value = data.startRow1 || 1; |
| | | 481 | | document.getElementById('startColumnInput1').value = data.startColumn1 || 1; |
| | | 482 | | document.getElementById('startRowInput2').value = data.startRow2 || 1; |
| | | 483 | | document.getElementById('startColumnInput2').value = data.startColumn2 || 1; |
| | | 484 | | |
| | | 485 | | // Показать поля начальных позиций |
| | | 486 | | document.getElementById('startInputs1').style.display = 'block'; |
| | | 487 | | document.getElementById('startInputs2').style.display = 'block'; |
| | | 488 | | |
| | | 489 | | // Заполнение полей сопоставления |
| | | 490 | | data.matchingColumns.forEach((column, index) => { |
| | | 491 | | const row = document.createElement('div'); |
| | | 492 | | row.className = 'matching-row'; |
| | | 493 | | row.id = `matchRow${index}`; |
| | | 494 | | row.innerHTML = ` |
| | | 495 | | <div class="row"> |
| | | 496 | | <div class="col-md-6"> |
| | | 497 | | <label class="form-label">Столбец из файла заказов</label> |
| | | 498 | | <input type="text" class="form-control" name="matchingColumns[${index}].Item1" required |
| | | 499 | | value="${column.item1}" placeholder="Название столбца"> |
| | | 500 | | </div> |
| | | 501 | | <div class="col-md-6"> |
| | | 502 | | <label class="form-label">Столбец из файла платежей</label> |
| | | 503 | | <input type="text" class="form-control" name="matchingColumns[${index}].Item2" required |
| | | 504 | | value="${column.item2}" placeholder="Название столбца"> |
| | | 505 | | </div> |
| | | 506 | | </div> |
| | | 507 | | ${index > 0 ? ` |
| | | 508 | | <div class="text-end mt-2"> |
| | | 509 | | <button type="button" class="btn btn-link btn-sm text-danger" onclick="removeMatchingField(${index}) |
| | | 510 | | <i class="fas fa-times me-1"></i>Удалить |
| | | 511 | | </button> |
| | | 512 | | </div> |
| | | 513 | | ` : ''} |
| | | 514 | | `; |
| | | 515 | | container.appendChild(row); |
| | | 516 | | }); |
| | | 517 | | |
| | | 518 | | matchCount = data.matchingColumns.length; |
| | | 519 | | } |
| | | 520 | | |
| | | 521 | | // Валидация формы |
| | | 522 | | document.addEventListener('DOMContentLoaded', function () { |
| | | 523 | | const form = document.getElementById('uploadForm'); |
| | | 524 | | form.addEventListener('submit', function (event) { |
| | | 525 | | if (!form.checkValidity()) { |
| | | 526 | | event.preventDefault(); |
| | | 527 | | event.stopPropagation(); |
| | | 528 | | } |
| | | 529 | | form.classList.add('was-validated'); |
| | | 530 | | }, false); |
| | | 531 | | }); |
| | | 532 | | </script> |