fix: 🐛 修复小程序显示问题
This commit is contained in:
@@ -25,12 +25,8 @@
|
||||
"keyframes-name-pattern": null,
|
||||
"no-descending-specificity": null,
|
||||
"no-empty-source": null,
|
||||
"unit-no-unknown": [
|
||||
true,
|
||||
{
|
||||
"ignoreUnits": ["rpx"]
|
||||
}
|
||||
],
|
||||
"declaration-property-value-no-unknown": null,
|
||||
"unit-no-unknown": null,
|
||||
"selector-type-no-unknown": [
|
||||
true,
|
||||
{
|
||||
|
||||
11
src/App.vue
11
src/App.vue
@@ -21,13 +21,24 @@ onHide(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* H5 环境样式变量设置 */
|
||||
:root {
|
||||
--primary-color: #165dff;
|
||||
--primary-color-light: #94bfff;
|
||||
--primary-color-dark: #0e3c9b;
|
||||
}
|
||||
|
||||
/* 小程序环境样式变量设置 */
|
||||
page {
|
||||
--primary-color: #165dff;
|
||||
--primary-color-light: #94bfff;
|
||||
--primary-color-dark: #0e3c9b;
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
/* 动态加载小程序主题色的钩子 */
|
||||
/* 用于通过小程序原生API获取主题色并应用 */
|
||||
.theme-container {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
"quickapp": {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin": {
|
||||
"appid": "",
|
||||
"appid": "wx99a151dc43d2637b",
|
||||
"setting": {
|
||||
"urlCheck": false
|
||||
},
|
||||
|
||||
@@ -1,487 +0,0 @@
|
||||
<template>
|
||||
<view class="complete-profile-container">
|
||||
<!-- 顶部导航栏 -->
|
||||
<view class="nav-bar">
|
||||
<wd-icon name="arrow-left" size="20" color="#fff" @click="goBack" />
|
||||
<text class="nav-title">完善个人信息</text>
|
||||
<view style="width: 20px"></view>
|
||||
</view>
|
||||
|
||||
<!-- 蓝色区域内容 -->
|
||||
<view class="top-content">
|
||||
<view class="title">完善个人信息</view>
|
||||
<view class="subtitle">完善您的个人信息以获得更好的使用体验</view>
|
||||
</view>
|
||||
|
||||
<!-- 白色区域 -->
|
||||
<view class="bottom-content">
|
||||
<!-- 头像上传 -->
|
||||
<view class="avatar-section">
|
||||
<view class="avatar-wrapper" @click="chooseAvatar">
|
||||
<image v-if="userForm.avatar" :src="userForm.avatar" class="avatar" />
|
||||
<view v-else class="avatar-placeholder">
|
||||
<wd-icon name="fill-camera" size="28" color="#999" />
|
||||
</view>
|
||||
<view class="avatar-upload">
|
||||
<wd-icon name="camera" size="16" color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="avatar-tip">点击更换头像</view>
|
||||
</view>
|
||||
|
||||
<!-- 表单部分 -->
|
||||
<view class="form-section">
|
||||
<wd-form ref="formRef" :model="userForm">
|
||||
<!-- 昵称输入框 -->
|
||||
<view class="input-wrap">
|
||||
<text class="input-label">昵称</text>
|
||||
<input
|
||||
v-model="userForm.nickname"
|
||||
class="form-input"
|
||||
placeholder="请输入您的昵称"
|
||||
placeholder-style="color: #999; font-weight: normal;"
|
||||
/>
|
||||
<wd-icon
|
||||
v-if="userForm.nickname"
|
||||
name="close-fill"
|
||||
size="18"
|
||||
color="#999"
|
||||
class="clear-icon"
|
||||
@click="userForm.nickname = ''"
|
||||
/>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<!-- 性别选择 -->
|
||||
<view class="gender-wrap">
|
||||
<text class="input-label">性别</text>
|
||||
<view class="gender-options">
|
||||
<view
|
||||
class="gender-option"
|
||||
:class="userForm.gender === 1 ? 'gender-selected' : ''"
|
||||
@click="userForm.gender = 1"
|
||||
>
|
||||
<text>男</text>
|
||||
</view>
|
||||
<view
|
||||
class="gender-option"
|
||||
:class="userForm.gender === 2 ? 'gender-selected' : ''"
|
||||
@click="userForm.gender = 2"
|
||||
>
|
||||
<text>女</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="button-wrap">
|
||||
<button
|
||||
class="submit-button"
|
||||
:disabled="submitting"
|
||||
:style="submitting ? 'opacity: 0.7;' : ''"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
提交
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- 微信获取信息按钮 -->
|
||||
<view v-if="isWechatEnv" class="button-wrap mt-20">
|
||||
<button
|
||||
class="wechat-button"
|
||||
:disabled="wxAuthing"
|
||||
:style="wxAuthing ? 'opacity: 0.7;' : ''"
|
||||
@click="handleGetWechatInfo"
|
||||
>
|
||||
<image src="/static/icons/weixin.png" class="wechat-icon" />
|
||||
<text>一键获取微信头像昵称</text>
|
||||
</button>
|
||||
</view>
|
||||
</wd-form>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 头像裁剪 -->
|
||||
<wd-img-cropper v-model="avatarShow" :img-src="originalSrc" @confirm="handleAvatarConfirm" />
|
||||
|
||||
<!-- 弹窗 -->
|
||||
<wd-toast />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useToast } from "wot-design-uni";
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
import FileAPI, { type FileInfo } from "@/api/file";
|
||||
import UserAPI, { type UserProfileForm } from "@/api/system/user";
|
||||
import { ref } from "vue";
|
||||
|
||||
const toast = useToast();
|
||||
const formRef = ref();
|
||||
const userStore = useUserStore();
|
||||
const submitting = ref(false);
|
||||
const wxAuthing = ref(false);
|
||||
const avatarShow = ref(false);
|
||||
const originalSrc = ref("");
|
||||
const redirectPath = ref("/pages/index/index");
|
||||
|
||||
// 用户表单数据
|
||||
const userForm = ref<UserProfileForm>({
|
||||
nickname: "",
|
||||
gender: 1,
|
||||
avatar: "",
|
||||
});
|
||||
|
||||
// 判断是否微信环境
|
||||
const isWechatEnv = ref(false);
|
||||
|
||||
// 获取参数
|
||||
onLoad((options) => {
|
||||
// 读取用户信息
|
||||
if (userStore.userInfo) {
|
||||
userForm.value.nickname = userStore.userInfo.nickname || "";
|
||||
userForm.value.gender = userStore.userInfo.gender || 1;
|
||||
userForm.value.avatar = userStore.userInfo.avatar || "";
|
||||
}
|
||||
|
||||
// 保存跳转路径
|
||||
if (options.redirect) {
|
||||
redirectPath.value = decodeURIComponent(options.redirect);
|
||||
}
|
||||
|
||||
// 检测环境
|
||||
// #ifdef MP-WEIXIN
|
||||
isWechatEnv.value = true;
|
||||
// #endif
|
||||
});
|
||||
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
// 选择头像
|
||||
const chooseAvatar = () => {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
originalSrc.value = res.tempFilePaths[0];
|
||||
avatarShow.value = true;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 头像裁剪完成
|
||||
const handleAvatarConfirm = (event: any) => {
|
||||
const { tempFilePath } = event;
|
||||
// 显示上传中
|
||||
uni.showLoading({ title: "上传中..." });
|
||||
|
||||
// 上传头像
|
||||
FileAPI.upload(tempFilePath)
|
||||
.then((fileInfo: FileInfo) => {
|
||||
userForm.value.avatar = fileInfo.url;
|
||||
uni.hideLoading();
|
||||
})
|
||||
.catch(() => {
|
||||
uni.hideLoading();
|
||||
toast.error("头像上传失败,请重试");
|
||||
});
|
||||
};
|
||||
|
||||
// 一键获取微信信息
|
||||
const handleGetWechatInfo = () => {
|
||||
wxAuthing.value = true;
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// @ts-ignore
|
||||
uni.getUserProfile({
|
||||
desc: "用于完善用户资料",
|
||||
success: (res) => {
|
||||
const { userInfo } = res;
|
||||
// 填充表单
|
||||
userForm.value.nickname = userInfo.nickName;
|
||||
userForm.value.gender = userInfo.gender;
|
||||
|
||||
// 如果有头像,下载并上传头像
|
||||
if (userInfo.avatarUrl) {
|
||||
uni.showLoading({ title: "获取头像中..." });
|
||||
|
||||
// 下载微信头像
|
||||
uni.downloadFile({
|
||||
url: userInfo.avatarUrl,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
// 上传到服务器
|
||||
FileAPI.upload(res.tempFilePath)
|
||||
.then((fileInfo: FileInfo) => {
|
||||
userForm.value.avatar = fileInfo.url;
|
||||
uni.hideLoading();
|
||||
})
|
||||
.catch(() => {
|
||||
uni.hideLoading();
|
||||
toast.error("头像上传失败");
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
uni.hideLoading();
|
||||
toast.error("获取微信头像失败");
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
toast.error("获取微信信息失败,请手动填写");
|
||||
},
|
||||
complete: () => {
|
||||
wxAuthing.value = false;
|
||||
},
|
||||
});
|
||||
// #endif
|
||||
|
||||
// 非微信环境
|
||||
// #ifndef MP-WEIXIN
|
||||
toast.error("当前环境不支持获取微信信息");
|
||||
wxAuthing.value = false;
|
||||
// #endif
|
||||
};
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = () => {
|
||||
if (submitting.value) return;
|
||||
|
||||
// 简单验证
|
||||
if (!userForm.value.nickname.trim()) {
|
||||
toast.error("请填写昵称");
|
||||
return;
|
||||
}
|
||||
|
||||
submitting.value = true;
|
||||
|
||||
// 更新用户信息
|
||||
UserAPI.updateProfile(userForm.value)
|
||||
.then(async () => {
|
||||
// 更新本地存储的用户信息
|
||||
await userStore.getInfo();
|
||||
toast.success("信息已更新");
|
||||
|
||||
// 延迟跳转
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({
|
||||
url: redirectPath.value,
|
||||
});
|
||||
}, 1500);
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("更新失败,请重试");
|
||||
})
|
||||
.finally(() => {
|
||||
submitting.value = false;
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.complete-profile-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background-color: #0063ff;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx;
|
||||
padding-top: calc(30rpx + var(--status-bar-height, 0px));
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.top-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 0 60rpx;
|
||||
}
|
||||
|
||||
.top-content .title {
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.top-content .subtitle {
|
||||
padding: 0 60rpx;
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.bottom-content {
|
||||
flex: 1;
|
||||
padding: 40rpx 30rpx;
|
||||
overflow-y: auto;
|
||||
background-color: #fff;
|
||||
border-radius: 30rpx 30rpx 0 0;
|
||||
}
|
||||
|
||||
.avatar-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.avatar-section .avatar-wrapper {
|
||||
position: relative;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.avatar-section .avatar-wrapper .avatar {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.avatar-section .avatar-wrapper .avatar-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.avatar-section .avatar-wrapper .avatar-upload {
|
||||
position: absolute;
|
||||
right: 5rpx;
|
||||
bottom: 5rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: #4080ff;
|
||||
border: 2rpx solid #fff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.avatar-section .avatar-tip {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.form-section .input-wrap {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.form-section .input-wrap .input-label {
|
||||
width: 100rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-section .input-wrap .form-input {
|
||||
flex: 1;
|
||||
height: 60rpx;
|
||||
font-size: 28rpx;
|
||||
line-height: 60rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-section .input-wrap .clear-icon {
|
||||
padding: 10rpx;
|
||||
}
|
||||
|
||||
.form-section .gender-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.form-section .gender-wrap .input-label {
|
||||
width: 100rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-section .gender-wrap .gender-options {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
gap: 20rpx;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.form-section .gender-wrap .gender-options .gender-option {
|
||||
padding: 10rpx 30rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.form-section .gender-wrap .gender-options .gender-option.gender-selected {
|
||||
color: #fff;
|
||||
background-color: #4080ff;
|
||||
}
|
||||
|
||||
.form-section .divider {
|
||||
height: 1px;
|
||||
margin: 0 0 10rpx 0;
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
.form-section .button-wrap {
|
||||
margin-top: 60rpx;
|
||||
}
|
||||
|
||||
.form-section .button-wrap .submit-button {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
line-height: 90rpx;
|
||||
color: #fff;
|
||||
background-color: #4080ff;
|
||||
border: none;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
|
||||
.form-section .button-wrap .wechat-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 30rpx;
|
||||
color: #fff;
|
||||
background-color: #07c160;
|
||||
border: none;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
|
||||
.form-section .button-wrap .wechat-button .wechat-icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.mt-20 {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -35,11 +35,17 @@
|
||||
<input
|
||||
v-model="loginFormData.password"
|
||||
class="form-input"
|
||||
type="password"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
placeholder="请输入密码"
|
||||
placeholder-style="color: #9ca3af; font-weight: normal;"
|
||||
/>
|
||||
<wd-icon name="eye-close" size="18" color="#9ca3af" class="eye-icon" />
|
||||
<wd-icon
|
||||
:name="showPassword ? 'eye-open' : 'eye-close'"
|
||||
size="18"
|
||||
color="#9ca3af"
|
||||
class="eye-icon"
|
||||
@click="showPassword = !showPassword"
|
||||
/>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
@@ -94,6 +100,7 @@ const loginFormRef = ref();
|
||||
const toast = useToast();
|
||||
const loading = ref(false);
|
||||
const userStore = useUserStore();
|
||||
const showPassword = ref(false);
|
||||
|
||||
// 登录表单数据
|
||||
const loginFormData = ref<LoginFormData>({
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
:src="isLogin ? userInfo!.avatar : defaultAvatar"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view v-if="isLogin" class="avatar-edit">
|
||||
<wd-icon name="edit-pen" size="16" color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="user-details">
|
||||
<block v-if="isLogin">
|
||||
@@ -21,7 +18,12 @@
|
||||
</block>
|
||||
<block v-else>
|
||||
<view class="login-prompt">立即登录获取更多功能</view>
|
||||
<wd-button class="login-btn" size="small" type="primary" @click="navigateToLoginPage">
|
||||
<wd-button
|
||||
custom-class="btn-login"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="navigateToLoginPage"
|
||||
>
|
||||
登录/注册
|
||||
</wd-button>
|
||||
</block>
|
||||
@@ -31,7 +33,7 @@
|
||||
<wd-icon name="setting1" size="22" color="#333" />
|
||||
</view>
|
||||
<view v-if="isLogin" class="action-btn" @click="navigateToSection('messages')">
|
||||
<wd-icon name="message" size="22" color="#333" />
|
||||
<wd-icon name="notification" size="22" color="#333" />
|
||||
<view v-if="true" class="badge">2</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -56,53 +58,6 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 我的订单 -->
|
||||
<view class="card-container">
|
||||
<view class="card-header">
|
||||
<view class="card-title">
|
||||
<wd-icon name="cart" size="18" :color="themeStore.primaryColor" />
|
||||
<text>我的订单</text>
|
||||
</view>
|
||||
<view class="card-action" @click="navigateToSection('orders')">
|
||||
<text>全部订单</text>
|
||||
<wd-icon name="arrow-right" size="14" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-status">
|
||||
<view class="status-item" @click="navigateToSection('orders', 'pending')">
|
||||
<view class="status-icon">
|
||||
<wd-icon name="wallet-pay" size="28" :color="themeStore.primaryColor" />
|
||||
<view v-if="true" class="status-badge">2</view>
|
||||
</view>
|
||||
<view class="status-label">待付款</view>
|
||||
</view>
|
||||
<view class="status-item" @click="navigateToSection('orders', 'shipping')">
|
||||
<view class="status-icon">
|
||||
<wd-icon name="shopping" size="28" :color="themeStore.primaryColor" />
|
||||
</view>
|
||||
<view class="status-label">待发货</view>
|
||||
</view>
|
||||
<view class="status-item" @click="navigateToSection('orders', 'receiving')">
|
||||
<view class="status-icon">
|
||||
<wd-icon name="car" size="28" :color="themeStore.primaryColor" />
|
||||
</view>
|
||||
<view class="status-label">待收货</view>
|
||||
</view>
|
||||
<view class="status-item" @click="navigateToSection('orders', 'comment')">
|
||||
<view class="status-icon">
|
||||
<wd-icon name="comment-o" size="28" :color="themeStore.primaryColor" />
|
||||
</view>
|
||||
<view class="status-label">待评价</view>
|
||||
</view>
|
||||
<view class="status-item" @click="navigateToSection('orders', 'after-sale')">
|
||||
<view class="status-icon">
|
||||
<wd-icon name="service" size="28" :color="themeStore.primaryColor" />
|
||||
</view>
|
||||
<view class="status-label">售后</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 常用工具 -->
|
||||
<view class="card-container">
|
||||
<view class="card-header">
|
||||
@@ -114,22 +69,11 @@
|
||||
<view class="tools-grid">
|
||||
<view class="tool-item" @click="navigateToProfile">
|
||||
<view class="tool-icon">
|
||||
<wd-icon name="person" size="24" :color="themeStore.primaryColor" />
|
||||
<wd-icon name="user" size="24" :color="themeStore.primaryColor" />
|
||||
</view>
|
||||
<view class="tool-label">个人资料</view>
|
||||
</view>
|
||||
<view class="tool-item" @click="navigateToSection('address')">
|
||||
<view class="tool-icon">
|
||||
<wd-icon name="location" size="24" :color="themeStore.primaryColor" />
|
||||
</view>
|
||||
<view class="tool-label">收货地址</view>
|
||||
</view>
|
||||
<view class="tool-item" @click="navigateToSection('todos')">
|
||||
<view class="tool-icon">
|
||||
<wd-icon name="task" size="24" :color="themeStore.primaryColor" />
|
||||
</view>
|
||||
<view class="tool-label">待办事项</view>
|
||||
</view>
|
||||
|
||||
<view class="tool-item" @click="navigateToFAQ">
|
||||
<view class="tool-icon">
|
||||
<wd-icon name="help-circle" size="24" :color="themeStore.primaryColor" />
|
||||
@@ -148,18 +92,6 @@
|
||||
</view>
|
||||
<view class="tool-label">关于我们</view>
|
||||
</view>
|
||||
<view class="tool-item" @click="navigateToSettings">
|
||||
<view class="tool-icon">
|
||||
<wd-icon name="setting1" size="24" :color="themeStore.primaryColor" />
|
||||
</view>
|
||||
<view class="tool-label">设置</view>
|
||||
</view>
|
||||
<view class="tool-item" @click="navigateToSection('wallet')">
|
||||
<view class="tool-icon">
|
||||
<wd-icon name="wallet" size="24" :color="themeStore.primaryColor" />
|
||||
</view>
|
||||
<view class="tool-label">我的钱包</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -174,8 +106,8 @@
|
||||
<view class="services-list">
|
||||
<view class="service-item" @click="navigateToSection('services', 'vip')">
|
||||
<view class="service-left">
|
||||
<view class="service-icon vip-icon">
|
||||
<wd-icon name="crown" size="22" color="#FFD700" />
|
||||
<view class="service-icon">
|
||||
<wd-icon name="dong" size="22" :color="themeStore.primaryColor" />
|
||||
</view>
|
||||
<view class="service-info">
|
||||
<view class="service-name">会员中心</view>
|
||||
@@ -187,7 +119,7 @@
|
||||
<view class="service-item" @click="navigateToSection('services', 'coupon')">
|
||||
<view class="service-left">
|
||||
<view class="service-icon">
|
||||
<wd-icon name="ticket" size="22" :color="themeStore.primaryColor" />
|
||||
<wd-icon name="discount" size="22" :color="themeStore.primaryColor" />
|
||||
</view>
|
||||
<view class="service-info">
|
||||
<view class="service-name">优惠券</view>
|
||||
@@ -212,7 +144,7 @@
|
||||
</view>
|
||||
|
||||
<view v-if="isLogin" class="logout-btn-container">
|
||||
<wd-button class="logout-btn" @click="handleLogout">退出登录</wd-button>
|
||||
<wd-button custom-class="logout-btn-unocss" @click="handleLogout">退出登录</wd-button>
|
||||
</view>
|
||||
|
||||
<wd-toast />
|
||||
@@ -314,6 +246,7 @@ const navigateToSection = (section: string, subSection?: string) => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* stylelint-disable declaration-property-value-no-unknown */
|
||||
.mine-container {
|
||||
min-height: 100vh;
|
||||
padding-bottom: 100rpx;
|
||||
@@ -352,20 +285,6 @@ const navigateToSection = (section: string, subSection?: string) => {
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.avatar-edit {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
background-color: var(--primary-color);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.user-details {
|
||||
@@ -389,16 +308,6 @@ const navigateToSection = (section: string, subSection?: string) => {
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
font-size: 26rpx;
|
||||
color: var(--primary-color);
|
||||
background-color: #fff;
|
||||
border: none;
|
||||
border-radius: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
@@ -617,10 +526,6 @@ const navigateToSection = (section: string, subSection?: string) => {
|
||||
height: 70rpx;
|
||||
background-color: rgba(var(--primary-color-rgb), 0.08);
|
||||
border-radius: 16rpx;
|
||||
|
||||
&.vip-icon {
|
||||
background: linear-gradient(135deg, #ffd700, #ffa500);
|
||||
}
|
||||
}
|
||||
|
||||
.service-info {
|
||||
@@ -645,19 +550,33 @@ const navigateToSection = (section: string, subSection?: string) => {
|
||||
// 退出登录按钮
|
||||
.logout-btn-container {
|
||||
margin: 60rpx 30rpx;
|
||||
|
||||
.logout-btn {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
background-color: #f5f5f5;
|
||||
border: none;
|
||||
border-radius: 40rpx;
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
/* 使用全局样式解决微信小程序组件样式问题 */
|
||||
.logout-btn-unocss {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
width: 100% !important;
|
||||
height: 80rpx !important;
|
||||
font-size: 32rpx !important;
|
||||
font-weight: bold !important;
|
||||
color: #fff !important;
|
||||
background-color: var(--primary-color) !important;
|
||||
border: 2rpx solid var(--primary-color) !important;
|
||||
border-radius: 40rpx !important;
|
||||
box-shadow: 0 4rpx 12rpx rgba(var(--primary-color-rgb), 0.3) !important;
|
||||
}
|
||||
|
||||
.btn-login {
|
||||
width: 160rpx !important;
|
||||
height: 60rpx !important;
|
||||
font-size: 26rpx !important;
|
||||
color: var(--primary-color) !important;
|
||||
background-color: #fff !important;
|
||||
border: none !important;
|
||||
border-radius: 30rpx !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<template>
|
||||
<view class="settings-container">
|
||||
<wd-cell-group>
|
||||
<wd-cell title="个人资料" icon="user" is-link @click="navigateToProfile" />
|
||||
<wd-cell title="账号和安全" icon="secured" is-link @click="navigateToAccount" />
|
||||
<wd-cell title="主题设置" icon="brush" is-link @click="navigateToTheme" />
|
||||
<wd-cell title="主题设置" icon="setting1" is-link @click="navigateToTheme" />
|
||||
<wd-cell title="用户协议" icon="user" is-link @click="navigateToUserAgreement" />
|
||||
<wd-cell title="隐私政策" icon="folder" is-link @click="navigateToPrivacy" />
|
||||
<wd-cell title="关于我们" icon="info" is-link @click="navigateToAbout" />
|
||||
</wd-cell-group>
|
||||
|
||||
<wd-cell-group custom-style="margin-top:40rpx">
|
||||
@@ -18,9 +20,9 @@
|
||||
/>
|
||||
</wd-cell-group>
|
||||
|
||||
<wd-cell-group v-if="isLogin" custom-style="margin-top:40rpx">
|
||||
<wd-cell title="退出" icon="logout" is-link @click="handleLogout" />
|
||||
</wd-cell-group>
|
||||
<view v-if="isLogin" class="logout-section">
|
||||
<wd-button class="logout-btn" @click="handleLogout">退出登录</wd-button>
|
||||
</view>
|
||||
|
||||
<!-- 全屏 loading -->
|
||||
<view v-if="clearing" class="loading-mask">
|
||||
@@ -35,28 +37,57 @@
|
||||
<script lang="ts" setup>
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
import { checkLogin } from "@/utils/auth";
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const isLogin = computed(() => !!userStore.userInfo);
|
||||
|
||||
// 个人资料
|
||||
const navigateToProfile = () => {
|
||||
if (checkLogin()) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/mine/profile/index",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 账号和安全
|
||||
const navigateToAccount = () => {
|
||||
uni.navigateTo({ url: "/pages/mine/settings/account/index" });
|
||||
if (checkLogin()) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/mine/settings/account/index",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 主题设置
|
||||
const navigateToTheme = () => {
|
||||
uni.navigateTo({
|
||||
url: "/pages/mine/settings/theme/index",
|
||||
});
|
||||
};
|
||||
|
||||
// 用户协议
|
||||
const navigateToUserAgreement = () => {
|
||||
uni.navigateTo({ url: "/pages/mine/settings/agreement/index" });
|
||||
uni.navigateTo({
|
||||
url: "/pages/mine/agreements/user-agreement",
|
||||
});
|
||||
};
|
||||
|
||||
// 隐私政策
|
||||
const navigateToPrivacy = () => {
|
||||
uni.navigateTo({ url: "/pages/mine/settings/privacy/index" });
|
||||
uni.navigateTo({
|
||||
url: "/pages/mine/agreements/privacy-policy",
|
||||
});
|
||||
};
|
||||
// 主题设置
|
||||
const navigateToTheme = () => {
|
||||
uni.navigateTo({ url: "/pages/mine/settings/theme/index" });
|
||||
|
||||
// 关于我们
|
||||
const navigateToAbout = () => {
|
||||
uni.navigateTo({
|
||||
url: "/pages/mine/about/index",
|
||||
});
|
||||
};
|
||||
|
||||
// 网络测试
|
||||
const navigateToNetworkTest = () => {
|
||||
uni.navigateTo({ url: "/pages/mine/settings/network/index" });
|
||||
@@ -145,10 +176,18 @@ const handleClearCache = async () => {
|
||||
|
||||
// 退出登录
|
||||
const handleLogout = () => {
|
||||
userStore.logout().then(() => {
|
||||
uni.showToast({ title: "已退出登录", icon: "success" });
|
||||
// 跳转到登录页
|
||||
uni.reLaunch({ url: "/pages/mine/index" });
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "确定要退出登录吗?",
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
userStore.logout();
|
||||
uni.showToast({
|
||||
title: "已退出登录",
|
||||
icon: "success",
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -161,6 +200,7 @@ onLoad(() => {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.settings-container {
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
|
||||
.loading-mask {
|
||||
@@ -199,5 +239,33 @@ onLoad(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logout-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 20rpx;
|
||||
margin-top: 60rpx;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
background-color: var(--primary-color);
|
||||
border: none;
|
||||
border-radius: 45rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(var(--primary-color-rgb), 0.3);
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&:active {
|
||||
opacity: 0.85;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -54,8 +54,9 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import { useThemeStore } from "@/store";
|
||||
import { applyThemeOnPageShow } from "@/utils/theme";
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
@@ -138,6 +139,22 @@ onLoad(() => {
|
||||
// 初始化自定义颜色输入框
|
||||
customColor.value = themeStore.primaryColor;
|
||||
});
|
||||
|
||||
// 页面显示时重新应用主题(解决小程序环境问题)
|
||||
onShow(() => {
|
||||
// 在小程序环境中,页面显示时重新应用主题
|
||||
if (typeof document === "undefined") {
|
||||
applyThemeOnPageShow(themeStore.primaryColor);
|
||||
|
||||
// 为了确保样式应用,我们可以在页面中设置内联样式
|
||||
// 这样可以绕过小程序的CSS变量限制
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1];
|
||||
if (currentPage) {
|
||||
console.log("当前页面重新应用主题色");
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -245,30 +262,30 @@ onLoad(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.preview-button {
|
||||
width: 200rpx;
|
||||
height: 80rpx;
|
||||
font-size: 28rpx;
|
||||
line-height: 80rpx;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
.preview-button {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.preview-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
.preview-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.preview-border {
|
||||
width: 200rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
border: 2px solid;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
.preview-border {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
background-color: #f5f5f5;
|
||||
border: 2px solid;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -276,10 +293,9 @@ onLoad(() => {
|
||||
.reset-btn {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
margin-bottom: 30rpx;
|
||||
font-size: 28rpx;
|
||||
line-height: 80rpx;
|
||||
color: #666;
|
||||
color: #333;
|
||||
background-color: #f5f5f5;
|
||||
border: none;
|
||||
border-radius: 8rpx;
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
placeholder="请输入关键字"
|
||||
/>
|
||||
<view class="flex-between py-2">
|
||||
<wd-button custom-class="w-20per" type="info" @click="handleResetQuery">重置</wd-button>
|
||||
<wd-button custom-class="w-70per" @click="handleQuery">确定</wd-button>
|
||||
<wd-button custom-class="w-20%" type="info" @click="handleResetQuery">重置</wd-button>
|
||||
<wd-button custom-class="w-70%" @click="handleQuery">确定</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
</wd-drop-menu-item>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { applyThemeToMiniProgram } from "@/utils/theme";
|
||||
import { getLighterColor, getDarkerColor } from "@/utils/colorUtils";
|
||||
|
||||
// 从缓存获取主题色
|
||||
const getThemeColor = (): string => {
|
||||
@@ -21,52 +23,20 @@ export const useThemeStore = defineStore("theme", () => {
|
||||
primaryColor.value = color;
|
||||
setThemeColorCache(color);
|
||||
|
||||
// 设置CSS变量,方便全局使用
|
||||
document.documentElement.style.setProperty("--primary-color", color);
|
||||
// 检测运行环境,区分处理
|
||||
if (typeof document !== "undefined") {
|
||||
// H5环境
|
||||
document.documentElement.style.setProperty("--primary-color", color);
|
||||
|
||||
// 计算衍生色
|
||||
const lighterColor = getLighterColor(color, 0.8);
|
||||
const darkerColor = getDarkerColor(color, 0.8);
|
||||
document.documentElement.style.setProperty("--primary-color-light", lighterColor);
|
||||
document.documentElement.style.setProperty("--primary-color-dark", darkerColor);
|
||||
};
|
||||
|
||||
// 获取浅色版本主题色
|
||||
const getLighterColor = (hexColor: string, factor: number): string => {
|
||||
// 去掉#前缀
|
||||
const hex = hexColor.replace("#", "");
|
||||
|
||||
// 解析RGB值
|
||||
let r = parseInt(hex.substring(0, 2), 16);
|
||||
let g = parseInt(hex.substring(2, 4), 16);
|
||||
let b = parseInt(hex.substring(4, 6), 16);
|
||||
|
||||
// 调亮颜色
|
||||
r = Math.min(255, Math.floor(r + (255 - r) * factor));
|
||||
g = Math.min(255, Math.floor(g + (255 - g) * factor));
|
||||
b = Math.min(255, Math.floor(b + (255 - b) * factor));
|
||||
|
||||
// 转回16进制
|
||||
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
||||
};
|
||||
|
||||
// 获取深色版本主题色
|
||||
const getDarkerColor = (hexColor: string, factor: number): string => {
|
||||
// 去掉#前缀
|
||||
const hex = hexColor.replace("#", "");
|
||||
|
||||
// 解析RGB值
|
||||
let r = parseInt(hex.substring(0, 2), 16);
|
||||
let g = parseInt(hex.substring(2, 4), 16);
|
||||
let b = parseInt(hex.substring(4, 6), 16);
|
||||
|
||||
// 调暗颜色
|
||||
r = Math.max(0, Math.floor(r * factor));
|
||||
g = Math.max(0, Math.floor(g * factor));
|
||||
b = Math.max(0, Math.floor(b * factor));
|
||||
|
||||
// 转回16进制
|
||||
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
||||
// 计算衍生色
|
||||
const lighterColor = getLighterColor(color, 0.8);
|
||||
const darkerColor = getDarkerColor(color, 0.8);
|
||||
document.documentElement.style.setProperty("--primary-color-light", lighterColor);
|
||||
document.documentElement.style.setProperty("--primary-color-dark", darkerColor);
|
||||
} else {
|
||||
// 小程序环境
|
||||
applyThemeToMiniProgram(color);
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化,应用主题色
|
||||
|
||||
51
src/utils/colorUtils.ts
Normal file
51
src/utils/colorUtils.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 颜色处理工具类
|
||||
*/
|
||||
|
||||
/**
|
||||
* 获取浅色版本的颜色
|
||||
* @param hexColor 十六进制颜色值
|
||||
* @param factor 调亮因子 (0-1)
|
||||
* @returns 调亮后的颜色值
|
||||
*/
|
||||
export function getLighterColor(hexColor: string, factor: number): string {
|
||||
// 去掉#前缀
|
||||
const hex = hexColor.replace("#", "");
|
||||
|
||||
// 解析RGB值
|
||||
let r = parseInt(hex.substring(0, 2), 16);
|
||||
let g = parseInt(hex.substring(2, 4), 16);
|
||||
let b = parseInt(hex.substring(4, 6), 16);
|
||||
|
||||
// 调亮颜色
|
||||
r = Math.min(255, Math.floor(r + (255 - r) * factor));
|
||||
g = Math.min(255, Math.floor(g + (255 - g) * factor));
|
||||
b = Math.min(255, Math.floor(b + (255 - b) * factor));
|
||||
|
||||
// 转回16进制
|
||||
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取深色版本的颜色
|
||||
* @param hexColor 十六进制颜色值
|
||||
* @param factor 调暗因子 (0-1)
|
||||
* @returns 调暗后的颜色值
|
||||
*/
|
||||
export function getDarkerColor(hexColor: string, factor: number): string {
|
||||
// 去掉#前缀
|
||||
const hex = hexColor.replace("#", "");
|
||||
|
||||
// 解析RGB值
|
||||
let r = parseInt(hex.substring(0, 2), 16);
|
||||
let g = parseInt(hex.substring(2, 4), 16);
|
||||
let b = parseInt(hex.substring(4, 6), 16);
|
||||
|
||||
// 调暗颜色
|
||||
r = Math.max(0, Math.floor(r * factor));
|
||||
g = Math.max(0, Math.floor(g * factor));
|
||||
b = Math.max(0, Math.floor(b * factor));
|
||||
|
||||
// 转回16进制
|
||||
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
||||
}
|
||||
33
src/utils/theme.ts
Normal file
33
src/utils/theme.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 小程序主题工具类
|
||||
* 用于解决小程序环境中CSS变量不能动态设置的问题
|
||||
*/
|
||||
|
||||
// 注入小程序环境的全局样式
|
||||
export function applyThemeToMiniProgram(primaryColor: string) {
|
||||
// 确保在小程序环境中执行
|
||||
if (typeof document !== "undefined") return;
|
||||
|
||||
try {
|
||||
// 设置TabBar样式
|
||||
uni.setTabBarStyle({
|
||||
color: "#000000",
|
||||
selectedColor: primaryColor,
|
||||
backgroundColor: "#ffffff",
|
||||
borderStyle: "black",
|
||||
});
|
||||
|
||||
console.log("小程序主题色已应用:", primaryColor);
|
||||
} catch (error) {
|
||||
console.error("应用小程序主题色失败:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// 在页面展示时应用主题
|
||||
export function applyThemeOnPageShow(primaryColor: string) {
|
||||
// 各平台小程序可能需要不同处理
|
||||
const platform = uni.getSystemInfoSync().platform;
|
||||
console.log(`当前平台: ${platform}, 应用主题色: ${primaryColor}`);
|
||||
|
||||
// 某些平台可能需要特定处理
|
||||
}
|
||||
Reference in New Issue
Block a user