feat: 重构用户中心页面UI
This commit is contained in:
@@ -160,6 +160,15 @@ export interface UserInfo {
|
||||
/** 头像URL */
|
||||
avatar?: string
|
||||
|
||||
/** 手机号 */
|
||||
mobile?: string
|
||||
|
||||
/** 邮箱 */
|
||||
email?: string
|
||||
|
||||
/** 部门名称 */
|
||||
deptName?: string
|
||||
|
||||
/** 角色编码集合 */
|
||||
roles?: string[]
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<view class="page-container dark:text-[var(--wot-color-text)]">
|
||||
<view class="page-container">
|
||||
<!-- 用户信息卡片 -->
|
||||
<view class="user-profile" :style="{ paddingTop: navbar.totalHeight.value + 'px' }">
|
||||
<view class="user-profile" :style="{ paddingTop: navbar.statusBarHeight.value + 'px' }">
|
||||
<view class="blur-bg" />
|
||||
|
||||
<view class="user-info">
|
||||
@@ -16,6 +16,9 @@
|
||||
<block v-if="isLogin">
|
||||
<view class="nickname">
|
||||
{{ userInfo!.nickname || "匿名用户" }}
|
||||
<text v-if="genderLabel" class="gender-badge" :class="genderClass">
|
||||
{{ genderLabel }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="user-id">ID: {{ userInfo?.username || "0000000" }}</view>
|
||||
</block>
|
||||
@@ -35,10 +38,13 @@
|
||||
<!-- 操作按钮区域 - 避开胶囊按钮 -->
|
||||
<view
|
||||
class="action-buttons"
|
||||
:style="{ marginRight: navbar.menuButtonRightGap.value + 8 + 'px' }"
|
||||
:style="{
|
||||
right: navbar.menuButtonRightGap.value + 8 + 'px',
|
||||
top: actionButtonsTop,
|
||||
}"
|
||||
>
|
||||
<view class="action-btn" @click="navigateToSettings">
|
||||
<wd-icon name="setting1" size="22" color="#fff" />
|
||||
<wd-icon name="setting" size="22" color="#fff" />
|
||||
</view>
|
||||
<view v-if="isLogin" class="action-btn relative" @click="navigateToSection('messages')">
|
||||
<wd-icon name="notification" size="22" color="#fff" />
|
||||
@@ -48,135 +54,156 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据统计 -->
|
||||
<wd-card custom-class="stats-card">
|
||||
<wd-grid :column="3" border>
|
||||
<wd-grid-item @click="navigateToSection('wallet')">
|
||||
<view class="stats-item">
|
||||
<view class="mb-8rpx text-36rpx font-600">0.00</view>
|
||||
<view class="text-26rpx text-gray-500">我的余额</view>
|
||||
</view>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item @click="navigateToSection('favorites')">
|
||||
<view class="stats-item">
|
||||
<view class="mb-8rpx text-36rpx font-600">0</view>
|
||||
<view class="text-26rpx text-gray-500">我的收藏</view>
|
||||
</view>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item @click="navigateToSection('history')">
|
||||
<view class="stats-item">
|
||||
<view class="mb-8rpx text-36rpx font-600">0</view>
|
||||
<view class="text-26rpx text-gray-500">浏览历史</view>
|
||||
</view>
|
||||
</wd-grid-item>
|
||||
</wd-grid>
|
||||
</wd-card>
|
||||
|
||||
<!-- 常用工具 -->
|
||||
<wd-card>
|
||||
<template #header>
|
||||
<view class="flex-start">
|
||||
<wd-icon name="tools" size="18" :color="currentThemeColor" />
|
||||
<text class="ml-12rpx text-28rpx font-600">常用工具</text>
|
||||
<view class="section-card">
|
||||
<view class="section-header">
|
||||
<view class="section-title">
|
||||
<wd-icon name="user" size="18" :color="currentThemeColor" />
|
||||
<text class="title-text">资料卡片</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<wd-grid :column="4" border>
|
||||
<wd-grid-item @click="navigateToProfile">
|
||||
<view class="flex-col-center py-20rpx">
|
||||
<view class="tool-icon mb-12rpx">
|
||||
<wd-icon name="user" size="24" :color="currentThemeColor" />
|
||||
</view>
|
||||
<view class="text-24rpx">个人资料</view>
|
||||
</view>
|
||||
<view class="profile-grid">
|
||||
<view class="profile-tile">
|
||||
<view class="tile-icon" :style="{ backgroundColor: currentThemeColor + '15' }">
|
||||
<wd-icon name="secured" size="20" :color="currentThemeColor" />
|
||||
</view>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item @click="navigateToFAQ">
|
||||
<view class="flex-col-center py-20rpx">
|
||||
<view class="mb-12rpx">
|
||||
<wd-icon name="help-circle" size="24" :color="currentThemeColor" />
|
||||
</view>
|
||||
<view class="text-24rpx">常见问题</view>
|
||||
<view class="tile-content">
|
||||
<text class="tile-label">角色</text>
|
||||
<text class="tile-value">{{ roleText }}</text>
|
||||
</view>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item @click="handleQuestionFeedback">
|
||||
<view class="flex-col-center py-20rpx">
|
||||
<view class="mb-12rpx">
|
||||
<wd-icon name="check-circle" size="24" :color="currentThemeColor" />
|
||||
</view>
|
||||
<view class="text-24rpx">问题反馈</view>
|
||||
</view>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item @click="navigateToAbout">
|
||||
<view class="flex-col-center py-20rpx">
|
||||
<view class="mb-12rpx">
|
||||
<wd-icon name="info-circle" size="24" :color="currentThemeColor" />
|
||||
</view>
|
||||
<view class="text-24rpx">关于我们</view>
|
||||
</view>
|
||||
</wd-grid-item>
|
||||
</wd-grid>
|
||||
</wd-card>
|
||||
|
||||
<!-- 推荐服务 -->
|
||||
<wd-card>
|
||||
<template #header>
|
||||
<view class="flex-start">
|
||||
<wd-icon name="star" size="18" :color="currentThemeColor" />
|
||||
<text class="ml-12rpx text-28rpx font-600">推荐服务</text>
|
||||
</view>
|
||||
</template>
|
||||
<view class="profile-tile">
|
||||
<view class="tile-icon" :style="{ backgroundColor: currentThemeColor + '15' }">
|
||||
<wd-icon name="goods" size="20" :color="currentThemeColor" />
|
||||
</view>
|
||||
<view class="tile-content">
|
||||
<text class="tile-label">部门</text>
|
||||
<text class="tile-value">{{ deptText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="profile-tile">
|
||||
<view class="tile-icon" :style="{ backgroundColor: currentThemeColor + '15' }">
|
||||
<wd-icon name="phone" size="20" :color="currentThemeColor" />
|
||||
</view>
|
||||
<view class="tile-content">
|
||||
<text class="tile-label">手机</text>
|
||||
<text class="tile-value">{{ mobileText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="profile-tile">
|
||||
<view class="tile-icon" :style="{ backgroundColor: currentThemeColor + '15' }">
|
||||
<wd-icon name="mail" size="20" :color="currentThemeColor" />
|
||||
</view>
|
||||
<view class="tile-content">
|
||||
<text class="tile-label">邮箱</text>
|
||||
<text class="tile-value">{{ emailText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<wd-cell-group>
|
||||
<wd-cell
|
||||
title="会员中心"
|
||||
label="解锁更多特权"
|
||||
is-link
|
||||
custom-class="service-cell"
|
||||
@click="navigateToSection('services', 'vip')"
|
||||
>
|
||||
<template #icon>
|
||||
<view class="service-icon mr-20rpx">
|
||||
<wd-icon name="dong" size="22" :color="currentThemeColor" />
|
||||
</view>
|
||||
</template>
|
||||
</wd-cell>
|
||||
<view class="section-card">
|
||||
<view class="section-header">
|
||||
<view class="section-title">
|
||||
<wd-icon name="setting" size="18" :color="currentThemeColor" />
|
||||
<text class="title-text">快捷入口</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="quick-grid">
|
||||
<view class="quick-item" @click="navigateToProfile">
|
||||
<view class="quick-icon" :style="{ backgroundColor: currentThemeColor + '15' }">
|
||||
<wd-icon name="user" size="24" :color="currentThemeColor" />
|
||||
</view>
|
||||
<text class="quick-text">个人资料</text>
|
||||
</view>
|
||||
<view v-if="isLogin" class="quick-item" @click="navigateToAccount">
|
||||
<view class="quick-icon" :style="{ backgroundColor: currentThemeColor + '15' }">
|
||||
<wd-icon name="secured" size="24" :color="currentThemeColor" />
|
||||
</view>
|
||||
<text class="quick-text">账号安全</text>
|
||||
</view>
|
||||
<view class="quick-item" @click="navigateToTheme">
|
||||
<view class="quick-icon" :style="{ backgroundColor: currentThemeColor + '15' }">
|
||||
<wd-icon name="color" size="24" :color="currentThemeColor" />
|
||||
</view>
|
||||
<text class="quick-text">主题设置</text>
|
||||
</view>
|
||||
<view class="quick-item" @click="navigateToSettings">
|
||||
<view class="quick-icon" :style="{ backgroundColor: currentThemeColor + '15' }">
|
||||
<wd-icon name="setting" size="24" :color="currentThemeColor" />
|
||||
</view>
|
||||
<text class="quick-text">更多设置</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<wd-cell
|
||||
title="优惠券"
|
||||
label="查看我的优惠券"
|
||||
is-link
|
||||
custom-class="service-cell"
|
||||
@click="navigateToSection('services', 'coupon')"
|
||||
>
|
||||
<template #icon>
|
||||
<view class="service-icon mr-20rpx">
|
||||
<wd-icon name="discount" size="22" :color="currentThemeColor" />
|
||||
</view>
|
||||
</template>
|
||||
</wd-cell>
|
||||
<view class="section-card">
|
||||
<view class="section-header">
|
||||
<view class="section-title">
|
||||
<wd-icon name="setting" size="18" :color="currentThemeColor" />
|
||||
<text class="title-text">系统设置</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="menu-list">
|
||||
<view class="menu-item" @click="navigateToUserAgreement">
|
||||
<wd-icon name="note" size="20" color="#666" />
|
||||
<text class="menu-text">用户协议</text>
|
||||
<wd-icon name="arrow-right" size="16" color="#ccc" />
|
||||
</view>
|
||||
<view class="menu-item" @click="navigateToAbout">
|
||||
<wd-icon name="info-circle" size="20" color="#666" />
|
||||
<text class="menu-text">关于我们</text>
|
||||
<wd-icon name="arrow-right" size="16" color="#ccc" />
|
||||
</view>
|
||||
<view class="menu-item" @click="navigateToNetworkTest">
|
||||
<wd-icon name="wifi" size="20" color="#666" />
|
||||
<text class="menu-text">网络测试</text>
|
||||
<wd-icon name="arrow-right" size="16" color="#ccc" />
|
||||
</view>
|
||||
<view class="menu-item" @click="handleClearCache">
|
||||
<wd-icon name="delete" size="20" color="#666" />
|
||||
<text class="menu-text">清空缓存</text>
|
||||
<text class="menu-value">{{ cacheSize }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<wd-cell
|
||||
title="邀请有礼"
|
||||
label="邀请好友得奖励"
|
||||
is-link
|
||||
custom-class="service-cell"
|
||||
@click="navigateToSection('services', 'invite')"
|
||||
>
|
||||
<template #icon>
|
||||
<view class="service-icon mr-20rpx">
|
||||
<wd-icon name="share" size="22" :color="currentThemeColor" />
|
||||
</view>
|
||||
</template>
|
||||
</wd-cell>
|
||||
</wd-cell-group>
|
||||
</wd-card>
|
||||
<view class="section-card">
|
||||
<view class="section-header">
|
||||
<view class="section-title">
|
||||
<wd-icon name="help-circle" size="18" :color="currentThemeColor" />
|
||||
<text class="title-text">帮助与支持</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="menu-list">
|
||||
<view class="menu-item" @click="navigateToFAQ">
|
||||
<wd-icon name="question-circle" size="20" color="#666" />
|
||||
<text class="menu-text">常见问题</text>
|
||||
<wd-icon name="arrow-right" size="16" color="#ccc" />
|
||||
</view>
|
||||
<view class="menu-item" @click="handleQuestionFeedback">
|
||||
<wd-icon name="edit" size="20" color="#666" />
|
||||
<text class="menu-text">问题反馈</text>
|
||||
<wd-icon name="arrow-right" size="16" color="#ccc" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 退出登录按钮 -->
|
||||
<view v-if="isLogin" class="flex-center mt-20rpx">
|
||||
<wd-button custom-class="logout-button" plain @click="handleLogout">退出登录</wd-button>
|
||||
<view v-if="isLogin" class="logout-section">
|
||||
<view class="logout-btn" @click="handleLogout">
|
||||
<text class="logout-text">退出登录</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<wd-toast />
|
||||
|
||||
<wd-loading
|
||||
v-if="clearing"
|
||||
v-model="clearing"
|
||||
text="正在清理..."
|
||||
mask
|
||||
custom-class="loading-center"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -189,6 +216,7 @@
|
||||
</route>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useToast } from "wot-design-uni";
|
||||
import { useUserStore, useThemeStore } from "@/store";
|
||||
import { useRouter } from "uni-mini-router";
|
||||
@@ -207,6 +235,74 @@ const router = useRouter();
|
||||
// 使用导航栏 Hook(TabBar 页面)
|
||||
const navbar = useNavbar({ hasTabbar: true });
|
||||
|
||||
const navContentHeight = computed(() => {
|
||||
const height = navbar.totalHeight.value - navbar.statusBarHeight.value;
|
||||
return `${height > 0 ? height : 0}px`;
|
||||
});
|
||||
|
||||
const actionButtonsTop = computed(() => {
|
||||
const navHeight = navbar.totalHeight.value - navbar.statusBarHeight.value;
|
||||
return `${navbar.statusBarHeight.value + navHeight / 2}px`;
|
||||
});
|
||||
|
||||
const roleText = computed(() => {
|
||||
if (!userInfo.value) return "-";
|
||||
return userInfo.value.roleName || userInfo.value.roles?.join("、") || "-";
|
||||
});
|
||||
|
||||
const deptText = computed(() => userInfo.value?.deptName || "-");
|
||||
const mobileText = computed(() => userInfo.value?.mobile || "-");
|
||||
const emailText = computed(() => userInfo.value?.email || "-");
|
||||
|
||||
const genderValue = computed(() => (userInfo.value as any)?.gender);
|
||||
const genderLabel = computed(() => {
|
||||
if (genderValue.value === 1) return "♂";
|
||||
if (genderValue.value === 2) return "♀";
|
||||
return "";
|
||||
});
|
||||
const genderClass = computed(() => {
|
||||
if (genderValue.value === 1) return "gender-badge--male";
|
||||
if (genderValue.value === 2) return "gender-badge--female";
|
||||
return "";
|
||||
});
|
||||
|
||||
const clearing = ref(false);
|
||||
const cacheSize = ref<any>("-");
|
||||
|
||||
const formatSize = (size: number) => {
|
||||
if (size < 1024) {
|
||||
return size + "B";
|
||||
} else if (size < 1024 * 1024) {
|
||||
return (size / 1024).toFixed(2) + "KB";
|
||||
} else {
|
||||
return (size / 1024 / 1024).toFixed(2) + "MB";
|
||||
}
|
||||
};
|
||||
|
||||
const getCacheSize = async () => {
|
||||
try {
|
||||
// #ifdef MP-WEIXIN
|
||||
const res = await uni.getStorageInfo();
|
||||
cacheSize.value = formatSize(res.currentSize);
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
cacheSize.value = formatSize(
|
||||
Object.keys(localStorage).reduce((size, key) => size + localStorage[key].length, 0)
|
||||
);
|
||||
// #endif
|
||||
if (!cacheSize.value) {
|
||||
cacheSize.value = "0B";
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取缓存大小失败:", error);
|
||||
cacheSize.value = "-";
|
||||
}
|
||||
};
|
||||
|
||||
onLoad(() => {
|
||||
getCacheSize();
|
||||
});
|
||||
|
||||
// 登录
|
||||
const navigateToLoginPage = () => {
|
||||
const pages = getCurrentPages();
|
||||
@@ -253,11 +349,47 @@ const navigateToSettings = () => {
|
||||
router.push({ path: "/pages/mine/settings/index" });
|
||||
};
|
||||
|
||||
const navigateToAccount = () => {
|
||||
if (!isLogin.value) {
|
||||
navigateToLoginPage();
|
||||
return;
|
||||
}
|
||||
router.push({ path: "/pages/mine/settings/account/index" });
|
||||
};
|
||||
|
||||
const navigateToTheme = () => {
|
||||
router.push({ path: "/pages/mine/settings/theme/index" });
|
||||
};
|
||||
|
||||
const navigateToUserAgreement = () => {
|
||||
router.push({ path: "/pages/mine/settings/agreement/index" });
|
||||
};
|
||||
|
||||
const navigateToNetworkTest = () => {
|
||||
router.push({ path: "/pages/mine/settings/network/index" });
|
||||
};
|
||||
|
||||
// 问题反馈
|
||||
const handleQuestionFeedback = () => {
|
||||
router.push({ path: "/pages/mine/feedback/index" });
|
||||
};
|
||||
|
||||
const handleClearCache = async () => {
|
||||
if (clearing.value) return;
|
||||
|
||||
try {
|
||||
clearing.value = true;
|
||||
await new Promise((resolve) => setTimeout(resolve, 800));
|
||||
await uni.clearStorage();
|
||||
await getCacheSize();
|
||||
toast.show("清理成功");
|
||||
} catch {
|
||||
toast.show("清理失败");
|
||||
} finally {
|
||||
clearing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 导航到各个板块
|
||||
const navigateToSection = (section: string, subSection?: string) => {
|
||||
console.log(`导航到: ${section}${subSection ? ` - ${subSection}` : ""}`);
|
||||
@@ -270,6 +402,11 @@ const navigateToSection = (section: string, subSection?: string) => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
// 用户信息卡片
|
||||
.user-profile {
|
||||
position: relative;
|
||||
@@ -290,34 +427,60 @@ const navigateToSection = (section: string, subSection?: string) => {
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 30rpx;
|
||||
min-height: v-bind(navContentHeight);
|
||||
padding: 32rpx 32rpx 40rpx;
|
||||
padding-right: 200rpx;
|
||||
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
|
||||
.avatar {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.8);
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.9);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
.user-details {
|
||||
flex: 1;
|
||||
margin-left: 24rpx;
|
||||
margin-left: 28rpx;
|
||||
|
||||
.nickname {
|
||||
margin-bottom: 8rpx;
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
|
||||
.gender-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 36rpx;
|
||||
height: 36rpx;
|
||||
padding: 0 12rpx;
|
||||
margin-left: 12rpx;
|
||||
font-size: 22rpx;
|
||||
font-weight: 700;
|
||||
line-height: 36rpx;
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0.25);
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.gender-badge--male {
|
||||
background-color: rgba(64, 158, 255, 0.5);
|
||||
}
|
||||
|
||||
.gender-badge--female {
|
||||
background-color: rgba(255, 99, 132, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.user-id {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
|
||||
.login-prompt {
|
||||
@@ -329,18 +492,21 @@ const navigateToSection = (section: string, subSection?: string) => {
|
||||
|
||||
// 操作按钮区域
|
||||
.action-buttons {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
margin-left: auto;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
background-color: rgba(255, 255, 255, 0.25);
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
background-color: rgba(255, 255, 255, 0.28);
|
||||
backdrop-filter: blur(8px);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@@ -363,37 +529,198 @@ const navigateToSection = (section: string, subSection?: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.stats-card) {
|
||||
margin: 20rpx 30rpx !important;
|
||||
// 通用卡片样式
|
||||
.section-card {
|
||||
padding: 28rpx;
|
||||
margin: 24rpx 28rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
// 服务图标
|
||||
.service-icon {
|
||||
.section-header {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
// 资料卡片网格
|
||||
.profile-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.profile-tile {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
background: #f9fafb;
|
||||
border-radius: 14rpx;
|
||||
transition: background 0.2s;
|
||||
|
||||
&:active {
|
||||
background: #f3f4f6;
|
||||
}
|
||||
}
|
||||
|
||||
.tile-icon {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin-right: 16rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.tile-content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tile-label {
|
||||
display: block;
|
||||
margin-bottom: 6rpx;
|
||||
overflow: hidden;
|
||||
font-size: 22rpx;
|
||||
color: #9ca3af;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tile-value {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// 快捷入口网格
|
||||
.quick-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.quick-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 8rpx;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.quick-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
background-color: var(--wot-color-bg-light);
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
margin-bottom: 12rpx;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.quick-text {
|
||||
font-size: 24rpx;
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
// 菜单列表
|
||||
.menu-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rpx;
|
||||
overflow: hidden;
|
||||
background: #f9fafb;
|
||||
border-radius: 14rpx;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 28rpx 24rpx;
|
||||
background: #fff;
|
||||
transition: background 0.2s;
|
||||
|
||||
&:active {
|
||||
background: #f9fafb;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1rpx solid #f3f4f6;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-text {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
.menu-value {
|
||||
font-size: 26rpx;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
.logout-section {
|
||||
padding: 40rpx 28rpx 80rpx;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 88rpx;
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.logout-text {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
// 加载遮罩
|
||||
:deep(.loading-center) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
// 登录按钮样式
|
||||
:deep(.btn-login) {
|
||||
font-size: 24rpx !important;
|
||||
border-radius: 20rpx !important;
|
||||
}
|
||||
|
||||
// 退出登录按钮样式
|
||||
:deep(.logout-button) {
|
||||
width: 80% !important;
|
||||
height: 80rpx !important;
|
||||
font-size: 32rpx !important;
|
||||
font-weight: bold !important;
|
||||
border-radius: 40rpx !important;
|
||||
|
||||
&:active {
|
||||
opacity: 0.8 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
374
src/types/uni-components.d.ts
vendored
374
src/types/uni-components.d.ts
vendored
@@ -8,65 +8,59 @@
|
||||
// 扩展 uni-app 原生组件属性类型
|
||||
declare module "@vue/runtime-core" {
|
||||
export interface GlobalComponents {
|
||||
view: new () => {
|
||||
$props: {
|
||||
class?: string
|
||||
style?: string | Record<string, any>
|
||||
hoverClass?: string
|
||||
hoverStartTime?: number
|
||||
hoverStayTime?: number
|
||||
hoverStopPropagation?: boolean
|
||||
onClick?: (event: any) => void
|
||||
}
|
||||
}
|
||||
text: new () => {
|
||||
$props: {
|
||||
class?: string
|
||||
style?: string | Record<string, any>
|
||||
selectable?: boolean
|
||||
userSelect?: boolean
|
||||
space?: "ensp" | "emsp" | "nbsp"
|
||||
decode?: boolean
|
||||
onClick?: (event: any) => void
|
||||
}
|
||||
}
|
||||
image: new () => {
|
||||
$props: {
|
||||
class?: string
|
||||
style?: string | Record<string, any>
|
||||
src?: string
|
||||
mode?:
|
||||
| "scaleToFill"
|
||||
| "aspectFit"
|
||||
| "aspectFill"
|
||||
| "widthFix"
|
||||
| "heightFix"
|
||||
| "top"
|
||||
| "bottom"
|
||||
| "center"
|
||||
| "left"
|
||||
| "right"
|
||||
| "top left"
|
||||
| "top right"
|
||||
| "bottom left"
|
||||
| "bottom right"
|
||||
lazyLoad?: boolean
|
||||
fadeShow?: boolean
|
||||
webp?: boolean
|
||||
showMenuByLongpress?: boolean
|
||||
onClick?: (event: any) => void
|
||||
}
|
||||
}
|
||||
view: import("vue").DefineComponent<{
|
||||
class?: string;
|
||||
style?: string | Record<string, any>;
|
||||
hoverClass?: string;
|
||||
hoverStartTime?: number;
|
||||
hoverStayTime?: number;
|
||||
hoverStopPropagation?: boolean;
|
||||
onClick?: (event: any) => void;
|
||||
}>;
|
||||
text: import("vue").DefineComponent<{
|
||||
class?: string;
|
||||
style?: string | Record<string, any>;
|
||||
selectable?: boolean;
|
||||
userSelect?: boolean;
|
||||
space?: "ensp" | "emsp" | "nbsp";
|
||||
decode?: boolean;
|
||||
onClick?: (event: any) => void;
|
||||
}>;
|
||||
image: import("vue").DefineComponent<{
|
||||
class?: string;
|
||||
style?: string | Record<string, any>;
|
||||
src?: string;
|
||||
mode?:
|
||||
| "scaleToFill"
|
||||
| "aspectFit"
|
||||
| "aspectFill"
|
||||
| "widthFix"
|
||||
| "heightFix"
|
||||
| "top"
|
||||
| "bottom"
|
||||
| "center"
|
||||
| "left"
|
||||
| "right"
|
||||
| "top left"
|
||||
| "top right"
|
||||
| "bottom left"
|
||||
| "bottom right";
|
||||
lazyLoad?: boolean;
|
||||
fadeShow?: boolean;
|
||||
webp?: boolean;
|
||||
showMenuByLongpress?: boolean;
|
||||
onClick?: (event: any) => void;
|
||||
}>;
|
||||
button: new () => {
|
||||
$props: {
|
||||
class?: string
|
||||
style?: string | Record<string, any>
|
||||
size?: "default" | "mini"
|
||||
type?: "primary" | "default" | "warn"
|
||||
plain?: boolean
|
||||
disabled?: boolean
|
||||
loading?: boolean
|
||||
formType?: "submit" | "reset"
|
||||
class?: string;
|
||||
style?: string | Record<string, any>;
|
||||
size?: "default" | "mini";
|
||||
type?: "primary" | "default" | "warn";
|
||||
plain?: boolean;
|
||||
disabled?: boolean;
|
||||
loading?: boolean;
|
||||
formType?: "submit" | "reset";
|
||||
openType?:
|
||||
| "feedback"
|
||||
| "share"
|
||||
@@ -78,149 +72,149 @@ declare module "@vue/runtime-core" {
|
||||
| "getAuthorize"
|
||||
| "contactShare"
|
||||
| "livestream"
|
||||
| "getRealnameAuthInfo"
|
||||
hoverClass?: string
|
||||
hoverStartTime?: number
|
||||
hoverStayTime?: number
|
||||
lang?: "en" | "zh_CN" | "zh_TW"
|
||||
sessionFrom?: string
|
||||
sendMessageTitle?: string
|
||||
sendMessagePath?: string
|
||||
sendMessageImg?: string
|
||||
showMessageCard?: boolean
|
||||
appParameter?: string
|
||||
onClick?: (event: any) => void
|
||||
onGetphonenumber?: (event: any) => void
|
||||
onGetuserinfo?: (event: any) => void
|
||||
onContact?: (event: any) => void
|
||||
onError?: (event: any) => void
|
||||
onOpensetting?: (event: any) => void
|
||||
onLaunchapp?: (event: any) => void
|
||||
}
|
||||
}
|
||||
| "getRealnameAuthInfo";
|
||||
hoverClass?: string;
|
||||
hoverStartTime?: number;
|
||||
hoverStayTime?: number;
|
||||
lang?: "en" | "zh_CN" | "zh_TW";
|
||||
sessionFrom?: string;
|
||||
sendMessageTitle?: string;
|
||||
sendMessagePath?: string;
|
||||
sendMessageImg?: string;
|
||||
showMessageCard?: boolean;
|
||||
appParameter?: string;
|
||||
onClick?: (event: any) => void;
|
||||
onGetphonenumber?: (event: any) => void;
|
||||
onGetuserinfo?: (event: any) => void;
|
||||
onContact?: (event: any) => void;
|
||||
onError?: (event: any) => void;
|
||||
onOpensetting?: (event: any) => void;
|
||||
onLaunchapp?: (event: any) => void;
|
||||
};
|
||||
};
|
||||
input: new () => {
|
||||
$props: {
|
||||
class?: string
|
||||
style?: string | Record<string, any>
|
||||
value?: string
|
||||
type?: "text" | "number" | "idcard" | "digit" | "safe-password" | "nickname"
|
||||
password?: boolean
|
||||
placeholder?: string
|
||||
placeholderStyle?: string
|
||||
placeholderClass?: string
|
||||
disabled?: boolean
|
||||
maxlength?: number | string
|
||||
cursorSpacing?: number
|
||||
autoFocus?: boolean
|
||||
focus?: boolean
|
||||
cursor?: number
|
||||
selectionStart?: number
|
||||
selectionEnd?: number
|
||||
adjustPosition?: boolean
|
||||
holdKeyboard?: boolean
|
||||
alwaysEmbed?: boolean
|
||||
confirmType?: "send" | "search" | "next" | "go" | "done"
|
||||
confirmHold?: boolean
|
||||
onInput?: (event: any) => void
|
||||
onFocus?: (event: any) => void
|
||||
onBlur?: (event: any) => void
|
||||
onConfirm?: (event: any) => void
|
||||
}
|
||||
}
|
||||
class?: string;
|
||||
style?: string | Record<string, any>;
|
||||
value?: string;
|
||||
type?: "text" | "number" | "idcard" | "digit" | "safe-password" | "nickname";
|
||||
password?: boolean;
|
||||
placeholder?: string;
|
||||
placeholderStyle?: string;
|
||||
placeholderClass?: string;
|
||||
disabled?: boolean;
|
||||
maxlength?: number | string;
|
||||
cursorSpacing?: number;
|
||||
autoFocus?: boolean;
|
||||
focus?: boolean;
|
||||
cursor?: number;
|
||||
selectionStart?: number;
|
||||
selectionEnd?: number;
|
||||
adjustPosition?: boolean;
|
||||
holdKeyboard?: boolean;
|
||||
alwaysEmbed?: boolean;
|
||||
confirmType?: "send" | "search" | "next" | "go" | "done";
|
||||
confirmHold?: boolean;
|
||||
onInput?: (event: any) => void;
|
||||
onFocus?: (event: any) => void;
|
||||
onBlur?: (event: any) => void;
|
||||
onConfirm?: (event: any) => void;
|
||||
};
|
||||
};
|
||||
textarea: new () => {
|
||||
$props: {
|
||||
class?: string
|
||||
style?: string | Record<string, any>
|
||||
value?: string
|
||||
placeholder?: string
|
||||
placeholderStyle?: string
|
||||
placeholderClass?: string
|
||||
disabled?: boolean
|
||||
maxlength?: number | string
|
||||
autoFocus?: boolean
|
||||
focus?: boolean
|
||||
autoHeight?: boolean
|
||||
fixed?: boolean
|
||||
cursorSpacing?: number
|
||||
cursor?: number
|
||||
showConfirmBar?: boolean
|
||||
selectionStart?: number
|
||||
selectionEnd?: number
|
||||
adjustPosition?: boolean
|
||||
holdKeyboard?: boolean
|
||||
disableDefaultPadding?: boolean
|
||||
confirmType?: "send" | "search" | "next" | "go" | "done"
|
||||
confirmHold?: boolean
|
||||
onInput?: (event: any) => void
|
||||
onFocus?: (event: any) => void
|
||||
onBlur?: (event: any) => void
|
||||
onConfirm?: (event: any) => void
|
||||
onLinechange?: (event: any) => void
|
||||
}
|
||||
}
|
||||
class?: string;
|
||||
style?: string | Record<string, any>;
|
||||
value?: string;
|
||||
placeholder?: string;
|
||||
placeholderStyle?: string;
|
||||
placeholderClass?: string;
|
||||
disabled?: boolean;
|
||||
maxlength?: number | string;
|
||||
autoFocus?: boolean;
|
||||
focus?: boolean;
|
||||
autoHeight?: boolean;
|
||||
fixed?: boolean;
|
||||
cursorSpacing?: number;
|
||||
cursor?: number;
|
||||
showConfirmBar?: boolean;
|
||||
selectionStart?: number;
|
||||
selectionEnd?: number;
|
||||
adjustPosition?: boolean;
|
||||
holdKeyboard?: boolean;
|
||||
disableDefaultPadding?: boolean;
|
||||
confirmType?: "send" | "search" | "next" | "go" | "done";
|
||||
confirmHold?: boolean;
|
||||
onInput?: (event: any) => void;
|
||||
onFocus?: (event: any) => void;
|
||||
onBlur?: (event: any) => void;
|
||||
onConfirm?: (event: any) => void;
|
||||
onLinechange?: (event: any) => void;
|
||||
};
|
||||
};
|
||||
scrollview: new () => {
|
||||
$props: {
|
||||
class?: string
|
||||
style?: string | Record<string, any>
|
||||
scrollX?: boolean
|
||||
scrollY?: boolean
|
||||
upperThreshold?: number
|
||||
lowerThreshold?: number
|
||||
scrollTop?: number | string
|
||||
scrollLeft?: number | string
|
||||
scrollIntoView?: string
|
||||
scrollWithAnimation?: boolean
|
||||
enableBackToTop?: boolean
|
||||
enableFlex?: boolean
|
||||
scrollAnchors?: boolean
|
||||
refresherEnabled?: boolean
|
||||
refresherThreshold?: number
|
||||
refresherDefaultStyle?: "black" | "white" | "none"
|
||||
refresherBackground?: string
|
||||
refresherTriggered?: boolean
|
||||
enhanced?: boolean
|
||||
bounces?: boolean
|
||||
showScrollbar?: boolean
|
||||
pagingEnabled?: boolean
|
||||
fastDeceleration?: boolean
|
||||
onScrolltoupper?: (event: any) => void
|
||||
onScrolltolower?: (event: any) => void
|
||||
onScroll?: (event: any) => void
|
||||
onRefresherrefresh?: (event: any) => void
|
||||
onRefresherrestore?: (event: any) => void
|
||||
onRefresherabort?: (event: any) => void
|
||||
}
|
||||
}
|
||||
class?: string;
|
||||
style?: string | Record<string, any>;
|
||||
scrollX?: boolean;
|
||||
scrollY?: boolean;
|
||||
upperThreshold?: number;
|
||||
lowerThreshold?: number;
|
||||
scrollTop?: number | string;
|
||||
scrollLeft?: number | string;
|
||||
scrollIntoView?: string;
|
||||
scrollWithAnimation?: boolean;
|
||||
enableBackToTop?: boolean;
|
||||
enableFlex?: boolean;
|
||||
scrollAnchors?: boolean;
|
||||
refresherEnabled?: boolean;
|
||||
refresherThreshold?: number;
|
||||
refresherDefaultStyle?: "black" | "white" | "none";
|
||||
refresherBackground?: string;
|
||||
refresherTriggered?: boolean;
|
||||
enhanced?: boolean;
|
||||
bounces?: boolean;
|
||||
showScrollbar?: boolean;
|
||||
pagingEnabled?: boolean;
|
||||
fastDeceleration?: boolean;
|
||||
onScrolltoupper?: (event: any) => void;
|
||||
onScrolltolower?: (event: any) => void;
|
||||
onScroll?: (event: any) => void;
|
||||
onRefresherrefresh?: (event: any) => void;
|
||||
onRefresherrestore?: (event: any) => void;
|
||||
onRefresherabort?: (event: any) => void;
|
||||
};
|
||||
};
|
||||
swiper: new () => {
|
||||
$props: {
|
||||
class?: string
|
||||
style?: string | Record<string, any>
|
||||
indicatorDots?: boolean
|
||||
indicatorColor?: string
|
||||
indicatorActiveColor?: string
|
||||
autoplay?: boolean
|
||||
current?: number
|
||||
interval?: number
|
||||
duration?: number
|
||||
circular?: boolean
|
||||
vertical?: boolean
|
||||
previousMargin?: string
|
||||
nextMargin?: string
|
||||
displayMultipleItems?: number
|
||||
skipHiddenItemLayout?: boolean
|
||||
easingFunction?: "default" | "linear" | "easeInCubic" | "easeOutCubic" | "easeInOutCubic"
|
||||
onChange?: (event: any) => void
|
||||
onTransition?: (event: any) => void
|
||||
onAnimationfinish?: (event: any) => void
|
||||
}
|
||||
}
|
||||
class?: string;
|
||||
style?: string | Record<string, any>;
|
||||
indicatorDots?: boolean;
|
||||
indicatorColor?: string;
|
||||
indicatorActiveColor?: string;
|
||||
autoplay?: boolean;
|
||||
current?: number;
|
||||
interval?: number;
|
||||
duration?: number;
|
||||
circular?: boolean;
|
||||
vertical?: boolean;
|
||||
previousMargin?: string;
|
||||
nextMargin?: string;
|
||||
displayMultipleItems?: number;
|
||||
skipHiddenItemLayout?: boolean;
|
||||
easingFunction?: "default" | "linear" | "easeInCubic" | "easeOutCubic" | "easeInOutCubic";
|
||||
onChange?: (event: any) => void;
|
||||
onTransition?: (event: any) => void;
|
||||
onAnimationfinish?: (event: any) => void;
|
||||
};
|
||||
};
|
||||
swiperitem: new () => {
|
||||
$props: {
|
||||
class?: string
|
||||
style?: string | Record<string, any>
|
||||
}
|
||||
}
|
||||
class?: string;
|
||||
style?: string | Record<string, any>;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {}
|
||||
export {};
|
||||
|
||||
Reference in New Issue
Block a user