|
@@ -1,20 +1,95 @@
|
|
|
<template>
|
|
<template>
|
|
|
<!-- 我的 -->
|
|
<!-- 我的 -->
|
|
|
<div class="user-index">
|
|
<div class="user-index">
|
|
|
- <div class="loan-info">
|
|
|
|
|
- <div class="info-left">
|
|
|
|
|
- <img src="../../assets/img/index/user/default-head.png" alt="" />
|
|
|
|
|
- <div class="info-name" @click="deleteAccount">
|
|
|
|
|
- <div class="name-area pf500 fs18 fc121212">
|
|
|
|
|
- 用户昵称
|
|
|
|
|
- <div class="level pf500 fs12 fcDF384C" @click.stop="router.push({name: 'VipCenter'})">V2</div>
|
|
|
|
|
|
|
+ <!-- 导航栏 -->
|
|
|
|
|
+
|
|
|
|
|
+ <div class="content">
|
|
|
|
|
+ <div class="user-card">
|
|
|
|
|
+ <!-- 左侧信息保持不变 -->
|
|
|
|
|
+ <div class="card-left">
|
|
|
|
|
+ <div class="avatar-box">
|
|
|
|
|
+ <img :src="userInfo.avatar" alt="Avatar" class="avatar-img" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="info-box">
|
|
|
|
|
+ <div class="name-row">
|
|
|
|
|
+ <span class="user-name">{{ userInfo.nickname }}</span>
|
|
|
|
|
+ <span class="vip-badge">{{ userInfo.level }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="user-id">ID: {{ userInfo.id }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 右侧:动态信用分仪表盘 -->
|
|
|
|
|
+ <div class="card-right">
|
|
|
|
|
+ <div class="score-chart">
|
|
|
|
|
+ <svg viewBox="0 0 100 100" class="chart-svg">
|
|
|
|
|
+ <!--
|
|
|
|
|
+ 第一层:灰色底轨 (Background Segments)
|
|
|
|
|
+ 遍历配置生成4段灰色轨迹,作为槽位
|
|
|
|
|
+ -->
|
|
|
|
|
+ <circle
|
|
|
|
|
+ v-for="(item, index) in backgroundSegments"
|
|
|
|
|
+ :key="`bg-${index}`"
|
|
|
|
|
+ cx="50" cy="50" :r="radius"
|
|
|
|
|
+ fill="none"
|
|
|
|
|
+ stroke="#E5E9F2"
|
|
|
|
|
+ stroke-width="6"
|
|
|
|
|
+ :stroke-dasharray="item.dashArray"
|
|
|
|
|
+ stroke-linecap="round"
|
|
|
|
|
+ :transform="item.transform"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <!--
|
|
|
|
|
+ 第二层:彩色进度 (Progress Segments)
|
|
|
|
|
+ 根据分数覆盖在底轨之上
|
|
|
|
|
+ -->
|
|
|
|
|
+ <circle
|
|
|
|
|
+ v-for="(item, index) in progressSegments"
|
|
|
|
|
+ :key="`prog-${index}`"
|
|
|
|
|
+ cx="50" cy="50" :r="radius"
|
|
|
|
|
+ fill="none"
|
|
|
|
|
+ :stroke="item.color"
|
|
|
|
|
+ stroke-width="6"
|
|
|
|
|
+ :stroke-dasharray="item.dashArray"
|
|
|
|
|
+ stroke-linecap="round"
|
|
|
|
|
+ :transform="item.transform"
|
|
|
|
|
+ />
|
|
|
|
|
+ </svg>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 环内文字 -->
|
|
|
|
|
+ <div class="score-text">
|
|
|
|
|
+ <div class="score-num">{{ creditScore }}</div>
|
|
|
|
|
+ <div class="score-label">信用分</div>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="pf400 fs14 fc6A7187" >ID: 658908</div>
|
|
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="info-right"></div>
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 调试滑块 (实际使用可删除) -->
|
|
|
|
|
+<!-- <div class="debug-slider">-->
|
|
|
|
|
+<!-- <div class="slider-header">-->
|
|
|
|
|
+<!-- <span>当前分数: {{ creditScore }}</span>-->
|
|
|
|
|
+<!-- <span style="font-size:12px; color:#999">拖动查看未填满时的灰色效果</span>-->
|
|
|
|
|
+<!-- </div>-->
|
|
|
|
|
+<!-- <input type="range" min="0" max="100" v-model.number="creditScore" class="custom-range" />-->
|
|
|
|
|
+<!-- </div>-->
|
|
|
|
|
+
|
|
|
</div>
|
|
</div>
|
|
|
- <img src="../../assets/img/user/Invite Friends.svg" class="invite-friend" alt="" @click="router.push('/invite')"/>
|
|
|
|
|
|
|
+<!-- <div class="loan-info">-->
|
|
|
|
|
+<!-- <div class="info-left">-->
|
|
|
|
|
+<!-- <img src="../../assets/img/index/user/default-head.png" alt="" />-->
|
|
|
|
|
+<!-- <div class="info-name" @click="deleteAccount">-->
|
|
|
|
|
+<!-- <div class="name-area pf500 fs18 fc121212">-->
|
|
|
|
|
+<!-- 用户昵称-->
|
|
|
|
|
+<!-- <div class="level pf500 fs12 fcDF384C" @click.stop="router.push({name: 'VipCenter'})">V2</div>-->
|
|
|
|
|
+<!-- </div>-->
|
|
|
|
|
+<!-- <div class="pf400 fs14 fc6A7187" >ID: 658908</div>-->
|
|
|
|
|
+<!-- </div>-->
|
|
|
|
|
+<!-- </div>-->
|
|
|
|
|
+<!-- <div class="info-right"></div>-->
|
|
|
|
|
+<!-- </div>-->
|
|
|
|
|
+<!-- <div style="width: 375px; b"></div>-->
|
|
|
|
|
+ <img src="@/assets/icon/user/yaoqi.svg" class="invite-friend" alt="" @click="router.push('/invite')"/>
|
|
|
<div class="user-func">
|
|
<div class="user-func">
|
|
|
<div
|
|
<div
|
|
|
class="func-item"
|
|
class="func-item"
|
|
@@ -30,17 +105,114 @@
|
|
|
<img src="../../assets/icon/user/right-arrow.svg" class="right-arrow" alt="" />
|
|
<img src="../../assets/icon/user/right-arrow.svg" class="right-arrow" alt="" />
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="submit pf600 fs14 fcFFFFFF">退出</div>
|
|
|
|
|
|
|
+ <div class="submit pf600 fs14 fcFFFFFF" @click="out=true">退出</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <logout v-model:visible="out"></logout>
|
|
|
</template>
|
|
</template>
|
|
|
<script setup>
|
|
<script setup>
|
|
|
|
|
+ import logout from '@/views/user/Logout.vue'
|
|
|
|
|
+ import { ref, computed } from 'vue';
|
|
|
import { useRoute, useRouter } from "vue-router";
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
|
|
+ const out = ref(false);
|
|
|
|
|
+const userInfo = ref({
|
|
|
|
|
+ nickname: '用户昵称',
|
|
|
|
|
+ id: '658908',
|
|
|
|
|
+ level: 'V2',
|
|
|
|
|
+ avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felix'
|
|
|
|
|
+});
|
|
|
|
|
|
|
|
- const deleteAccount = () => {
|
|
|
|
|
- router.push("/deleteAccount");
|
|
|
|
|
- };
|
|
|
|
|
|
|
+// --- 核心配置 ---
|
|
|
|
|
+const creditScore = ref(90); // 当前分数
|
|
|
|
|
+const maxScore = 100; // 满分
|
|
|
|
|
+
|
|
|
|
|
+const radius = 42;
|
|
|
|
|
+const circumference = 2 * Math.PI * radius; // 周长 ≈ 263.89
|
|
|
|
|
+
|
|
|
|
|
+// 修改 1: 起始角度改为 -90 度 (从顶部正中间开始,顺时针绘制)
|
|
|
|
|
+const startAngle = -270;
|
|
|
|
|
+const gapLength = 10; // 每一段之间的间隙 (像素)
|
|
|
|
|
+
|
|
|
|
|
+// 修改 2: 总有效长度改为完整圆周长 (不再乘 0.75,变成闭合圆环)
|
|
|
|
|
+const totalArcLength = circumference;
|
|
|
|
|
+
|
|
|
|
|
+// 颜色段配置 (总分需等于100)
|
|
|
|
|
+// 这里的顺序决定了圆环颜色的排列顺序
|
|
|
|
|
+const configSegments = [
|
|
|
|
|
+ { max: 50, color: '#2B6BFF' }, // 蓝色
|
|
|
|
|
+ { max: 20, color: '#FF4D6A' }, // 红色
|
|
|
|
|
+ { max: 15, color: '#FFAA00' }, // 黄色
|
|
|
|
|
+ { max: 15, color: '#00C087' }, // 绿色
|
|
|
|
|
+];
|
|
|
|
|
+
|
|
|
|
|
+// --- 辅助函数:计算一段圆弧的几何信息 ---
|
|
|
|
|
+const calculateSegmentGeometry = (segmentMaxScore, currentStartAngle) => {
|
|
|
|
|
+ // 1. 计算这一段理论上应该占多长 (像素)
|
|
|
|
|
+ const ratio = segmentMaxScore / maxScore;
|
|
|
|
|
+ let arcLength = ratio * totalArcLength;
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 减去间隙 (视觉上扣除,防止连在一起)
|
|
|
|
|
+ // 实际绘制长度不能小于0
|
|
|
|
|
+ const drawLength = Math.max(0, arcLength - gapLength);
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 计算这一段占用的角度 (包含被扣除的间隙,用于计算下一段的起点)
|
|
|
|
|
+ const angleSpan = (arcLength / circumference) * 360;
|
|
|
|
|
+
|
|
|
|
|
+ return { drawLength, angleSpan };
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// --- 计算属性 1: 底轨片段 (灰色) ---
|
|
|
|
|
+const backgroundSegments = computed(() => {
|
|
|
|
|
+ let currentAngle = startAngle;
|
|
|
|
|
+ return configSegments.map(seg => {
|
|
|
|
|
+ const { drawLength, angleSpan } = calculateSegmentGeometry(seg.max, currentAngle);
|
|
|
|
|
+
|
|
|
|
|
+ const result = {
|
|
|
|
|
+ dashArray: `${drawLength}, ${circumference}`,
|
|
|
|
|
+ transform: `rotate(${currentAngle}, 50, 50)`
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ currentAngle += angleSpan; // 移动到下一段起点
|
|
|
|
|
+ return result;
|
|
|
|
|
+ });
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// --- 计算属性 2: 进度片段 (彩色) ---
|
|
|
|
|
+const progressSegments = computed(() => {
|
|
|
|
|
+ let currentAngle = startAngle;
|
|
|
|
|
+ let remainingScore = creditScore.value;
|
|
|
|
|
+
|
|
|
|
|
+ return configSegments.map(seg => {
|
|
|
|
|
+ const { drawLength, angleSpan } = calculateSegmentGeometry(seg.max, currentAngle);
|
|
|
|
|
+
|
|
|
|
|
+ // 计算这一段应该填满多少
|
|
|
|
|
+ let fillRatio = 0;
|
|
|
|
|
+ if (remainingScore >= seg.max) {
|
|
|
|
|
+ fillRatio = 1; // 填满
|
|
|
|
|
+ } else if (remainingScore > 0) {
|
|
|
|
|
+ fillRatio = remainingScore / seg.max; // 填一部分
|
|
|
|
|
+ } else {
|
|
|
|
|
+ fillRatio = 0; // 不填
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const currentDrawLength = drawLength * fillRatio;
|
|
|
|
|
+
|
|
|
|
|
+ const result = {
|
|
|
|
|
+ color: seg.color,
|
|
|
|
|
+ dashArray: `${currentDrawLength}, ${circumference}`,
|
|
|
|
|
+ transform: `rotate(${currentAngle}, 50, 50)`
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ currentAngle += angleSpan;
|
|
|
|
|
+ remainingScore -= seg.max;
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+ });
|
|
|
|
|
+});
|
|
|
|
|
+ // const deleteAccount = () => {
|
|
|
|
|
+ // router.push("/deleteAccount");
|
|
|
|
|
+ // };
|
|
|
|
|
|
|
|
const goMenuRouter = (index, item) => {
|
|
const goMenuRouter = (index, item) => {
|
|
|
if (index == 1) {
|
|
if (index == 1) {
|
|
@@ -51,13 +223,14 @@
|
|
|
router.push({ name: 'AdvancedCertification' });
|
|
router.push({ name: 'AdvancedCertification' });
|
|
|
}else if (index === 3) {
|
|
}else if (index === 3) {
|
|
|
router.push({ name: 'KycForm' });
|
|
router.push({ name: 'KycForm' });
|
|
|
- }
|
|
|
|
|
- else if (index === 5) {
|
|
|
|
|
|
|
+ }else if (index === 5) {
|
|
|
router.push({ name: 'LanguageSwitch' });
|
|
router.push({ name: 'LanguageSwitch' });
|
|
|
}else if (index === 7) {
|
|
}else if (index === 7) {
|
|
|
router.push({ name: 'HelpCenter' });
|
|
router.push({ name: 'HelpCenter' });
|
|
|
}else if (index === 8) {
|
|
}else if (index === 8) {
|
|
|
router.push({ name: 'AboutUs' });
|
|
router.push({ name: 'AboutUs' });
|
|
|
|
|
+ }else if (index === 0) {
|
|
|
|
|
+ router.push({ name: 'SecuritySettings' });
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -171,9 +344,11 @@
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.invite-friend {
|
|
.invite-friend {
|
|
|
- margin-top: 20px;
|
|
|
|
|
- width: 327px;
|
|
|
|
|
|
|
+ margin: 0 auto;
|
|
|
|
|
+ //margin-top: 20px;
|
|
|
|
|
+ width: 360px ;
|
|
|
height: 68px;
|
|
height: 68px;
|
|
|
|
|
+ padding-left: 15px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.user-func {
|
|
.user-func {
|
|
@@ -185,7 +360,7 @@
|
|
|
justify-content: space-between;
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
margin-top: 26.5px;
|
|
margin-top: 26.5px;
|
|
|
- width: 340px;
|
|
|
|
|
|
|
+ width: 355px;
|
|
|
height: 24px;
|
|
height: 24px;
|
|
|
|
|
|
|
|
&:first-child {
|
|
&:first-child {
|
|
@@ -231,4 +406,73 @@
|
|
|
letter-spacing: 0.2px;
|
|
letter-spacing: 0.2px;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ //xin
|
|
|
|
|
+.nav-bar {
|
|
|
|
|
+ display: flex; justify-content: space-between; align-items: center;
|
|
|
|
|
+ height: 44px; padding: 0 16px; background: #fff;
|
|
|
|
|
+ position: sticky; top: 0; z-index: 10;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ .icon1{ padding-left: 15px;}
|
|
|
|
|
+}
|
|
|
|
|
+.nav-title { font-size: 18px; font-weight: 500; color: #333; }
|
|
|
|
|
+.nav-left, .nav-right { width: 40px; }
|
|
|
|
|
+
|
|
|
|
|
+.content { width:100%;padding: 15px; }
|
|
|
|
|
+
|
|
|
|
|
+.user-card {
|
|
|
|
|
+ background: #fff; border-radius: 16px; padding: 0px 0 0 15px;
|
|
|
|
|
+ display: flex; justify-content: space-between; align-items: center;
|
|
|
|
|
+ //box-shadow: 0 4px 12px rgba(0,0,0,0.03);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.card-left { display: flex; align-items: center; }
|
|
|
|
|
+.avatar-box {
|
|
|
|
|
+ width: 56px; height: 56px; border-radius: 50%; overflow: hidden;
|
|
|
|
|
+ background: #E0E6ED; margin-right: 12px; border: 1px solid #f0f0f0;
|
|
|
|
|
+}
|
|
|
|
|
+.avatar-img { width: 100%; height: 100%; object-fit: cover; }
|
|
|
|
|
+
|
|
|
|
|
+.info-box { display: flex; flex-direction: column; justify-content: center; }
|
|
|
|
|
+.name-row { display: flex; align-items: center; margin-bottom: 6px; }
|
|
|
|
|
+.user-name { font-size: 18px; font-weight: 600; color: #1A1A1A; margin-right: 8px; }
|
|
|
|
|
+.vip-badge {
|
|
|
|
|
+ background-color: #FDEEEE; color: #E02F44; font-size: 10px; font-weight: 700;
|
|
|
|
|
+ padding: 1px 5px; border-radius: 4px; line-height: 1.4; font-style: italic;
|
|
|
|
|
+}
|
|
|
|
|
+.user-id { font-size: 14px; color: #858B9C; }
|
|
|
|
|
+
|
|
|
|
|
+.card-right { position: relative; }
|
|
|
|
|
+.score-chart {
|
|
|
|
|
+ width: 90px; height: 90px; position: relative;
|
|
|
|
|
+ display: flex; align-items: center; justify-content: center;
|
|
|
|
|
+}
|
|
|
|
|
+.chart-svg {
|
|
|
|
|
+ width: 100%; height: 100%;
|
|
|
|
|
+ transform: rotate(0deg);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.score-text {
|
|
|
|
|
+ position: absolute; text-align: center;
|
|
|
|
|
+ top: 50%; left: 50%;
|
|
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
|
|
+}
|
|
|
|
|
+.score-num {
|
|
|
|
|
+ font-size: 22px; font-weight: 700; color: #1A1A1A; line-height: 1; margin-bottom: 2px;
|
|
|
|
|
+}
|
|
|
|
|
+.score-label {
|
|
|
|
|
+ font-size: 10px; color: #858B9C; transform: scale(0.9);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 调试滑块样式 */
|
|
|
|
|
+.debug-slider {
|
|
|
|
|
+ margin-top: 20px; padding: 15px; background: #fff; border-radius: 12px;
|
|
|
|
|
+}
|
|
|
|
|
+.slider-header {
|
|
|
|
|
+ display: flex; justify-content: space-between; margin-bottom: 10px; font-size: 14px; color: #333;
|
|
|
|
|
+}
|
|
|
|
|
+.custom-range {
|
|
|
|
|
+ width: 100%; accent-color: #2B6BFF;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|