| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- <script lang="ts" setup>
- import CountTo from '@/components/count-to1.vue'
- import { IotStatApi } from '@/api/pms/stat'
- const mttr = ref(0)
- const loading = ref(false)
- function toNumber(value: unknown) {
- const num = Number(value)
- return Number.isFinite(num) ? num : 0
- }
- async function loadMttr() {
- loading.value = true
- try {
- const res = await IotStatApi.getMttr()
- mttr.value = toNumber(res)
- } catch (error) {
- console.error('获取 MTTR 失败:', error)
- mttr.value = 0
- } finally {
- loading.value = false
- }
- }
- onMounted(() => {
- loadMttr()
- })
- </script>
- <template>
- <div class="panel flex flex-col">
- <div class="panel-title panel-title--md">
- <div class="icon-decorator">
- <span></span>
- <span></span>
- </div>
- MTTR(平均解决时间)
- </div>
- <div
- class="metric-panel flex-1 min-h-0"
- style="
- /* stylelint-disable-next-line custom-property-empty-line-before */
- --metric-accent: #21b7b1;
- --metric-glow: rgb(33 183 177 / 16%);
- --metric-border: rgb(33 183 177 / 14%);
- --metric-tag-bg: rgb(33 183 177 / 10%);
- "
- >
- <div class="metric-panel__orbit metric-panel__orbit--outer"></div>
- <div class="metric-panel__top">
- <span class="metric-panel__tag">REPAIR</span>
- </div>
- <div class="metric-panel__center">
- <div class="metric-panel__headline">平均处理时长</div>
- <div class="metric-panel__value-row translate-x-1">
- <CountTo
- class="metric-panel__value"
- :start-val="0"
- :end-val="mttr"
- :duration="1200"
- :decimals="1"
- />
- <span class="metric-panel__unit">h</span>
- </div>
- </div>
- </div>
- </div>
- </template>
- <style lang="scss" scoped>
- @import url('@/styles/kb.scss');
- .metric-panel {
- position: relative;
- display: flex;
- padding: calc(12px * var(--kb-scale, 1)) calc(12px * var(--kb-scale, 1))
- calc(9px * var(--kb-scale, 1));
- overflow: hidden;
- flex-direction: column;
- }
- .metric-panel__orbit {
- position: absolute;
- left: 50%;
- border: 1px solid var(--metric-border);
- border-radius: 999px;
- transform: translateX(-50%);
- }
- .metric-panel__orbit--outer {
- top: calc(20px * var(--kb-scale, 1));
- width: calc(180px * var(--kb-scale, 1));
- height: calc(180px * var(--kb-scale, 1));
- }
- .metric-panel__top,
- .metric-panel__center {
- position: relative;
- z-index: 1;
- }
- .metric-panel__tag {
- display: inline-flex;
- padding: calc(4px * var(--kb-scale, 1)) calc(10px * var(--kb-scale, 1));
- font-family: YouSheBiaoTiHei, sans-serif;
- font-size: calc(14px * var(--kb-scale, 1));
- line-height: 1;
- letter-spacing: 1px;
- color: var(--metric-accent);
- background: var(--metric-tag-bg);
- border: 1px solid rgb(255 255 255 / 72%);
- border-radius: 999px;
- box-shadow: inset 0 1px 0 rgb(255 255 255 / 78%);
- }
- .metric-panel__center {
- display: flex;
- margin: auto 0;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- text-align: center;
- }
- .metric-panel__headline {
- font-size: calc(16px * var(--kb-scale, 1));
- font-weight: 600;
- letter-spacing: 1px;
- color: #4f678a;
- }
- .metric-panel__value-row {
- display: flex;
- margin-top: calc(10px * var(--kb-scale, 1));
- align-items: flex-end;
- justify-content: center;
- }
- .metric-panel__value {
- font-family: YouSheBiaoTiHei, sans-serif;
- font-size: calc(54px * var(--kb-scale, 1));
- line-height: 0.92;
- letter-spacing: 1px;
- color: var(--metric-accent);
- text-shadow: 0 10px 18px var(--metric-glow);
- }
- .metric-panel__unit {
- padding-bottom: calc(7px * var(--kb-scale, 1));
- margin-left: calc(4px * var(--kb-scale, 1));
- font-family: YouSheBiaoTiHei, sans-serif;
- font-size: calc(22px * var(--kb-scale, 1));
- line-height: 1;
- color: #5b789e;
- }
- </style>
|