• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE html>
2<html lang="en">
3
4<head>
5  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7  <title>{{ case.name }}</title>
8  <style>
9    /* Execution Log style Begin */
10    a:link {
11      text-decoration: none;
12    }
13
14    #logs div {
15      white-space: pre-wrap;
16      font-size: 14px;
17    }
18
19    .aw,
20    .step {
21      font-weight: bold;
22      color: #1E90FF;
23    }
24
25    .aw1 {
26      color: #008B45;
27    }
28
29    .aw2 {
30      color: #00CD00;
31    }
32
33    .aw3 {
34      font-weight: bold;
35      background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet);
36      -webkit-background-clip: text;
37      color: transparent;
38      display: inline-block;
39      background-repeat: no-repeat;
40    }
41
42    .aw3-container {
43      display: block; /* 确保容器是块级元素 */
44      overflow: hidden; /* 确保背景渐变效果 */
45    }
46
47    .ui_container {
48      background-color: black;
49      color: #18b302;
50      padding: 20px;
51      box-sizing: border-box;
52    }
53
54    .ui_component-number {
55      color: #18b302;
56    }
57
58    .ui_components {
59      display: flex;
60      flex-wrap: wrap;
61    }
62
63    .ui_component {
64      flex: 1;
65      margin: 5px;
66      color: #18b302;
67      background-color: #333;
68      padding: 10px;
69      box-sizing: border-box;
70      overflow-wrap: break-word; /* Ensures long words break */
71      word-break: break-all; /* Ensures long words break */
72    }
73
74    .ui_component pre {
75        white-space: pre-wrap;
76        word-wrap: break-word; /* Ensures long words break */
77    }
78
79    .ui_old-component .highlight {
80        color: red;
81    }
82    .ui_new-component .highlight {
83        color: yellow;
84    }
85
86    @media (max-width: 600px) {
87      .ui_components {
88            flex-direction: column;
89        }
90    }
91
92    .error,
93    .blocked,
94    .fail,
95    .failed,
96    .unavailable {
97      color: red !important;
98    }
99
100    .pass,
101    .passed {
102      color: green !important;
103    }
104
105    .warn,
106    .warning {
107      color: #FFCC00;
108    }
109    /* Execution Log style End */
110
111    body {
112      margin: 0 100px;
113      background-color: #fff;
114    }
115
116    h4 {
117      margin-top: 16px;
118      margin-bottom: 16px;
119    }
120
121    .el-descriptions__header {
122      display: flex;
123      justify-content: space-between;
124      align-items: center;
125      margin-bottom: 16px;
126    }
127
128    .el-descriptions__title {
129      color: #000000;
130      font-size: 16px;
131      font-weight: 700;
132    }
133
134    .el-descriptions__body {
135      background-color: #ffffff;
136      max-height: 121px;
137      overflow-y: auto;
138    }
139
140    .el-descriptions__body .el-descriptions__table {
141      border-collapse: collapse;
142      width: 100%;
143    }
144
145    .el-descriptions__body .el-descriptions__table.is-bordered .el-descriptions__cell {
146      border: 1px solid #edeef5;
147      padding: 8px 11px;
148    }
149
150    .el-descriptions__label.el-descriptions__cell.is-bordered-label {
151      font-weight: 700;
152      color: #606266;
153      background: #f5f7fa;
154    }
155
156    .el-descriptions__body .el-descriptions__table .el-descriptions__cell {
157      box-sizing: border-box;
158      text-align: left;
159      line-height: 23px;
160      font-size: 14px;
161    }
162
163    .el-descriptions__table .el-descriptions__cell {
164      word-wrap: break-word;
165      word-break: break-all;
166    }
167
168    .header .el-descriptions__table .el-descriptions__cell {
169      width: calc(100%/6);
170    }
171
172    .toolbar .el-descriptions__table .el-descriptions__label {
173      width: 12.5%;
174    }
175
176    .el-descriptions__content.el-descriptions__cell.is-bordered-content {
177      color: #303133;
178    }
179
180    ::-webkit-scrollbar {
181      width: 8px;
182      height: 8px;
183      border-radius: 8px;
184      background-color: #bcbcbc;
185    }
186
187    ::-webkit-scrollbar-track {
188      border-radius: 8px;
189      background-color: #f5f5f5;
190    }
191
192    ::-webkit-scrollbar-thumb {
193      border-radius: 8px;
194      background-color: #bfc3c6;
195    }
196
197    .el-popover.el-popper {
198      min-width: 280px;
199    }
200
201    .el-progress-bar__innerText {
202      color: #37383a;
203    }
204
205    .el-descriptions__title {
206      color: #000000;
207    }
208
209    .el-table__body .el-table__cell,
210    .el-table__header-wrapper .el-table__cell {
211      border-left: none;
212      border-right: none;
213    }
214
215    .el-table--border .el-table__inner-wrapper::after,
216    .el-table__border-left-patch,
217    .el-table--border::after,
218    .el-table--border::before {
219      display: none;
220    }
221
222    .toolbar {
223      display: flex;
224      border: 1px solid #ebeef5;
225      max-height: 760px;
226    }
227
228    .toolbar ul {
229      min-width: 25%;
230      height: auto;
231      overflow-y: auto;
232      flex-direction: column;
233      justify-content: flex-start;
234      flex-wrap: nowrap;
235      padding: 0;
236      padding-top: 0;
237      margin-top: 0;
238      margin-bottom: 0;
239      border-right: 1px solid #ebeef5;
240    }
241
242    .toolbar ul li {
243      height: 60px;
244      display: flex;
245      flex-direction: column;
246      justify-content: center;
247      padding-left: 12px;
248      cursor: pointer;
249      border-bottom: 1px solid #ebeef5;
250      background: #f5f7fa;
251    }
252
253    .toolbar ul li .li-div {
254      display: flex;
255      justify-content: space-between;
256    }
257
258    .toolbar ul li .li-span {
259      font-size: 14px;
260      display: -webkit-box;
261      overflow: hidden;
262      text-overflow: ellipsis;
263      max-width: 300px;
264      line-height: 23px;
265      white-space: normal;
266      word-break: break-all;
267      -webkit-box-orient: vertical;
268      -webkit-line-clamp: 2;
269    }
270
271    .toolbar ul li .li-tag {
272      margin-left: 10px;
273      font-size: 14px;
274    }
275
276    .toolbar ul li svg {
277      margin-right: 10px;
278      margin-left: 10px;
279      width: 16px;
280      height: 16px
281    }
282
283    .toolbar div img {
284      height: 514px;
285    }
286
287    .toolbar ul .isChecked {
288      background: #c9e1f8;
289    }
290
291    .toolbar ul .isPassed {
292      color: red;
293    }
294
295    .toolbar .img-div {
296      max-height: 630px;
297      overflow-y: auto;
298      display: flex;
299      justify-content: start;
300      margin-top: 10px;
301
302    }
303
304    .toolbar .screen-div {
305      min-width: 420px
306    }
307
308    .div-error {
309      white-space: nowrap;
310      overflow: hidden;
311      text-overflow: ellipsis;
312    }
313
314    .div-others {
315      display: inline-block;
316      width: 90%;
317      line-height: 23px;
318      vertical-align: sub
319    }
320
321    .span-img {
322      width: 5%;
323      display: inline-block;
324    }
325
326    .img {
327      margin-left: 5px;
328      cursor: pointer;
329      height: 16px;
330      width: 16px;
331    }
332
333    .div-dialog {
334      border-bottom: 1px solid #ebeef5;
335      border-top: 1px solid #ebeef5;
336    }
337
338    .des-style {
339      max-height: 342px !important;
340      overflow: auto;
341    }
342
343    .div-dialog .el-descriptions__table tr:nth-child(1) .el-descriptions__cell {
344      border-top: none;
345    }
346
347    .div-dialog .el-descriptions__table tr:last-child .el-descriptions__cell {
348      border-bottom: none;
349    }
350
351    .el-dialog__body {
352      padding-top: 10px;
353      padding-bottom: 40px;
354    }
355
356    .el-dialog__headerbtn {
357      top: -2px;
358    }
359
360    .el-table--fit {
361      border-right: 0;
362      border-bottom: 0;
363    }
364
365    .el-table {
366      position: relative;
367      overflow: hidden;
368      box-sizing: border-box;
369      height: fit-content;
370      width: 100%;
371      max-width: 100%;
372      background-color: #ffffff;
373      font-size: 14px;
374      color: #606266;
375    }
376
377    .el-table__inner-wrapper {
378      position: relative;
379      display: flex;
380      flex-direction: column;
381      height: 100%;
382    }
383
384    .el-table__header-wrapper {
385      overflow: hidden;
386      flex-shrink: 0;
387      width: 100%;
388    }
389
390    .el-table__header {
391      table-layout: fixed;
392      border-collapse: separate;
393    }
394
395    .el-table th.el-table__cell.is-leaf {
396      border-bottom: 1px solid #ebeef5;
397    }
398
399    .el-table th.el-table__cell {
400      -webkit-user-select: none;
401      -moz-user-select: none;
402      -ms-user-select: none;
403      user-select: none;
404      background-color: #ffffff;
405      border-left: none;
406      border-right: none;
407    }
408
409    .el-table .el-table__cell {
410      padding: 8px 0;
411      min-width: 0;
412      box-sizing: border-box;
413      text-overflow: ellipsis;
414      vertical-align: middle;
415      position: relative;
416      text-align: left;
417      z-index: 1;
418    }
419
420    .el-table__body-wrapper {
421      overflow: hidden;
422      position: relative;
423      flex: 1;
424      width: 100%;
425    }
426
427    .el-table__body {
428      table-layout: fixed;
429      border-collapse: separate;
430    }
431
432    .el-table tr {
433      background-color: #ffffff;
434    }
435
436    .el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell {
437      background-color: #f5f7fa;
438    }
439
440    .el-table--enable-row-transition .el-table__body td.el-table__cell {
441      transition: background-color .25s ease;
442    }
443
444    .el-table td.el-table__cell,
445    .el-table th.el-table__cell.is-leaf {
446      border-bottom: 1px solid #ebeef5;
447    }
448
449    .el-table thead {
450      color: #909399;
451      font-weight: 500;
452    }
453
454    .el-table .cell {
455      box-sizing: border-box;
456      overflow: hidden;
457      text-overflow: ellipsis;
458      white-space: normal;
459      word-break: break-all;
460      line-height: 23px;
461      padding: 0 12px;
462    }
463
464    .el-scrollbar {
465      overflow: hidden;
466      position: relative;
467      height: 100%;
468    }
469
470    .el-scrollbar__wrap--hidden-default {
471      scrollbar-width: none;
472    }
473
474    .el-scrollbar__wrap {
475      overflow: auto;
476      height: 100%;
477    }
478
479    .el-table .cell.el-tooltip {
480      white-space: nowrap;
481      overflow: hidden;
482      text-overflow: ellipsis;
483      min-width: 50px;
484    }
485
486    .mask {
487      background: rgba(0, 0, 0, 0.5);
488      width: 100%;
489      height: 100%;
490      position: fixed;
491      left: 0;
492      z-index: 20001;
493      top: 0;
494      display: none;
495      justify-content: center;
496      align-items: center;
497    }
498
499    .mask-imgBg {
500      background-color: #fff;
501      position: relative;
502      border-radius: 0.1875rem;
503      border: 0.3125rem solid #fff;
504    }
505
506    .mask-delete {
507      position: absolute;
508      z-index: 5;
509      right: 18px;
510      top: 20px;
511      transform-origin: center center;
512      width: 50px;
513      height: 50px;
514      border-radius: 50%;
515      background-color: #f0f0f0;
516      text-align: center;
517      line-height: 50px;
518      font-weight: 700;
519      box-shadow: 0 0 6px rgba(0, 0, 0, .2);
520      cursor: pointer;
521    }
522
523    .mask-delete:hover {
524      cursor: pointer;
525    }
526
527    .svg-style {
528      width: 28px;
529      height: 28px;
530      cursor: pointer;
531    }
532
533    .btn-div {
534      margin-bottom: 5px;
535      border-bottom: 1px solid #d1cdcd;
536      padding: 5px;
537    }
538
539    .scroll-top-btn {
540      padding: 5px;
541    }
542
543    .table-margin {
544      margin-top: 10px;
545    }
546  </style>
547</head>
548
549<body>
550  <div id="app">
551    <h3>{{ case.name }}</h3>
552    <h4 style="margin-top: 0;">Summary</h4>
553    <div class="header">
554      <div>
555        <div class="el-descriptions">
556          <div class="el-descriptions__body">
557            <table class="el-descriptions__table is-bordered">
558              <tbody>
559                <tr>
560                  <td class="el-descriptions__cell el-descriptions__label is-bordered-label">Test Start</td>
561                  <td class="el-descriptions__cell el-descriptions__content is-bordered-content">{{ case.begin }}</td>
562                  <td class="el-descriptions__cell el-descriptions__label is-bordered-label">Test End</td>
563                  <td class="el-descriptions__cell el-descriptions__content is-bordered-content">{{ case.end }}</td>
564                  <td class="el-descriptions__cell el-descriptions__label is-bordered-label">Elapsed</td>
565                  <td class="el-descriptions__cell el-descriptions__content is-bordered-content">{{ case.elapsed }}</td>
566                </tr>
567                {% if case.subcases %}
568
569                <!-- 测试套,无Error/Result,不显示 -->
570                {% if case.error %}
571                <tr>
572                  <td class="el-descriptions__cell el-descriptions__label is-bordered-label">Logs</td>
573                  <td class="el-descriptions__cell el-descriptions__content is-bordered-content" colspan="5">{{ case.logs }}</td>
574                </tr>
575                {% endif %}
576
577                {% else %}
578                <!-- 测试用例 -->
579                <tr>
580                  <td class="el-descriptions__cell el-descriptions__label is-bordered-label">Result</td>
581                  <td class="el-descriptions__cell el-descriptions__content is-bordered-content {{ case.result | lower }}">{{ case.result }}</td>
582                  <td class="el-descriptions__cell el-descriptions__label is-bordered-label">Logs</td>
583                  <td class="el-descriptions__cell el-descriptions__content is-bordered-content" colspan="3">{{ case.logs }}</td>
584                </tr>
585                {% if case.error %}
586                <tr>
587                  <td class="el-descriptions__cell el-descriptions__label is-bordered-label">Error</td>
588                  <td class="el-descriptions__cell el-descriptions__content is-bordered-content col_error error" colspan="5">{{ case.error }}</td>
589                </tr>
590                {% endif %}
591
592                {% endif %}
593              </tbody>
594            </table>
595          </div>
596        </div>
597      </div>
598    </div>
599
600    {% if case.subcases %}
601    <div class="el-table--fit el-table--enable-row-hover el-table--enable-row-transition el-table table-margin"
602      data-prefix="el" style="width: 100%;">
603      <div class="el-table__inner-wrapper">
604        <div class="el-table__header-wrapper">
605          <table class="el-table__header" cellpadding="0" cellspacing="0" style="width: 100%; border: 0;">
606            <colgroup>
607              <col name="el-table_1_column_1" style="width: 3%;">
608              <col name="el-table_1_column_2" style="width: 30%;">
609              <col name="el-table_1_column_3" style="width: 7%;">
610              <col name="el-table_1_column_4" style="width: 42%;">
611              <col name="el-table_1_column_5" style="width: 9%;">
612              <col name="el-table_1_column_6" style="width: 9%;">
613            </colgroup>
614            <thead class="">
615              <tr class="">
616                <th class="el-table_1_column_1 is-leaf el-table__cell">
617                  <div class="cell">#</div>
618                </th>
619                <th class="el-table_1_column_2 is-leaf el-table__cell">
620                  <div class="cell">Testcase</div>
621                </th>
622                <th class="el-table_1_column_3 is-leaf el-table__cell">
623                  <div class="cell">Result</div>
624                </th>
625                <th class="el-table_1_column_4 is-leaf el-table__cell">
626                  <div class="cell">Error</div>
627                </th>
628                <th class="el-table_1_column_5 is-leaf el-table__cell">
629                  <div class="cell">Begin</div>
630                </th>
631                <th class="el-table_1_column_6 is-leaf el-table__cell">
632                  <div class="cell">Elapsed</div>
633                </th>
634              </tr>
635            </thead>
636          </table>
637        </div>
638        <div class="el-table__body-wrapper">
639          <div class="el-scrollbar">
640            <div class="el-scrollbar__wrap el-scrollbar__wrap--hidden-default">
641              <div class="el-scrollbar__view" style="display: inline-block; vertical-align: middle;">
642                <table class="el-table__body" cellspacing="0" cellpadding="0"
643                  style="table-layout: fixed; width: 100%; border: 0;">
644                  <colgroup>
645                    <col name="el-table_1_column_1" style="width: 3%;">
646                    <col name="el-table_1_column_2" style="width: 30%;">
647                    <col name="el-table_1_column_3" style="width: 7%;">
648                    <col name="el-table_1_column_4" style="width: 42%;">
649                    <col name="el-table_1_column_5" style="width: 9%;">
650                    <col name="el-table_1_column_6" style="width: 9%;">
651                  </colgroup>
652                  <tbody id="casesTableBody">
653                    {% for subcase in case.subcases %}
654                    <tr class="el-table__row">
655                      <td class="el-table_1_column_1 el-table__cell">
656                        <div class="cell"><span>{{ loop.index }}</span></div>
657                      </td>
658                      <td class="el-table_1_column_2 el-table__cell">
659                        <div class="cell el-tooltip"><a href="{{ subcase.report }}" target="_blank">{{ subcase.name }}</a>
660                        </div>
661                      </td>
662                      <td class="el-table_1_column_3 el-table__cell">
663                        <div class="cell {{ subcase.result | lower }}"><span>{{ subcase.result }}</span></div>
664                      </td>
665                      <td class="el-table_1_column_4 el-table__cell">
666                        <div class="cell error"><span>{{ subcase.error }}</span></div>
667                      </td>
668                      <td class="el-table_1_column_5 el-table__cell">
669                        <div class="cell"><span>{{ subcase.begin }}</span></div>
670                      </td>
671                      <td class="el-table_1_column_6 el-table__cell">
672                        <div class="cell"><span>{{ subcase.elapsed }}</span></div>
673                      </td>
674                    </tr>
675                    {% endfor %}
676                  </tbody>
677                </table>
678              </div>
679            </div>
680          </div>
681        </div>
682      </div>
683    </div>
684    {% endif %}
685
686    {% if case.devices %}
687    <h4>Test Devices</h4>
688    <div class="el-table--fit fit-height el-table--enable-row-hover el-table--enable-row-transition el-table"
689      data-prefix="el" style="width: 100%; max-height: 120px;">
690      <div class="el-table__inner-wrapper wrapper-height" style="max-height: 120px;">
691        <div class="el-table__header-wrapper">
692          <table class="el-table__header" cellpadding="0" cellspacing="0" style="width: 100%; border: 0;">
693            <colgroup>
694              <col name="el-table_1_column_1" style="width: 3%;">
695              <col name="el-table_1_column_2" style="width: 22%;">
696              <col name="el-table_1_column_3" style="width: 14%;">
697              <col name="el-table_1_column_4" style="width: 14%;">
698              <col name="el-table_1_column_5" style="width: 14%;">
699              <col name="el-table_1_column_6" style="width: 16%;">
700              <col name="el-table_1_column_7" style="width: 17%;">
701            </colgroup>
702            <thead class="">
703              <tr class="">
704                <th class="el-table_1_column_1 is-leaf el-table__cell">
705                  <div class="cell">#</div>
706                </th>
707                <th class="el-table_1_column_2 is-leaf el-table__cell">
708                  <div class="cell">SN</div>
709                </th>
710                <th class="el-table_1_column_3 is-leaf el-table__cell">
711                  <div class="cell">Model</div>
712                </th>
713                <th class="el-table_1_column_4 is-leaf el-table__cell">
714                  <div class="cell">Type</div>
715                </th>
716                <th class="el-table_1_column_5 is-leaf el-table__cell">
717                  <div class="cell">Platform</div>
718                </th>
719                <th class="el-table_1_column_6 is-leaf el-table__cell">
720                  <div class="cell">Version</div>
721                </th>
722                <th class="el-table_1_column_7 is-leaf el-table__cell">
723                  <div class="cell">Others</div>
724                </th>
725              </tr>
726            </thead>
727          </table>
728        </div>
729        <div class="el-table__body-wrapper">
730          <div class="el-scrollbar">
731            <div class="el-scrollbar__wrap" style="max-height: calc(80px);">
732              <div class="el-scrollbar__view" style="display: inline-block; vertical-align: middle;">
733                <table class="el-table__body" cellspacing="0" cellpadding="0"
734                  style="table-layout: fixed; width: 100%; border: 0;">
735                  <colgroup>
736                    <col name="el-table_1_column_1" style="width: 3%;">
737                    <col name="el-table_1_column_2" style="width: 22%;">
738                    <col name="el-table_1_column_3" style="width: 14%;">
739                    <col name="el-table_1_column_4" style="width: 14%;">
740                    <col name="el-table_1_column_5" style="width: 14%;">
741                    <col name="el-table_1_column_6" style="width: 16%;">
742                    <col name="el-table_1_column_7" style="width: 17%;">
743                  </colgroup>
744                  <tbody>
745                    {% for device in case.devices %}
746                    <tr class="el-table__row">
747                      <td class="el-table_1_column_1 el-table__cell">
748                        <div class="cell"><span>{{ loop.index }}</span></div>
749                      </td>
750                      <td class="el-table_1_column_2 el-table__cell">
751                        <div class="cell el-tooltip"><span>{{ device.sn }}</span></div>
752                      </td>
753                      <td class="el-table_1_column_3 el-table__cell">
754                        <div class="cell"><span>{{ device.model }}</span></div>
755                      </td>
756                      <td class="el-table_1_column_4 el-table__cell">
757                        <div class="cell"><span>{{ device.type }}</span></div>
758                      </td>
759                      <td class="el-table_1_column_5 el-table__cell">
760                        <div class="cell"><span>{{ device.platform }}</span></div>
761                      </td>
762                      <td class="el-table_1_column_6 el-table__cell">
763                        <div class="cell"><span>{{ device.version }}</span></div>
764                      </td>
765                      {% if device.others %}
766                      <td class="el-table_1_column_7 el-table__cell">
767                        <div class="cell"><span>{{ device.others }}</span></div>
768                      </td>
769                      {% else %}
770                      <td class="el-table_1_column_7 el-table__cell">
771                        <div class="cell"><span>-</span></div>
772                      </td>
773                      {% endif %}
774                    </tr>
775                    {% endfor %}
776                  </tbody>
777                </table>
778              </div>
779            </div>
780          </div>
781        </div>
782      </div>
783    </div>
784    {% endif %}
785
786    <div id="details">
787      <h4>Test Details</h4>
788      <div class="toolbar">
789        <ul id="phoneErrorPosition" ref="phoneLeft">
790        </ul>
791        <div class="err" style="overflow: auto; margin-left: 10px; width: 75%; position: relative; min-height: 625px;">
792          <div class="el-descriptions__body err-scroll" style="margin-top: 10px;">
793            <table class="el-descriptions__table is-bordered">
794              <tbody id="message">
795              </tbody>
796            </table>
797          </div>
798          <div class="img-div">
799          </div>
800        </div>
801      </div>
802    </div>
803
804    <div id="dialog" class="mask">
805      <div class="mask-imgBg"></div>
806      <div class="mask-delete" onclick="closeDialog()">
807        <svg style="vertical-align: -0.125em" focusable="false" data-icon="close"
808          width="1em" height="1em" fill="currentColor" aria-hidden="true" fill-rule="evenodd" viewBox="64 64 896 896">
809          <path
810            d="M799.86 166.31c.02 0 .04.02.08.06l57.69 57.7c.04.03.05.05.06.08a.12.12 0 010 .06c0 .03-.02.05-.06.09L569.93 512l287.7 287.7c.04.04.05.06.06.09a.12.12 0 010 .07c0 .02-.02.04-.06.08l-57.7 57.69c-.03.04-.05.05-.07.06a.12.12 0 01-.07 0c-.03 0-.05-.02-.09-.06L512 569.93l-287.7 287.7c-.04.04-.06.05-.09.06a.12.12 0 01-.07 0c-.02 0-.04-.02-.08-.06l-57.69-57.7c-.04-.03-.05-.05-.06-.07a.12.12 0 010-.07c0-.03.02-.05.06-.09L454.07 512l-287.7-287.7c-.04-.04-.05-.06-.06-.09a.12.12 0 010-.07c0-.02.02-.04.06-.08l57.7-57.69c.03-.04.05-.05.07-.06a.12.12 0 01.07 0c.03 0 .05.02.09.06L512 454.07l287.7-287.7c.04-.04.06-.05.09-.06a.12.12 0 01.07 0z">
811          </path>
812        </svg>
813      </div>
814    </div>
815  </div>
816
817  <div class="btns"
818    style="position: fixed; z-index: 5000; bottom: 90px; right: 90px; display: none; border: 1px solid #d1cdcd;">
819    <div class="btn-div">
820      <div id="svg-show-media" style="display: none;" title="显示图片/视频">
821        <svg onclick="displayMedia('block')" class="svg-style" xmlns="http://www.w3.org/2000/svg"
822          viewBox="0 0 1024 1024" data-v-ea893728="">
823          <path fill="currentColor"
824            d="M512 160c320 0 512 352 512 352S832 864 512 864 0 512 0 512s192-352 512-352m0 64c-225.28 0-384.128 208.064-436.8 288 52.608 79.872 211.456 288 436.8 288 225.28 0 384.128-208.064 436.8-288-52.608-79.872-211.456-288-436.8-288zm0 64a224 224 0 1 1 0 448 224 224 0 0 1 0-448m0 64a160.192 160.192 0 0 0-160 160c0 88.192 71.744 160 160 160s160-71.808 160-160-71.744-160-160-160">
825          </path>
826        </svg>
827      </div>
828      <div id="svg-hide-media" title="隐藏图片/视频">
829        <svg onclick="displayMedia('none')" class="svg-style" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"
830          data-v-ea893728="">
831          <path fill="currentColor"
832            d="M876.8 156.8c0-9.6-3.2-16-9.6-22.4-6.4-6.4-12.8-9.6-22.4-9.6-9.6 0-16 3.2-22.4 9.6L736 220.8c-64-32-137.6-51.2-224-60.8-160 16-288 73.6-377.6 176C44.8 438.4 0 496 0 512s48 73.6 134.4 176c22.4 25.6 44.8 48 73.6 67.2l-86.4 89.6c-6.4 6.4-9.6 12.8-9.6 22.4 0 9.6 3.2 16 9.6 22.4 6.4 6.4 12.8 9.6 22.4 9.6 9.6 0 16-3.2 22.4-9.6l704-710.4c3.2-6.4 6.4-12.8 6.4-22.4Zm-646.4 528c-76.8-70.4-128-128-153.6-172.8 28.8-48 80-105.6 153.6-172.8C304 272 400 230.4 512 224c64 3.2 124.8 19.2 176 44.8l-54.4 54.4C598.4 300.8 560 288 512 288c-64 0-115.2 22.4-160 64s-64 96-64 160c0 48 12.8 89.6 35.2 124.8L256 707.2c-9.6-6.4-19.2-16-25.6-22.4Zm140.8-96c-12.8-22.4-19.2-48-19.2-76.8 0-44.8 16-83.2 48-112 32-28.8 67.2-48 112-48 28.8 0 54.4 6.4 73.6 19.2zM889.599 336c-12.8-16-28.8-28.8-41.6-41.6l-48 48c73.6 67.2 124.8 124.8 150.4 169.6-28.8 48-80 105.6-153.6 172.8-73.6 67.2-172.8 108.8-284.8 115.2-51.2-3.2-99.2-12.8-140.8-28.8l-48 48c57.6 22.4 118.4 38.4 188.8 44.8 160-16 288-73.6 377.6-176C979.199 585.6 1024 528 1024 512s-48.001-73.6-134.401-176Z">
833          </path>
834          <path fill="currentColor"
835            d="M511.998 672c-12.8 0-25.6-3.2-38.4-6.4l-51.2 51.2c28.8 12.8 57.6 19.2 89.6 19.2 64 0 115.2-22.4 160-64 41.6-41.6 64-96 64-160 0-32-6.4-64-19.2-89.6l-51.2 51.2c3.2 12.8 6.4 25.6 6.4 38.4 0 44.8-16 83.2-48 112-32 28.8-67.2 48-112 48Z">
836          </path>
837        </svg>
838      </div>
839    </div>
840    <div title="查看错误详情" class="btn-div">
841      <svg onclick="gotoTrace()" class="svg-style" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"
842        data-v-ea893728="">
843        <path fill="currentColor"
844          d="M832 384H576V128H192v768h640zm-26.496-64L640 154.496V320zM160 64h480l256 256v608a32 32 0 0 1-32 32H160a32 32 0 0 1-32-32V96a32 32 0 0 1 32-32m160 448h384v64H320zm0-192h160v64H320zm0 384h384v64H320z">
845        </path>
846      </svg>
847    </div>
848    <div title="回到顶部" class="scroll-top-btn"><svg class="svg-style" xmlns="http://www.w3.org/2000/svg"
849        viewBox="0 0 1024 1024" data-v-ea893728="">
850        <path fill="currentColor"
851          d="M572.235 205.282v600.365a30.118 30.118 0 1 1-60.235 0V205.282L292.382 438.633a28.913 28.913 0 0 1-42.646 0 33.43 33.43 0 0 1 0-45.236l271.058-288.045a28.913 28.913 0 0 1 42.647 0L834.5 393.397a33.43 33.43 0 0 1 0 45.176 28.913 28.913 0 0 1-42.647 0l-219.618-233.23z">
852        </path>
853      </svg></div>
854  </div>
855
856  <h4 class="h4">Execution Log</h4>
857  <div id="logs">
858    {% for log in logs.content %}
859    <div>{{ log | replace("\n", "<br>") }}</div>
860    {% endfor %}
861  </div>
862
863  <script>
864    const reportData = {{ case }};
865
866    const element = document.querySelector('#logs');
867    const elementPosition = element.offsetTop;
868    const btns = document.querySelector('.btns');
869    const scrollButton = document.querySelector('.scroll-top-btn');
870    window.addEventListener('scroll', () => {
871      if (window.scrollY > elementPosition + 200) {
872        btns.style.display = 'block';
873      } else {
874        btns.style.display = 'none';
875      }
876    });
877    scrollButton.addEventListener('click', function () {
878      window.scrollTo({
879        top: 0,
880        behavior: 'smooth'
881      });
882    });
883
884    // 获取ul元素
885    const ul = document.getElementById('phoneErrorPosition');
886    const imgDiv = document.querySelector('.img-div');
887    const err = document.querySelector('.err');
888    const dialog = document.getElementById('dialog');
889    const maskImgBg = document.querySelector('.mask-imgBg');
890    const detailsId = document.getElementById('details');
891
892    const { steps } = reportData;
893    if (!steps?.length) {
894      detailsId.remove();
895    } else {
896      addLi();
897    }
898
899    // 定义一个函数,用于将li数据渲染成HTML字符串
900    function renderLi(data, index) {
901      return `<li class="${data.error !== '' ? 'isPassed' : ''} ${data.isChecked ? 'isChecked' : ''}"  onclick="clickLi(${index})">
902        <div class="li-div">
903          <span title="${data.name}" class="li-span">${data.name}</span>
904          <span>
905            <span class="li-tag">${data.cost}s</span>
906            <span style="vertical-align: middle;" title="查看日志" onclick="gotoStep(${index})">
907              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" data-v-ea893728=""><path fill="currentColor" d="M832 384H576V128H192v768h640zm-26.496-64L640 154.496V320zM160 64h480l256 256v608a32 32 0 0 1-32 32H160a32 32 0 0 1-32-32V96a32 32 0 0 1 32-32m160 448h384v64H320zm0-192h160v64H320zm0 384h384v64H320z"></path></svg>
908            </span>
909          </span>
910        </div>
911      </li>`;
912    }
913
914    function renderTr(key, value) {
915      return `<td class="el-descriptions__cell el-descriptions__label is-bordered-label" colspan="1">${key}</td>
916              <td class="el-descriptions__cell el-descriptions__content is-bordered-content" colspan="3">${value}</td>`;
917    }
918
919    // 定义一个函数,用于添加li元素
920    function clickLi(index) {
921      const liList = ul.getElementsByTagName('li'); // 获取所有li元素
922      for (let i = 0; i < liList.length; i++) {
923        liList[i].classList.remove('isChecked');  // 移除class-name类名
924      }
925      const li = ul.getElementsByTagName('li')[index]; // 获取点击的li元素
926      li.classList.add('isChecked'); // 添加class-name
927      showStep(steps[index]);
928    }
929
930    function addLi() {
931      let step = steps.findIndex(item => item.error !== '');
932      if (step !== -1) {
933        steps[step].isChecked = true;
934        showStep(steps[step]);
935      } else {
936        steps[0].isChecked = true;
937        showStep(steps[0]);
938      }
939      steps.forEach((item, index) => {
940        ul.innerHTML += renderLi(item, index);
941      });
942    }
943
944    function showStep(step) {
945      const message = document.getElementById('message');
946      while (message.firstChild) {
947        message.removeChild(message.firstChild);
948      }
949      if (step.error) {
950        message.innerHTML = `<td class="el-descriptions__cell el-descriptions__label is-bordered-label" colspan="1">Error</td>
951                <td class="errorInfo el-descriptions__cell el-descriptions__content is-bordered-content error-content" colspan="7"
952                  style="color: red;">${step.error}
953                </td>`
954      }
955      let tds = []
956      for (const key in step.extras) {
957        let h = renderTr(key, step.extras[key]);
958        tds.push(h);
959      }
960      let count = 0;
961      let trs = null;
962      // 遍历所有的td元素
963      for (let i = 0; i < tds.length; i++) {
964        // 如果计数器为0,则创建一个新的tr元素
965        if (count === 0) {
966          trs = document.createElement('tr');
967        }
968        // 将当前的td元素添加到tr元素中
969        trs.innerHTML += tds[i];
970        // 计数器加1
971        count++;
972        // 如果计数器为2,则将tr元素添加到表格中,并将计数器重置为0
973        if (count === 2) {
974          message.appendChild(trs);
975          count = 0;
976        }
977      }
978      // 如果计数器不为0,则将剩余的td元素添加到一个新的tr元素中,并将其添加到表格中
979      if (count !== 0) {
980        message.appendChild(trs);
981      }
982      const screen = step.screenshot.reduce((acc, cur) => {
983        const prefix = cur.link.split('.')[0]; // 获取字符串中第一个 . 之前的部分作为前缀
984        if (!acc[prefix]) {
985          acc[prefix] = []; // 如果前缀不存在,则创建一个新的数组
986        }
987        acc[prefix].push(cur); // 将当前字符串添加到对应的数组中
988        return acc;
989      }, {});
990      const numOfProperties = Object.keys(screen).length;
991      const errScroll = document.querySelector('.err-scroll');
992      imgDiv.scrollTop = 0;
993      errScroll.scrollTop = 0;
994      while (imgDiv.firstChild) {
995        imgDiv.removeChild(imgDiv.firstChild);
996      }
997      if (numOfProperties > 1) {
998        multipleSn(screen);
999      } else {
1000        singleSn(screen);
1001      }
1002      if (message.children.length === 0) {
1003        errScroll.style.marginTop = 0;
1004      } else {
1005        errScroll.style.marginTop = '10px';
1006      }
1007    }
1008
1009    function singleSn(screen) {
1010      for (const [key, item] of Object.entries(screen)) {
1011        const title = document.createElement('div');
1012        const screenDiv = document.createElement('div');
1013        screenDiv.scrollLeft = 0;
1014        title.textContent = key.split('/')[1];
1015        screenDiv.appendChild(title);
1016        screenDiv.className = 'screen-div';
1017        screenDiv.style.textAlign = 'center';
1018        title.style.backgroundColor = '#f5f7fa';
1019        title.style.fontWeight = 700;
1020        title.style.lineHeight = '38px';
1021        title.style.color = '#606266';
1022        title.style.fontSize = '15px';
1023        const div2 = document.createElement('div');
1024        div2.style.display = 'flex';
1025        imgDiv.appendChild(title);
1026        imgDiv.style.display = 'block';
1027        imgDiv.style.textAlign = 'center';
1028        imgDiv.style.overflowX = 'hidden';
1029        screenDiv.style.overflowX = 'auto';
1030        for (let i = 0; i < item.length; i++) {
1031          const div = document.createElement('div');
1032          div.style.padding = '10px 0 20px 0';
1033          if (item.length > 1) {
1034            div.style.marginRight = '50px';
1035          }
1036          screenDiv.style.marginRight = '0';
1037          const div3 = document.createElement('div');
1038          if (item[i].link.includes('.avi') || item[i].link.includes('.mp4')) {
1039            div.appendChild(isVideo(item[i].link));
1040          } else {
1041            const img = isImage(item[i].link);
1042            div.appendChild(img);
1043            img.onload = function() {
1044              div3.style.width = img.width + 'px';
1045            }
1046          }
1047          const fileName = item[i].name;
1048          addStyle(div3, fileName);
1049          div.appendChild(div3);
1050          div2.appendChild(div);
1051          screenDiv.appendChild(div2);
1052        }
1053        imgDiv.appendChild(screenDiv);
1054      }
1055    }
1056
1057    function multipleSn(screen) {
1058      const noSingleDiv = document.createElement('div');
1059      noSingleDiv.style.backgroundColor = '#f5f7fa';
1060      noSingleDiv.style.height = '38px';
1061      noSingleDiv.style.width = '100%';
1062      noSingleDiv.style.position = 'absolute';
1063      noSingleDiv.style.zIndex = -1;
1064      imgDiv.appendChild(noSingleDiv);
1065      const keys = Object.keys(screen);
1066      const maxLength = Math.max(...keys.map(key => screen[key].length));
1067      // 构建新数组
1068      const result = [];
1069      for (let i = 0; i < maxLength; i++) {
1070        const item = {};
1071        keys.forEach(key => {
1072          item[key] = screen[key][i] || {
1073            link: '', name: ''
1074          }; // 如果属性值数组长度不够,用空字符串填充
1075        });
1076        result.push(item);
1077      }
1078      const tableImg = document.createElement('table');
1079      const theadImg = document.createElement('thead');
1080      const theadTrImg = document.createElement('tr');
1081      keys.forEach(item => {
1082        const thImg = document.createElement('th');
1083        thImg.textContent = item.split('/')[1];
1084        thImg.style.position = 'sticky';
1085        thImg.style.top = 0;
1086        thImg.style.backgroundColor = '#f5f7fa';
1087        thImg.style.zIndex = 10;
1088        theadTrImg.appendChild(thImg);
1089      })
1090      theadTrImg.style.height = '38px';
1091      theadTrImg.style.color = '#606266';
1092      theadTrImg.style.fontSize = '15px';
1093      theadImg.appendChild(theadTrImg);
1094      tableImg.appendChild(theadImg);
1095      tableImg.style.borderCollapse = 'collapse';
1096      const tbodyImg = document.createElement('tbody');
1097      for (let i = 0; i < maxLength; i++) {
1098        const trImg = document.createElement('tr');
1099        for (const key in result[i]) {
1100          const tdImg = document.createElement('td');
1101          const div = document.createElement('div');
1102          div.style.padding = '10px 0 20px 0';
1103          const div3 = document.createElement('div');
1104          div3.style.width = '230px';
1105          if (result[i][key].link.includes('.avi') || result[i][key].link.includes('.mp4')) {
1106            div.appendChild(isVideo(result[i][key].link));
1107          } else {
1108            const img = isImage(result[i][key].link);
1109            div.appendChild(img);
1110            img.onload = function() {
1111              div3.style.width = img.width + 'px';
1112            };
1113          }
1114          const fileName = result[i][key].name;
1115          addStyle(div3, fileName);
1116          div.appendChild(div3);
1117          div.style.minWidth = '470px';
1118          tdImg.appendChild(div);
1119          trImg.appendChild(tdImg);
1120        }
1121        tbodyImg.appendChild(trImg);
1122      }
1123      tableImg.appendChild(tbodyImg);
1124      imgDiv.appendChild(tableImg);
1125      imgDiv.style.display = 'flex';
1126      imgDiv.style.overflowX = 'auto';
1127      imgDiv.style.textAlign = 'center';
1128    }
1129
1130    function addStyle(div, fileName) {
1131      div.textContent = fileName;
1132      div.title = fileName;
1133      div.style.fontSize = '14px';
1134      div.style.margin = '0 auto';
1135      div.style.overflow = 'hidden';
1136      div.style. whiteSpace = 'nowrap';
1137      div.style.textOverflow = 'ellipsis';
1138    }
1139
1140    function isVideo(item) {
1141      const video = document.createElement('video');
1142      video.controls = 'controls';
1143      video.muted = 'muted';
1144      video.style.width = '236px';
1145      video.style.height = '514px';
1146      video.src = item;
1147      video.addEventListener('click', (event) => {
1148        clickScreenShot('video', item);
1149        if (!event.target.classList.contains('controls')) {
1150          event.preventDefault();
1151          return false;
1152        }
1153      });
1154      return video;
1155    }
1156
1157    function isImage(item) {
1158      const img = document.createElement('img');
1159      img.src = item;
1160      img.alt = '';
1161      img.style.cursor = 'pointer';
1162      img.addEventListener('click', (event) => clickScreenShot('img', item));
1163      if (item) {
1164        img.onerror = function () {
1165          img.style.width = '230px';
1166        };
1167      }
1168      return img;
1169    }
1170
1171    const clickScreenShot = (type, index) => {
1172      const screenHeight = window.innerHeight;
1173      dialog.style.display = 'flex';
1174      if (type === 'video') {
1175        const video = document.createElement('video');
1176        video.controls = 'controls';
1177        video.muted = 'muted';
1178        video.style.width = 'auto';
1179        video.style.height = 0.8 * screenHeight + 'px';
1180        video.src = index;
1181        maskImgBg.appendChild(video);
1182      } else {
1183        const img = document.createElement('img');
1184        img.src = index;
1185        img.alt = '';
1186        img.style.cursor = 'pointer';
1187        img.style.width = 'auto';
1188        img.style.height = 0.8 * screenHeight + 'px';
1189        maskImgBg.appendChild(img);
1190      }
1191    }
1192
1193    function closeDialog() {
1194      const images = maskImgBg.getElementsByTagName('img');
1195      for (let i = 0; i < images.length; i++) {
1196        maskImgBg.removeChild(images[i]);
1197      }
1198      const videos = maskImgBg.getElementsByTagName('video');
1199      for (let i = 0; i < videos.length; i++) {
1200        maskImgBg.removeChild(videos[i]);
1201      }
1202      dialog.style.display = 'none';
1203    }
1204
1205    function displayMedia(value) {
1206      const el_svg_show_media = document.getElementById('svg-show-media');
1207      const el_svg_hide_media = document.getElementById('svg-hide-media');
1208      const el_log = document.getElementById('logs');
1209      const el_images = el_log.getElementsByTagName('img');
1210      const el_videos = el_log.getElementsByTagName('video');
1211
1212      let elements = [];
1213      elements.push(...el_images, ...el_videos);
1214      for (let i = 0; i < elements.length; i++) {
1215        let element = elements[i];
1216        let element_a = element.parentNode;
1217        element.src = element_a.href;
1218        if (value === 'block') {
1219          element.style.display = 'block';
1220          el_svg_hide_media.style.display = 'block';
1221          el_svg_show_media.style.display = 'none';
1222        } else {
1223          element.style.display = 'none';
1224          el_svg_hide_media.style.display = 'none';
1225          el_svg_show_media.style.display = 'block';
1226        }
1227      }
1228    }
1229
1230    function gotoStep(stepId) {
1231      let element = document.getElementById(stepId);
1232      if (element != null) {
1233        let distance = element.offsetTop - 50;
1234        document.documentElement.scrollTo(0, distance);
1235      }
1236    }
1237
1238    function gotoTrace() {
1239      const columns = document.getElementsByClassName('col_error');
1240      if (columns.length === 0) {
1241        return;
1242      }
1243      const errorMsg = columns[0].textContent;
1244      if (!errorMsg) {
1245        return;
1246      }
1247      const elements = document.getElementById('logs').getElementsByClassName('error');
1248      for (let i = 0; i < elements.length; i++) {
1249        let element = elements[i];
1250        if (element.textContent.indexOf(errorMsg) >= 0) {
1251          document.documentElement.scrollTop = element.offsetTop;
1252          break;
1253        }
1254      }
1255    }
1256
1257    const rainbowText = document.getElementById('rainbowText');
1258    const textLength = rainbowText.offsetWidth;
1259    rainbowText.style.backgroundSize = `${textLength}px 100%`;
1260  </script>
1261</body>
1262
1263</html>