Files
medical-mall/components/analytics/KpiCard.uvue
2026-01-22 21:15:02 +08:00

99 lines
1.7 KiB
Plaintext

<template>
<view class="kpi" :class="tone">
<text class="t">{{ title }}</text>
<text class="v">{{ value }}</text>
<view class="row" v-if="!deltaHidden">
<text class="delta" :class="delta >= 0 ? 'pos' : 'neg'">
{{ delta >= 0 ? '+' : '' }}{{ delta.toFixed(1) }}%
</text>
<text class="s">{{ subtitle }}</text>
</view>
<text class="s" v-else>{{ subtitle }}</text>
</view>
</template>
<script lang="uts">
export default {
props: {
title: { type: String, default: '' },
value: { type: String, default: '' },
subtitle: { type: String, default: '' },
delta: { type: Number, default: 0 },
tone: { type: String, default: 'danger' },
deltaHidden: { type: Boolean, default: false }
}
}
</script>
<style>
.kpi {
width: calc(50% - 7rpx);
padding: 16rpx;
border-radius: 16rpx;
color: #fff;
}
.t {
font-size: 22rpx;
opacity: 0.9;
}
.v {
font-size: 36rpx;
font-weight: 800;
margin-top: 10rpx;
display: block;
}
.row {
display: flex;
align-items: center;
gap: 10rpx;
margin-top: 10rpx;
}
.s {
font-size: 20rpx;
opacity: 0.85;
}
.delta {
font-size: 20rpx;
padding: 2rpx 10rpx;
border-radius: 999rpx;
background: rgba(255, 255, 255, 0.18);
font-weight: 700;
}
.delta.pos {
}
.delta.neg {
}
/* tones */
.danger {
background: linear-gradient(135deg, #ff6b6b 0%, #ff4d4f 100%);
}
.teal {
background: linear-gradient(135deg, #4ecdc4 0%, #44a08d 100%);
}
.green {
background: linear-gradient(135deg, #a8e6cf 0%, #7fcdbb 100%);
}
.amber {
background: linear-gradient(135deg, #ffd93d 0%, #ffa07a 100%);
}
@media screen and (max-width: 768px) {
.kpi {
width: 100%;
}
}
</style>