first commit
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
<!--
|
||||
* 信用分 — 对齐 C端.html #sub-credit-detail (~line 3055)
|
||||
* 当前信用分仪表盘 + 五维度构成 + 等级说明
|
||||
-->
|
||||
<template>
|
||||
<view class="sub-page">
|
||||
<nav-bar title="信用分" :show-back="true" @back="closeSub()" />
|
||||
|
||||
<scroll-view scroll-y class="page-content">
|
||||
<text class="sub-hint" v-if="deviceId">📡 单设备 · 由中控平台计算并推送</text>
|
||||
<text class="sub-hint" v-else>📊 全部设备信用分均值 · 点击设备详情查看单设备明细</text>
|
||||
|
||||
<!-- 当前信用分仪表盘 -->
|
||||
<view class="score-card">
|
||||
<view class="sc-glow"></view>
|
||||
<view class="sc-inner">
|
||||
<text class="sc-label">当前信用分</text>
|
||||
|
||||
<view class="sc-ring-wrap">
|
||||
<svg viewBox="0 0 120 120" class="sc-svg">
|
||||
<circle fill="none" stroke="#E6F4FF" stroke-width="10" cx="60" cy="60" r="52" />
|
||||
<circle stroke-dashoffset="33" cx="60" cy="60" stroke-width="10" stroke-dasharray="326.7"
|
||||
r="52" fill="none" stroke="url(#creditGrad)" stroke-linecap="round" />
|
||||
<defs>
|
||||
<linearGradient id="creditGrad" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="#1677FF" />
|
||||
<stop offset="100%" stop-color="#00C4A7" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
<view class="sc-ring-center">
|
||||
<text class="src-score">{{ creditScore }}</text>
|
||||
<text class="src-total">/ 100</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<text class="sc-badge">{{ scoreLabel }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 信用分构成(五维度)— 仅单设备模式展示 -->
|
||||
<view class="card" v-if="deviceId">
|
||||
<text class="card-title">信用分构成(五维度)</text>
|
||||
<view class="info-row" v-for="d in dimensions" :key="d.name">
|
||||
<text class="ir-label">{{ d.name }} (权重{{ d.weight }}%)</text>
|
||||
<text class="ir-val">{{ d.raw }} → {{ d.score }}分</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="card" v-else>
|
||||
<text class="card-title">信用分构成(五维度)</text>
|
||||
<view class="info-row" style="justify-content:center;padding:24rpx 0;">
|
||||
<text class="ir-label" style="color:#8B91A1;">查看单设备信用分明细请从设备详情页进入</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 信用分等级说明 -->
|
||||
<view class="card">
|
||||
<text class="card-title">信用分等级说明</text>
|
||||
<view class="info-row" v-for="g in grades" :key="g.label">
|
||||
<text class="ir-label">{{ g.label }} ({{ g.range }})</text>
|
||||
<text class="ir-val" :style="{ color: g.color }">{{ g.bonus }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="height: 40rpx;"></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import NavBar from '@/components/NavBar.vue'
|
||||
import request from '@/utils/request'
|
||||
import { ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { closeSub, parseSubParams } from '@/composables/useNavigation'
|
||||
|
||||
const creditScore = ref(96)
|
||||
const dimensions = ref([])
|
||||
const scoreLabel = ref('良好 · 质量良好')
|
||||
const deviceId = ref('')
|
||||
|
||||
onLoad(async (options) => {
|
||||
const params = parseSubParams(options)
|
||||
deviceId.value = params.id || ''
|
||||
|
||||
if (deviceId.value) {
|
||||
// 单设备详情模式:从设备API获取
|
||||
await loadDeviceCredit(deviceId.value)
|
||||
} else {
|
||||
// 用户总览模式(从我的/首页进入,无 device_id):取全部设备均值
|
||||
await loadUserCredit()
|
||||
}
|
||||
})
|
||||
|
||||
const loadDeviceCredit = async (deviceId) => {
|
||||
try {
|
||||
const res = await request.get('/c/devices/' + deviceId, { showLoading: false })
|
||||
const d = res.data
|
||||
creditScore.value = d.credit_score ?? 96
|
||||
dimensions.value = d.credit_dimensions || []
|
||||
const cs = creditScore.value
|
||||
scoreLabel.value = cs >= 95 ? '优秀 · 质量优秀' : cs >= 80 ? '良好 · 质量良好' : cs >= 60 ? '一般 · 质量一般' : '极差 · 待优化'
|
||||
} catch (e) { /* 设备不存在 */ }
|
||||
}
|
||||
|
||||
const loadUserCredit = async () => {
|
||||
try {
|
||||
const res = await request.get('/c/profile', { showLoading: false })
|
||||
const cs = res.data?.avg_credit_score
|
||||
if (cs !== undefined && cs !== null) {
|
||||
creditScore.value = cs
|
||||
}
|
||||
dimensions.value = [
|
||||
{ name: '带宽达标率', weight: 30, raw: '--', score: '--' },
|
||||
{ name: '丢包率', weight: 25, raw: '--', score: '--' },
|
||||
{ name: '延迟', weight: 20, raw: '--', score: '--' },
|
||||
{ name: '上游回传', weight: 15, raw: '--', score: '--' },
|
||||
{ name: 'NAT稳定性', weight: 10, raw: '--', score: '--' },
|
||||
]
|
||||
const csVal = creditScore.value
|
||||
scoreLabel.value = csVal >= 95 ? '优秀 · 质量优秀' : csVal >= 80 ? '良好 · 质量良好' : csVal >= 60 ? '一般 · 质量一般' : '极差 · 待优化'
|
||||
} catch (e) { /* 忽略 */ }
|
||||
}
|
||||
|
||||
const goBack = () => closeSub()
|
||||
|
||||
const grades = ref([
|
||||
{ label: '优秀', range: '≥95', bonus: '收益加成 1.2x', color: '#00C4A7' },
|
||||
{ label: '良好', range: '80-94', bonus: '收益加成 1.0x', color: '#1677FF' },
|
||||
{ label: '一般', range: '60-79', bonus: '收益加成 0.8x', color: '#FF8800' },
|
||||
{ label: '极差', range: '<40', bonus: '暂停结算', color: '#FF4D4F' }
|
||||
])
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.sub-page { height: 100vh; display: flex; flex-direction: column; overflow: hidden; background: #F2F4F8; }
|
||||
.page-content { flex: 1; height: 0; padding: 0 24rpx 40rpx; }
|
||||
|
||||
.sub-hint { font-size: 20rpx; color: #BCC2CE; display: block; padding: 16rpx 0 12rpx; }
|
||||
|
||||
/* 仪表盘卡片 */
|
||||
.score-card {
|
||||
background: linear-gradient(135deg, #F0F7FF, #F0F7FF);
|
||||
border-radius: 16rpx;
|
||||
text-align: center;
|
||||
margin-bottom: 16rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.sc-glow {
|
||||
position: absolute; top: -60rpx; right: -60rpx; width: 200rpx; height: 200rpx;
|
||||
border-radius: 50%; background: radial-gradient(circle, rgba(22,119,255,.12), transparent 70%);
|
||||
}
|
||||
.sc-inner { position: relative; z-index: 1; padding: 24rpx 0 28rpx; }
|
||||
.sc-label { font-size: 24rpx; color: #8B91A1; display: block; margin-bottom: 16rpx; }
|
||||
|
||||
.sc-ring-wrap {
|
||||
width: 240rpx; height: 240rpx; margin: 0 auto 20rpx; position: relative;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.sc-svg {
|
||||
width: 100%; height: 100%; position: absolute; top: 0; left: 0;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
.sc-ring-center { display: flex; flex-direction: column; align-items: center; justify-content: center; }
|
||||
.src-score { font-size: 72rpx; font-weight: 800; color: #1677FF; line-height: 1; font-family: 'DIN Alternate', -apple-system, sans-serif; }
|
||||
.src-total { font-size: 20rpx; color: #8B91A1; margin-top: 4rpx; }
|
||||
|
||||
.sc-badge {
|
||||
display: inline-block; font-size: 26rpx; font-weight: 600; padding: 8rpx 24rpx;
|
||||
border-radius: 32rpx; background: #E6FAF5; color: #00C4A7;
|
||||
}
|
||||
|
||||
/* 卡片 */
|
||||
.card { background: #fff; border-radius: 16rpx; padding: 28rpx 24rpx; margin-bottom: 16rpx; box-shadow: 0 1px 3px rgba(15,18,38,.04); }
|
||||
.card-title { font-size: 28rpx; font-weight: 600; color: #0F1226; display: block; margin-bottom: 20rpx; }
|
||||
|
||||
.info-row {
|
||||
display: flex; justify-content: space-between; align-items: center;
|
||||
padding: 14rpx 0; border-bottom: 0.5px solid #F3F5F9;
|
||||
&:last-child { border-bottom: none; }
|
||||
}
|
||||
.ir-label { font-size: 24rpx; color: #5A6072; }
|
||||
.ir-val { font-size: 24rpx; color: #00C4A7; font-weight: 500; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user