feat: 添加有来技术公众号页面及相关功能优化
This commit is contained in:
@@ -158,7 +158,7 @@ const AuthAPI = {
|
||||
logout(): Promise<any> {
|
||||
return request<any>({
|
||||
url: `${AUTH_BASE_URL}/logout`,
|
||||
method: "POST",
|
||||
method: "DELETE",
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"type": "page",
|
||||
"name": "login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "登录"
|
||||
"navigationStyle": "custom",
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -54,6 +54,14 @@
|
||||
"requireAuth": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/official/index",
|
||||
"type": "page",
|
||||
"name": "official",
|
||||
"style": {
|
||||
"navigationBarTitleText": "有来技术"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/profile/complete-profile",
|
||||
"type": "page"
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
<template>
|
||||
<view class="home-page">
|
||||
<custom-navbar title="首页" fixed placeholder :showBack="false">
|
||||
<template #right>
|
||||
<wd-search
|
||||
v-model="searchValue"
|
||||
class="navbar__search"
|
||||
hide-cancel
|
||||
disabled
|
||||
@click="handleSearch"
|
||||
/>
|
||||
</template>
|
||||
</custom-navbar>
|
||||
|
||||
<!-- 轮播图 -->
|
||||
<wd-swiper
|
||||
v-model:current="current"
|
||||
custom-class="swiper-box"
|
||||
:list="swiperList"
|
||||
autoplay
|
||||
@click="handleSwiperClick"
|
||||
@change="handleSwiperChange"
|
||||
/>
|
||||
<view class="hero">
|
||||
<wd-swiper
|
||||
v-model:current="current"
|
||||
custom-class="swiper-box"
|
||||
:list="swiperList"
|
||||
autoplay
|
||||
@click="handleSwiperClick"
|
||||
@change="handleSwiperChange"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 快捷导航 -->
|
||||
<view class="section">
|
||||
<view class="section section--overlay">
|
||||
<wd-grid clickable :column="4">
|
||||
<wd-grid-item
|
||||
v-for="(item, index) in navList"
|
||||
@@ -118,9 +108,10 @@
|
||||
* - 支持暗黑模式(通过 CSS 变量)
|
||||
*/
|
||||
|
||||
import { reactive, ref } from "vue";
|
||||
import { onReady } from "@dcloudio/uni-app";
|
||||
import { dayjs } from "wot-design-uni";
|
||||
import { useRouter } from "uni-mini-router";
|
||||
import CustomNavbar from "@/components/custom-navbar/index.vue";
|
||||
|
||||
// ============================================================================
|
||||
// 类型定义
|
||||
@@ -154,7 +145,6 @@ const router = useRouter();
|
||||
// ============================================================================
|
||||
|
||||
const current = ref(0);
|
||||
const searchValue = ref("");
|
||||
const recentDaysRange = ref(7);
|
||||
|
||||
const swiperList = ref(["https://www.youlai.tech/storage/blog/banner9.png"]);
|
||||
@@ -268,10 +258,6 @@ function loadVisitTrendData() {
|
||||
// 事件处理
|
||||
// ============================================================================
|
||||
|
||||
function handleSearch() {
|
||||
uni.showToast({ title: "搜索功能开发中", icon: "none" });
|
||||
}
|
||||
|
||||
function handleNavClick(item: NavItem) {
|
||||
router.push({ path: item.url });
|
||||
}
|
||||
@@ -317,6 +303,39 @@ onReady(() => {
|
||||
background-color: var(--color-bg-secondary);
|
||||
}
|
||||
|
||||
.hero {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hero::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 120rpx;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
rgba(245, 247, 250, 0) 0%,
|
||||
rgba(245, 247, 250, 0.85) 60%,
|
||||
rgba(245, 247, 250, 1) 100%
|
||||
);
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
:deep(.swiper-box) {
|
||||
height: 420rpx;
|
||||
overflow: hidden;
|
||||
border-bottom-left-radius: 32rpx;
|
||||
border-bottom-right-radius: 32rpx;
|
||||
}
|
||||
|
||||
:deep(.swiper-box .wd-swiper__item),
|
||||
:deep(.swiper-box image) {
|
||||
height: 420rpx;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 导航栏
|
||||
// ============================================================================
|
||||
@@ -369,6 +388,16 @@ onReady(() => {
|
||||
margin: 24rpx;
|
||||
}
|
||||
|
||||
.section--overlay {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
margin-top: -72rpx;
|
||||
padding: 16rpx 8rpx;
|
||||
background: var(--color-bg);
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 16rpx 36rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 快捷导航项
|
||||
// ============================================================================
|
||||
|
||||
@@ -106,7 +106,12 @@
|
||||
</view>
|
||||
|
||||
<!-- 登录按钮 -->
|
||||
<button class="btn-primary" :disabled="loading" @click="handleLogin">
|
||||
<button
|
||||
class="btn-primary"
|
||||
:class="{ 'btn-primary--loading': loading }"
|
||||
:disabled="loading"
|
||||
@click="handleLogin"
|
||||
>
|
||||
{{ loading ? "登录中..." : "登 录" }}
|
||||
</button>
|
||||
|
||||
@@ -866,6 +871,7 @@ const handleBack = () => {
|
||||
|
||||
// 主按钮
|
||||
.btn-primary {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -878,14 +884,44 @@ const handleBack = () => {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 15px -3px rgba(59, 130, 246, 0.3);
|
||||
transition: all 0.2s;
|
||||
overflow: hidden;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
box-shadow: none;
|
||||
opacity: 0.5;
|
||||
opacity: 0.9;
|
||||
box-shadow: 0 8px 14px -6px rgba(59, 130, 246, 0.22);
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-primary--loading {
|
||||
opacity: 0.92;
|
||||
}
|
||||
|
||||
.btn-primary--loading::before {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
content: "";
|
||||
background: linear-gradient(
|
||||
110deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.16) 30%,
|
||||
rgba(255, 255, 255, 0) 60%
|
||||
);
|
||||
transform: translateX(-100%);
|
||||
animation: btnShimmer 1.1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes btnShimmer {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<view class="page-container dark:text-[var(--wot-color-text)]">
|
||||
<custom-navbar
|
||||
title="我的主页"
|
||||
bg-color="transparent"
|
||||
@@ -20,16 +20,25 @@
|
||||
:src="isLogin ? userInfo!.avatar : defaultAvatar"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view v-if="genderIconName" class="gender-icon" :class="genderIconClass">
|
||||
<wd-icon :name="genderIconName" size="12" color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="user-details">
|
||||
<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>
|
||||
<view class="user-meta">
|
||||
<view class="meta-row">
|
||||
<wd-icon name="user" size="14" color="rgba(255, 255, 255, 0.92)" />
|
||||
<text class="meta-value">{{ userInfo?.username || "0000000" }}</text>
|
||||
</view>
|
||||
<view v-if="deptNameText" class="meta-row">
|
||||
<wd-icon name="home" size="14" color="rgba(255, 255, 255, 0.92)" />
|
||||
<text class="meta-value">{{ deptNameText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view class="login-prompt">立即登录获取更多功能</view>
|
||||
@@ -45,55 +54,12 @@
|
||||
</view>
|
||||
|
||||
<view class="header-actions">
|
||||
<view class="action-btn relative" @click="navigateToNotifications">
|
||||
<wd-icon name="notification" size="20" color="#fff" />
|
||||
<view v-if="true" class="action-badge">2</view>
|
||||
</view>
|
||||
<view class="action-btn" @click="navigateToSettings">
|
||||
<wd-icon name="setting" size="22" color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="isLogin" 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>
|
||||
</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>
|
||||
<view class="tile-content">
|
||||
<text class="tile-label">角色</text>
|
||||
<text class="tile-value">{{ roleText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<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>
|
||||
<wd-icon name="setting" size="20" color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -102,31 +68,21 @@
|
||||
<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>
|
||||
<wd-icon name="user" 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>
|
||||
<view class="menu-item" @click="navigateToProfile">
|
||||
<wd-icon name="user" 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>
|
||||
<view class="menu-item" @click="navigateToAccount">
|
||||
<wd-icon name="secured" 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>
|
||||
|
||||
@@ -138,11 +94,6 @@
|
||||
</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>
|
||||
@@ -151,22 +102,20 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 退出登录按钮 -->
|
||||
<view v-if="isLogin" class="logout-section">
|
||||
<view class="logout-btn" @click="handleLogout">
|
||||
<text class="logout-text">退出登录</text>
|
||||
<view class="section-card official-section">
|
||||
<view class="official-card" @click="navigateToOfficialAccount">
|
||||
<image class="official-avatar" src="/static/logo.png" mode="aspectFill" />
|
||||
<view class="official-body">
|
||||
<view class="official-title">有来技术</view>
|
||||
<view class="official-desc">技术干货 · 开源社区 · 交流群</view>
|
||||
</view>
|
||||
<view class="official-action">
|
||||
<wd-icon name="arrow-right" size="18" color="#9ca3af" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<wd-toast />
|
||||
|
||||
<wd-loading
|
||||
v-if="clearing"
|
||||
v-model="clearing"
|
||||
text="正在清理..."
|
||||
mask
|
||||
custom-class="loading-center"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -180,12 +129,10 @@
|
||||
|
||||
<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";
|
||||
import { useNavbar } from "@/composables/useNavbar";
|
||||
|
||||
const toast = useToast();
|
||||
const userStore = useUserStore();
|
||||
const themeStore = useThemeStore();
|
||||
const currentThemeColor = computed(() => themeStore.themeVars.colorTheme);
|
||||
@@ -205,64 +152,33 @@ const router = useRouter();
|
||||
// 使用导航栏 Hook(TabBar 页面)
|
||||
const navbar = useNavbar({ hasTabbar: true });
|
||||
|
||||
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 normalizedGender = computed(() => {
|
||||
const v = genderValue.value;
|
||||
const n = typeof v === "number" ? v : Number(v);
|
||||
return Number.isFinite(n) ? n : 0;
|
||||
});
|
||||
const genderClass = computed(() => {
|
||||
if (genderValue.value === 1) return "gender-badge--male";
|
||||
if (genderValue.value === 2) return "gender-badge--female";
|
||||
|
||||
const deptNameText = computed(() => {
|
||||
if (!isLogin.value) return "";
|
||||
return (userInfo.value as any)?.deptName || "";
|
||||
});
|
||||
|
||||
const genderIconName = computed(() => {
|
||||
if (!isLogin.value) return "";
|
||||
if (normalizedGender.value === 1) return "gender-male";
|
||||
if (normalizedGender.value === 2) return "gender-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 genderIconClass = computed(() => {
|
||||
if (normalizedGender.value === 1) return "gender-icon--male";
|
||||
if (normalizedGender.value === 2) return "gender-icon--female";
|
||||
return "";
|
||||
});
|
||||
|
||||
onLoad(() => {});
|
||||
|
||||
// 登录
|
||||
const navigateToLoginPage = () => {
|
||||
const pages = getCurrentPages();
|
||||
@@ -271,20 +187,6 @@ const navigateToLoginPage = () => {
|
||||
router.push({ path: "/pages/login/index", query: { redirect: currentPagePath } });
|
||||
};
|
||||
|
||||
// 退出登录
|
||||
const handleLogout = () => {
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "确认退出登录吗?",
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
userStore.logout();
|
||||
toast.show("已退出登录");
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 个人信息
|
||||
const navigateToProfile = () => {
|
||||
if (!isLogin.value) {
|
||||
@@ -294,14 +196,20 @@ const navigateToProfile = () => {
|
||||
router.push({ path: "/pages/mine/profile/index" });
|
||||
};
|
||||
|
||||
// 常见问题
|
||||
const navigateToFAQ = () => {
|
||||
router.push({ path: "/pages/mine/faq/index" });
|
||||
// 账号和安全
|
||||
const navigateToAccount = () => {
|
||||
if (!isLogin.value) {
|
||||
navigateToLoginPage();
|
||||
return;
|
||||
}
|
||||
router.push({ path: "/pages/mine/settings/account/index" });
|
||||
};
|
||||
|
||||
// 关于我们
|
||||
const navigateToAbout = () => {
|
||||
router.push({ path: "/pages/mine/about/index" });
|
||||
const navigateToNotifications = () => {
|
||||
uni.showToast({
|
||||
title: "功能开发中",
|
||||
icon: "none",
|
||||
});
|
||||
};
|
||||
|
||||
// 设置
|
||||
@@ -309,40 +217,19 @@ const navigateToSettings = () => {
|
||||
router.push({ path: "/pages/mine/settings/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 navigateToOfficialAccount = () => {
|
||||
router.push({ path: "/pages/mine/official/index" });
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
// page-container 使用全局样式,支持暗黑模式
|
||||
|
||||
// 用户信息卡片
|
||||
.user-profile {
|
||||
@@ -355,7 +242,7 @@ const handleClearCache = async () => {
|
||||
right: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
height: 380rpx;
|
||||
height: 460rpx;
|
||||
border-bottom-right-radius: 48rpx;
|
||||
border-bottom-left-radius: 48rpx;
|
||||
}
|
||||
@@ -365,19 +252,41 @@ const handleClearCache = async () => {
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 32rpx 32rpx 40rpx;
|
||||
padding: 48rpx 32rpx 56rpx;
|
||||
padding-right: 140rpx;
|
||||
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
|
||||
.avatar {
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
width: 144rpx;
|
||||
height: 144rpx;
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.9);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.gender-icon {
|
||||
position: absolute;
|
||||
right: 8rpx;
|
||||
bottom: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
border: 2rpx solid rgba(255, 255, 255, 0.9);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
|
||||
.gender-icon--male {
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.gender-icon--female {
|
||||
background-color: #ff6384;
|
||||
}
|
||||
}
|
||||
|
||||
.user-details {
|
||||
@@ -386,40 +295,33 @@ const handleClearCache = async () => {
|
||||
|
||||
.nickname {
|
||||
margin-bottom: 10rpx;
|
||||
font-size: 36rpx;
|
||||
font-size: 40rpx;
|
||||
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;
|
||||
.user-meta {
|
||||
margin-top: 4rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6rpx;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
|
||||
.meta-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.meta-value {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.login-prompt {
|
||||
margin-bottom: 16rpx;
|
||||
font-size: 28rpx;
|
||||
@@ -432,6 +334,7 @@ const handleClearCache = async () => {
|
||||
top: 50%;
|
||||
right: 32rpx;
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
@@ -439,8 +342,8 @@ const handleClearCache = async () => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
background-color: rgba(255, 255, 255, 0.28);
|
||||
backdrop-filter: blur(8px);
|
||||
border-radius: 50%;
|
||||
@@ -494,62 +397,6 @@ const handleClearCache = async () => {
|
||||
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;
|
||||
}
|
||||
|
||||
// 菜单列表
|
||||
.menu-list {
|
||||
display: flex;
|
||||
@@ -588,6 +435,54 @@ const handleClearCache = async () => {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.official-section {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.official-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 32rpx 28rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.official-avatar {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 24rpx;
|
||||
}
|
||||
|
||||
.official-body {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
margin-left: 28rpx;
|
||||
}
|
||||
|
||||
.official-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.official-desc {
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
color: #9ca3af;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
|
||||
.official-action {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
background: #f3f4f6;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
.logout-section {
|
||||
padding: 40rpx 28rpx 80rpx;
|
||||
|
||||
108
src/pages/mine/official/index.vue
Normal file
108
src/pages/mine/official/index.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<view class="page-container dark:text-[var(--wot-color-text)]">
|
||||
<view class="page-content">
|
||||
<view class="header">
|
||||
<image class="logo" src="/static/logo.png" mode="aspectFill" />
|
||||
<view class="header-info">
|
||||
<view class="title">有来技术</view>
|
||||
<view class="sub-title">关注公众号获取更多技术干货</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="qr-card">
|
||||
<image
|
||||
class="qr-image"
|
||||
src="/static/images/qrcode-official.png"
|
||||
mode="widthFix"
|
||||
show-menu-by-longpress
|
||||
/>
|
||||
<view class="qr-tip">长按识别二维码关注公众号</view>
|
||||
|
||||
<view class="group-tip">
|
||||
如需加入技术交流群,请添加微信 haoxianrui 并备注「前端/后端/全栈」,邀您入群。
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<route lang="json">
|
||||
{
|
||||
"name": "official",
|
||||
"style": {
|
||||
"navigationBarTitleText": "有来技术"
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<script lang="ts" setup></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-content {
|
||||
padding: 28rpx;
|
||||
padding-bottom: calc(28rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
padding: 28rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.header-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
margin-top: 8rpx;
|
||||
font-size: 26rpx;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.group-tip {
|
||||
margin-top: 20rpx;
|
||||
padding: 20rpx;
|
||||
font-size: 26rpx;
|
||||
line-height: 1.6;
|
||||
color: #374151;
|
||||
background: #f9fafb;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.qr-card {
|
||||
margin-top: 24rpx;
|
||||
padding: 28rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.qr-image {
|
||||
width: 100%;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.qr-tip {
|
||||
margin-top: 20rpx;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: #6b7280;
|
||||
}
|
||||
</style>
|
||||
@@ -1,14 +1,6 @@
|
||||
<template>
|
||||
<view class="page-container dark:text-[var(--wot-color-text)]">
|
||||
<wd-cell-group>
|
||||
<wd-cell v-if="isLogin" title="个人资料" icon="user" is-link @click="navigateToProfile" />
|
||||
<wd-cell
|
||||
v-if="isLogin"
|
||||
title="账号和安全"
|
||||
icon="secured"
|
||||
is-link
|
||||
@click="navigateToAccount"
|
||||
/>
|
||||
<wd-cell title="主题设置" icon="setting1" is-link @click="navigateToTheme" />
|
||||
<wd-cell title="用户协议" icon="user" is-link @click="navigateToUserAgreement" />
|
||||
<wd-cell title="关于我们" icon="info-circle" is-link @click="navigateToAbout" />
|
||||
@@ -42,30 +34,11 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useUserStore } from "@/store";
|
||||
import { checkLogin } from "@/utils/auth";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
|
||||
const userStore = useUserStore();
|
||||
const isLogin = computed(() => !!userStore.userInfo);
|
||||
|
||||
// 个人资料
|
||||
const navigateToProfile = () => {
|
||||
if (checkLogin()) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/mine/profile/index",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 账号和安全
|
||||
const navigateToAccount = () => {
|
||||
if (checkLogin()) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/mine/settings/account/index",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 主题设置
|
||||
const navigateToTheme = () => {
|
||||
uni.navigateTo({
|
||||
|
||||
1
src/types/uni-pages.d.ts
vendored
1
src/types/uni-pages.d.ts
vendored
@@ -11,6 +11,7 @@ interface NavigateToOptions {
|
||||
"/pages/mine/about/index" |
|
||||
"/pages/mine/faq/index" |
|
||||
"/pages/mine/feedback/index" |
|
||||
"/pages/mine/official/index" |
|
||||
"/pages/mine/profile/complete-profile" |
|
||||
"/pages/mine/profile/index" |
|
||||
"/pages/mine/settings/index" |
|
||||
|
||||
Reference in New Issue
Block a user