优化
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import CustomerOperatingMetricCard from './CustomerOperatingMetricCard.vue'
|
||||
|
||||
describe('CustomerOperatingMetricCard', () => {
|
||||
const props = { title: '累计应收', value: '12.3456', unit: '万元', detail: '未结清 0.125 万元', tone: 'green' as const }
|
||||
|
||||
it('keeps the supplied decimal precision', () => {
|
||||
const wrapper = mount(CustomerOperatingMetricCard, { props })
|
||||
expect(wrapper.text()).toContain('12.3456万元')
|
||||
expect(wrapper.text()).toContain('未结清 0.125 万元')
|
||||
})
|
||||
|
||||
it('shows a dash instead of zero for failures', () => {
|
||||
const wrapper = mount(CustomerOperatingMetricCard, { props: { ...props, failed: true } })
|
||||
expect(wrapper.text()).toContain('—')
|
||||
expect(wrapper.text()).toContain('加载失败')
|
||||
expect(wrapper.text()).not.toContain('12.3456')
|
||||
})
|
||||
|
||||
it('shows the permission state without exposing a value', () => {
|
||||
const wrapper = mount(CustomerOperatingMetricCard, { props: { ...props, unauthorized: true } })
|
||||
expect(wrapper.text()).toContain('暂无查看权限')
|
||||
expect(wrapper.text()).not.toContain('12.3456')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
title: string
|
||||
value: string
|
||||
unit: string
|
||||
detail: string
|
||||
loading?: boolean
|
||||
failed?: boolean
|
||||
unauthorized?: boolean
|
||||
tone: 'blue' | 'green' | 'amber'
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article class="operating-metric-card" :aria-label="title" :aria-busy="loading || undefined">
|
||||
<span class="metric-icon" :class="`is-${tone}`" aria-hidden="true"><slot name="icon" /></span>
|
||||
<div class="metric-content">
|
||||
<p>{{ title }}</p>
|
||||
<strong v-if="loading" class="metric-loading" aria-label="加载中">—</strong>
|
||||
<strong v-else-if="failed || unauthorized">—</strong>
|
||||
<strong v-else>{{ value }}<small>{{ unit }}</small></strong>
|
||||
<span :class="{ 'is-error': failed }">{{ unauthorized ? '暂无查看权限' : failed ? '加载失败' : loading ? '加载中…' : detail }}</span>
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.operating-metric-card { display:flex; min-width:0; align-items:center; gap:14px; padding:22px 24px; border-right:1px solid var(--cc-border); }
|
||||
.metric-icon { display:grid; width:44px; height:44px; flex:0 0 auto; place-items:center; border-radius:12px; }
|
||||
.metric-icon.is-blue { background:linear-gradient(135deg,rgba(102,126,234,.15),rgba(118,75,162,.1)); color:#667eea; }
|
||||
.metric-icon.is-green { background:linear-gradient(135deg,rgba(34,197,94,.15),rgba(22,163,74,.1)); color:#16a34a; }
|
||||
.metric-icon.is-amber { background:linear-gradient(135deg,rgba(245,158,11,.15),rgba(234,88,12,.1)); color:#ea580c; }
|
||||
.metric-content { min-width:0; }
|
||||
p,span { margin:0; color:var(--cc-muted); font-size:12px; }
|
||||
strong { display:block; min-width:0; margin:5px 0 4px; color:#172033; font-size:26px; line-height:1; overflow-wrap:anywhere; }
|
||||
small { margin-left:5px; color:#475467; font-size:12px; font-weight:600; white-space:nowrap; }
|
||||
.is-error { color:#d92d20; }
|
||||
.metric-loading { color:#98a2b3; }
|
||||
@media (max-width:720px) { .operating-metric-card { border-right:0; border-bottom:1px solid var(--cc-border); } }
|
||||
@media (max-width:360px) { .operating-metric-card { gap:10px; padding:18px 14px; }.metric-icon { width:40px; height:40px; }strong { font-size:23px; } }
|
||||
</style>
|
||||
Reference in New Issue
Block a user