| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- <script lang="ts" setup>
- import CountTo from '@/components/count-to1.vue'
- import { IotStatApi } from '@/api/pms/stat'
- const safeCount = ref(0)
- const loading = ref(false)
- function toNumber(value: unknown) {
- const num = Number(value)
- return Number.isFinite(num) ? num : 0
- }
- async function loadSafeCount() {
- loading.value = true
- try {
- const res = await IotStatApi.getSafeCount()
- safeCount.value = toNumber(res)
- } catch (error) {
- console.error('获取库存预警数量失败:', error)
- safeCount.value = 0
- } finally {
- loading.value = false
- }
- }
- onMounted(() => {
- loadSafeCount()
- })
- </script>
- <template>
- <div class="panel flex flex-col">
- <div class="panel-title h-12">
- <div class="icon-decorator">
- <span></span>
- <span></span>
- </div>
- 库存预警物料数量
- </div>
- <div
- class="metric-panel flex-1 min-h-0"
- style="
- /* stylelint-disable-next-line custom-property-empty-line-before */
- --metric-accent: #ef6b6f;
- --metric-glow: rgb(239 107 111 / 18%);
- --metric-border: rgb(239 107 111 / 14%);
- --metric-tag-bg: rgb(239 107 111 / 10%);
- "
- >
- <div class="metric-panel__orbit metric-panel__orbit--outer"></div>
- <div class="metric-panel__orbit metric-panel__orbit--inner"></div>
- <div class="metric-panel__top">
- <span class="metric-panel__tag">ALERT</span>
- </div>
- <div class="metric-panel__body">
- <div class="metric-panel__center">
- <div class="metric-panel__headline">当前预警物料</div>
- <div class="metric-panel__value-row">
- <CountTo
- class="metric-panel__value"
- :start-val="0"
- :end-val="safeCount"
- :duration="1200"
- />
- </div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <style lang="scss" scoped>
- @import url('@/styles/kb.scss');
- .metric-panel {
- position: relative;
- display: grid;
- padding: 16px 14px 20px;
- overflow: hidden;
- grid-template-rows: auto minmax(0, 1fr);
- gap: 16px;
- }
- .metric-panel::before {
- position: absolute;
- inset: 54px 18px 16px;
- pointer-events: none;
- background: radial-gradient(
- circle at center,
- rgb(255 255 255 / 20%) 0%,
- rgb(255 255 255 / 0%) 72%
- );
- content: '';
- }
- .metric-panel__orbit {
- position: absolute;
- top: 56%;
- left: 50%;
- border: 1px solid var(--metric-border);
- border-radius: 999px;
- transform: translate(-50%, -50%);
- }
- .metric-panel__orbit--outer {
- width: 240px;
- height: 240px;
- }
- .metric-panel__orbit--inner {
- width: 188px;
- height: 188px;
- border-color: rgb(255 255 255 / 42%);
- opacity: 0.55;
- }
- .metric-panel__top,
- .metric-panel__body,
- .metric-panel__center {
- position: relative;
- z-index: 1;
- }
- .metric-panel__body {
- display: flex;
- min-height: 0;
- align-items: center;
- justify-content: center;
- }
- .metric-panel__tag {
- display: inline-flex;
- padding: 5px 12px;
- font-family: YouSheBiaoTiHei, sans-serif;
- font-size: 16px;
- line-height: 1;
- letter-spacing: 2px;
- 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;
- width: 100%;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- text-align: center;
- }
- .metric-panel__headline {
- font-size: 22px;
- font-weight: 600;
- letter-spacing: 2px;
- color: #4f678a;
- text-shadow: 0 4px 12px rgb(255 255 255 / 35%);
- }
- .metric-panel__value-row {
- display: flex;
- margin-top: 18px;
- align-items: flex-end;
- justify-content: center;
- }
- .metric-panel__value {
- font-family: YouSheBiaoTiHei, sans-serif;
- font-size: 90px;
- line-height: 0.88;
- letter-spacing: 2px;
- color: var(--metric-accent);
- text-shadow: 0 10px 18px var(--metric-glow);
- }
- </style>
|