refactor: 移除用户中心相关页面和隐私弹窗组件
删除与用户中心相关的所有页面,包括个人资料、修改密码、关于我们等 移除不再使用的隐私协议弹窗组件及相关样式文件 清理路由配置中不再需要的页面路径
This commit is contained in:
parent
7dd210e427
commit
4445e18b02
@ -40,12 +40,6 @@ export default defineUniPages({
|
||||
pagePath: 'pages/about/about',
|
||||
text: '关于',
|
||||
},
|
||||
{
|
||||
iconPath: 'static/tabbar/personal.png',
|
||||
selectedIconPath: 'static/tabbar/personalHL.png',
|
||||
pagePath: 'pages/mine/index',
|
||||
text: '我的',
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
@ -1,47 +0,0 @@
|
||||
@import 'wot-design-uni/components/wd-button/index.scss';
|
||||
:deep(.wd-privacy-popup) {
|
||||
width: 600rpx;
|
||||
padding: 0 24rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 32rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wd-privacy-popup {
|
||||
&__header {
|
||||
width: 100%;
|
||||
height: 128rpx;
|
||||
line-height: 128rpx;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
font-size: 30rpx;
|
||||
padding: 0 12rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
&__container {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 12rpx;
|
||||
margin-bottom: 32rpx;
|
||||
|
||||
font-size: 28rpx;
|
||||
line-height: 1.8;
|
||||
color: #3e3e3e;
|
||||
text-align: left;
|
||||
font-weight: 550;
|
||||
&-protocol {
|
||||
color: #4d80f0;
|
||||
}
|
||||
}
|
||||
|
||||
&__footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 36rpx;
|
||||
|
||||
button {
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<wd-popup
|
||||
v-model="showPopup"
|
||||
:close-on-click-modal="false"
|
||||
custom-class="wd-privacy-popup"
|
||||
@close="handleClose"
|
||||
>
|
||||
<view class="wd-privacy-popup__header">
|
||||
<!--标题-->
|
||||
<view class="wd-picker__title">{{ title }}</view>
|
||||
</view>
|
||||
<view class="wd-privacy-popup__container">
|
||||
<text>{{ desc }}</text>
|
||||
<text class="wd-privacy-popup__container-protocol" @click="openPrivacyContract">
|
||||
{{ protocol }}
|
||||
</text>
|
||||
<text>{{ subDesc }}</text>
|
||||
</view>
|
||||
<view class="wd-privacy-popup__footer">
|
||||
<button
|
||||
class="wd-privacy-popup__footer-disagree wd-button is-block is-round is-medium is-plain"
|
||||
id="disagree-btn"
|
||||
@click="handleDisagree"
|
||||
>
|
||||
拒绝
|
||||
</button>
|
||||
<button
|
||||
class="wd-privacy-popup__footer-agree wd-button is-primary is-block is-round is-medium"
|
||||
id="agree-btn"
|
||||
open-type="agreePrivacyAuthorization"
|
||||
@agreeprivacyauthorization="handleAgree"
|
||||
>
|
||||
同意
|
||||
</button>
|
||||
</view>
|
||||
</wd-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'privacy-popup',
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onBeforeMount, ref } from 'vue'
|
||||
|
||||
type Props = {
|
||||
title?: string // 标题
|
||||
desc?: string // 描述
|
||||
subDesc?: string // 字描述
|
||||
protocol?: string // 协议名称
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
title: '用户隐私保护提示',
|
||||
desc: '感谢您使用本应用,您使用本应用的服务之前请仔细阅读并同意',
|
||||
subDesc:
|
||||
'。当您点击同意并开始时用产品服务时,即表示你已理解并同息该条款内容,该条款将对您产生法律约束力。如您拒绝,将无法使用相应服务。',
|
||||
protocol: '《用户隐私保护指引》',
|
||||
})
|
||||
|
||||
const showPopup = ref<boolean>(false) // 是否展示popup
|
||||
|
||||
const privacyResolves = ref(new Set()) // onNeedPrivacyAuthorization的reslove
|
||||
|
||||
const privacyHandler = (resolve: any) => {
|
||||
showPopup.value = true
|
||||
privacyResolves.value.add(resolve)
|
||||
}
|
||||
|
||||
const emit = defineEmits(['agree', 'disagree'])
|
||||
|
||||
onBeforeMount(() => {
|
||||
// 注册监听
|
||||
if ((wx as any).onNeedPrivacyAuthorization) {
|
||||
;(wx as any).onNeedPrivacyAuthorization((resolve: any) => {
|
||||
if (typeof privacyHandler === 'function') {
|
||||
privacyHandler(resolve)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 同意隐私协议
|
||||
*/
|
||||
function handleAgree() {
|
||||
showPopup.value = false
|
||||
privacyResolves.value.forEach((resolve: any) => {
|
||||
resolve({
|
||||
event: 'agree',
|
||||
buttonId: 'agree-btn',
|
||||
})
|
||||
})
|
||||
privacyResolves.value.clear()
|
||||
emit('agree')
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝隐私协议
|
||||
*/
|
||||
function handleDisagree() {
|
||||
showPopup.value = false
|
||||
privacyResolves.value.forEach((resolve: any) => {
|
||||
resolve({
|
||||
event: 'disagree',
|
||||
})
|
||||
})
|
||||
privacyResolves.value.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开隐私协议
|
||||
*/
|
||||
function openPrivacyContract() {
|
||||
;(wx as any).openPrivacyContract({
|
||||
success: (res) => {
|
||||
console.log('openPrivacyContract success')
|
||||
},
|
||||
fail: (res) => {
|
||||
console.error('openPrivacyContract fail', res)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹出框关闭时清空
|
||||
*/
|
||||
function handleClose() {
|
||||
privacyResolves.value.clear()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
@ -35,12 +35,6 @@
|
||||
"selectedIconPath": "static/tabbar/exampleHL.png",
|
||||
"pagePath": "pages/about/about",
|
||||
"text": "关于"
|
||||
},
|
||||
{
|
||||
"iconPath": "static/tabbar/personal.png",
|
||||
"selectedIconPath": "static/tabbar/personalHL.png",
|
||||
"pagePath": "pages/mine/index",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -61,42 +55,6 @@
|
||||
"navigationBarTitleText": "关于",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "登录",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/about/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "关于我们"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/info/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人资料"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/password/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "修改密码"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subPackages": []
|
||||
|
@ -1,584 +0,0 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
style: {
|
||||
navigationBarTitleText: '登录',
|
||||
navigationStyle: 'custom',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
<template>
|
||||
<view class="login-container">
|
||||
<!-- 背景装饰元素 -->
|
||||
<view class="bg-decoration bg-circle-1"></view>
|
||||
<view class="bg-decoration bg-circle-2"></view>
|
||||
<view class="bg-decoration bg-circle-3"></view>
|
||||
|
||||
<view class="login-header">
|
||||
<image class="login-logo" :src="appLogo" mode="aspectFit"></image>
|
||||
<view class="login-title">{{ appTitle }}</view>
|
||||
</view>
|
||||
<view class="login-form">
|
||||
<view class="welcome-text">欢迎登录</view>
|
||||
<view class="login-desc">请输入您的账号和密码</view>
|
||||
<view class="login-input-group">
|
||||
<view class="input-wrapper">
|
||||
<wd-input
|
||||
v-model="loginForm.username"
|
||||
prefix-icon="user"
|
||||
placeholder="请输入用户名"
|
||||
clearable
|
||||
class="login-input"
|
||||
:border="false"
|
||||
required
|
||||
></wd-input>
|
||||
<view class="input-bottom-line"></view>
|
||||
</view>
|
||||
<view class="input-wrapper">
|
||||
<wd-input
|
||||
v-model="loginForm.password"
|
||||
prefix-icon="lock-on"
|
||||
placeholder="请输入密码"
|
||||
clearable
|
||||
show-password
|
||||
class="login-input"
|
||||
:border="false"
|
||||
required
|
||||
></wd-input>
|
||||
<view class="input-bottom-line"></view>
|
||||
</view>
|
||||
<!-- 验证码区域 -->
|
||||
<view class="input-wrapper captcha-wrapper">
|
||||
<wd-input
|
||||
v-if="captcha.captchaEnabled"
|
||||
v-model="loginForm.code"
|
||||
prefix-icon="secured"
|
||||
placeholder="请输入验证码"
|
||||
clearable
|
||||
class="login-input captcha-input"
|
||||
:border="false"
|
||||
required
|
||||
>
|
||||
<template #suffix>
|
||||
<image
|
||||
class="captcha-image"
|
||||
:src="'data:image/gif;base64,' + captcha.image"
|
||||
mode="aspectFit"
|
||||
@click="refreshCaptcha"
|
||||
></image>
|
||||
</template>
|
||||
</wd-input>
|
||||
<view class="input-bottom-line"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 登录按钮组 -->
|
||||
<view class="login-buttons">
|
||||
<!-- 账号密码登录按钮 -->
|
||||
<wd-button
|
||||
type="primary"
|
||||
size="large"
|
||||
block
|
||||
@click="handleAccountLogin"
|
||||
class="account-login-btn"
|
||||
>
|
||||
<wd-icon name="right" size="18px" class="login-icon"></wd-icon>
|
||||
登录
|
||||
</wd-button>
|
||||
<!-- 微信小程序一键登录按钮 -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="divider">
|
||||
<view class="divider-line"></view>
|
||||
<view class="divider-text">或</view>
|
||||
<view class="divider-line"></view>
|
||||
</view>
|
||||
<wd-button
|
||||
type="info"
|
||||
size="large"
|
||||
block
|
||||
plain
|
||||
@click="handleWechatLogin"
|
||||
class="wechat-login-btn"
|
||||
>
|
||||
微信一键登录
|
||||
</wd-button>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</view>
|
||||
<!-- 隐私协议勾选 -->
|
||||
<view class="privacy-agreement">
|
||||
<wd-checkbox
|
||||
v-model="agreePrivacy"
|
||||
shape="square"
|
||||
class="privacy-checkbox"
|
||||
active-color="var(--wot-color-theme, #1989fa)"
|
||||
>
|
||||
<view class="agreement-text">
|
||||
我已阅读并同意
|
||||
<text class="agreement-link" @click.stop="handleAgreement('user')">《用户协议》</text>
|
||||
和
|
||||
<text class="agreement-link" @click.stop="handleAgreement('privacy')">《隐私政策》</text>
|
||||
</view>
|
||||
</wd-checkbox>
|
||||
</view>
|
||||
<view class="login-footer"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { isMpWeixin } from '@/utils/platform'
|
||||
import { getCode, ILoginForm } from '@/api/login'
|
||||
import { toast } from '@/utils/toast'
|
||||
import { isTableBar } from '@/utils/index'
|
||||
import { ICaptcha } from '@/api/login.typings'
|
||||
const redirectRoute = ref('')
|
||||
|
||||
// 获取环境变量
|
||||
const appTitle = ref(import.meta.env.VITE_APP_TITLE || 'Unibest Login')
|
||||
const appLogo = ref(import.meta.env.VITE_APP_LOGO || '/static/logo.svg')
|
||||
|
||||
// 初始化store
|
||||
const userStore = useUserStore()
|
||||
// 路由位置
|
||||
// 验证码图片
|
||||
const captcha = ref<ICaptcha>({
|
||||
captchaEnabled: false,
|
||||
uuid: '',
|
||||
image: '',
|
||||
})
|
||||
// 登录表单数据
|
||||
const loginForm = ref<ILoginForm>({
|
||||
username: 'admin',
|
||||
password: '123456',
|
||||
code: '',
|
||||
uuid: '',
|
||||
})
|
||||
// 隐私协议勾选状态
|
||||
const agreePrivacy = ref(true)
|
||||
|
||||
// 页面加载完毕时触发
|
||||
onLoad((option) => {
|
||||
// 一进来就刷新验证码
|
||||
captcha.value.captchaEnabled && refreshCaptcha()
|
||||
// 获取跳转路由
|
||||
if (option.redirect) {
|
||||
redirectRoute.value = option.redirect
|
||||
}
|
||||
})
|
||||
|
||||
// 账号密码登录
|
||||
const handleAccountLogin = async () => {
|
||||
if (!agreePrivacy.value) {
|
||||
toast.error('请阅读同意协议')
|
||||
return
|
||||
}
|
||||
// 表单验证
|
||||
if (!loginForm.value.username) {
|
||||
toast.error('请输入用户名')
|
||||
return
|
||||
}
|
||||
if (!loginForm.value.password) {
|
||||
toast.error('请输入密码')
|
||||
return
|
||||
}
|
||||
if (captcha.value.captchaEnabled && !loginForm.value.code) {
|
||||
toast.error('请输入验证码')
|
||||
return
|
||||
}
|
||||
// 执行登录
|
||||
await userStore.login(loginForm.value)
|
||||
// 跳转到首页或重定向页面
|
||||
const targetUrl = redirectRoute.value || '/pages/index/index'
|
||||
if (isTableBar(targetUrl)) {
|
||||
uni.switchTab({ url: targetUrl })
|
||||
} else {
|
||||
uni.redirectTo({ url: targetUrl })
|
||||
}
|
||||
}
|
||||
|
||||
// 微信登录
|
||||
const handleWechatLogin = async () => {
|
||||
if (!isMpWeixin) {
|
||||
toast.info('请在微信小程序中使用此功能')
|
||||
return
|
||||
}
|
||||
|
||||
// 验证是否同意隐私协议
|
||||
if (!agreePrivacy.value) {
|
||||
toast.error('请先阅读并同意用户协议和隐私政策')
|
||||
return
|
||||
}
|
||||
// 微信登录
|
||||
await userStore.wxLogin()
|
||||
// 跳转到首页或重定向页面
|
||||
const targetUrl = redirectRoute.value || '/pages/index/index'
|
||||
if (isTableBar(targetUrl)) {
|
||||
uni.switchTab({ url: targetUrl })
|
||||
} else {
|
||||
uni.redirectTo({ url: targetUrl })
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新验证码
|
||||
const refreshCaptcha = () => {
|
||||
// 获取验证码
|
||||
getCode().then((res) => {
|
||||
const { data } = res
|
||||
loginForm.value.uuid = data.uuid
|
||||
captcha.value = data
|
||||
})
|
||||
}
|
||||
|
||||
// 处理协议点击
|
||||
const handleAgreement = (type: 'user' | 'privacy') => {
|
||||
const title = type === 'user' ? '用户协议' : '隐私政策'
|
||||
// showToast(`查看${title}`)
|
||||
// 实际项目中可以跳转到对应的协议页面
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/agreement/${type}`
|
||||
// })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 验证码输入框样式 */
|
||||
.captcha-wrapper {
|
||||
.captcha-input {
|
||||
:deep(.wd-input__suffix) {
|
||||
margin-right: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.captcha-image {
|
||||
width: 100px;
|
||||
height: 36px;
|
||||
margin-left: 10px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.1), transparent);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
transform: scale(0.96);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-container {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
padding: 0 70rpx;
|
||||
background-color: #ffffff;
|
||||
background-image: linear-gradient(
|
||||
135deg,
|
||||
rgba(25, 137, 250, 0.05) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 背景装饰元素 */
|
||||
.bg-decoration {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, rgba(25, 137, 250, 0.05), rgba(25, 137, 250, 0.1));
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.bg-circle-1 {
|
||||
width: 500rpx;
|
||||
height: 500rpx;
|
||||
top: -200rpx;
|
||||
right: -200rpx;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.bg-circle-2 {
|
||||
width: 400rpx;
|
||||
height: 400rpx;
|
||||
bottom: 10%;
|
||||
left: -200rpx;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.bg-circle-3 {
|
||||
width: 300rpx;
|
||||
height: 300rpx;
|
||||
bottom: -100rpx;
|
||||
right: 10%;
|
||||
opacity: 0.3;
|
||||
background: linear-gradient(135deg, rgba(7, 193, 96, 0.05), rgba(7, 193, 96, 0.1));
|
||||
}
|
||||
|
||||
.login-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 120rpx;
|
||||
animation: fadeInDown 0.8s ease-out;
|
||||
|
||||
.login-logo {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border-radius: 36rpx;
|
||||
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.12);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 6rpx 15rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.login-title {
|
||||
margin-top: 30rpx;
|
||||
font-size: 46rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
letter-spacing: 3rpx;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
.login-form {
|
||||
flex: 1;
|
||||
margin-top: 70rpx;
|
||||
animation: fadeIn 0.8s ease-out 0.2s both;
|
||||
|
||||
.welcome-text {
|
||||
margin-bottom: 16rpx;
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
text-align: center;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
|
||||
.login-desc {
|
||||
margin-bottom: 70rpx;
|
||||
font-size: 28rpx;
|
||||
color: #888888;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login-input-group {
|
||||
margin-bottom: 60rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
margin-bottom: 50rpx;
|
||||
transition: all 0.3s ease;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.login-input {
|
||||
padding: 12rpx 20rpx;
|
||||
background-color: rgba(245, 247, 250, 0.7);
|
||||
border-radius: 16rpx;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
:deep(.wd-input__inner) {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
:deep(.wd-input__placeholder) {
|
||||
font-size: 28rpx;
|
||||
color: #aaaaaa;
|
||||
}
|
||||
|
||||
&:focus-within {
|
||||
background-color: rgba(245, 247, 250, 0.95);
|
||||
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
transform: translateY(-3rpx);
|
||||
}
|
||||
}
|
||||
|
||||
.input-bottom-line {
|
||||
position: absolute;
|
||||
bottom: -2rpx;
|
||||
left: 5%;
|
||||
width: 90%;
|
||||
height: 2rpx;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
transparent,
|
||||
var(--wot-color-theme, #1989fa),
|
||||
transparent
|
||||
);
|
||||
transition: transform 0.4s ease;
|
||||
transform: scaleX(0);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&:focus-within .input-bottom-line {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.input-icon {
|
||||
margin-right: 16rpx;
|
||||
color: #666666;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
&:focus-within .input-icon {
|
||||
color: var(--wot-color-theme, #1989fa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 36rpx;
|
||||
|
||||
.account-login-btn {
|
||||
height: 96rpx;
|
||||
margin-top: 20rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
letter-spacing: 2rpx;
|
||||
border-radius: 48rpx;
|
||||
box-shadow: 0 10rpx 20rpx rgba(25, 137, 250, 0.25);
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.login-icon {
|
||||
margin-right: 8rpx;
|
||||
opacity: 0.8;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: 0 5rpx 10rpx rgba(25, 137, 250, 0.2);
|
||||
transform: scale(0.98);
|
||||
|
||||
.login-icon {
|
||||
transform: translateX(3rpx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 24rpx 0;
|
||||
|
||||
.divider-line {
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
.divider-text {
|
||||
padding: 0 24rpx;
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.wechat-login-btn {
|
||||
height: 96rpx;
|
||||
font-size: 32rpx;
|
||||
color: #07c160;
|
||||
border-color: #07c160;
|
||||
border-radius: 48rpx;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
.wechat-icon {
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: rgba(7, 193, 96, 0.08);
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.privacy-agreement {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 30rpx 0 40rpx;
|
||||
animation: fadeIn 0.8s ease-out 0.4s both;
|
||||
|
||||
.privacy-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.agreement-text {
|
||||
font-size: 26rpx;
|
||||
line-height: 1.6;
|
||||
color: #666666;
|
||||
|
||||
.agreement-link {
|
||||
padding: 0 4rpx;
|
||||
font-weight: 500;
|
||||
color: var(--wot-color-theme, #1989fa);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-footer {
|
||||
padding: 50rpx 0;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
/* 添加动画效果 */
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,173 +0,0 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationBarTitleText: '关于我们',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="about-container">
|
||||
<view class="about-card">
|
||||
<!-- 应用信息 -->
|
||||
<view class="app-info">
|
||||
<view class="logo-wrapper">
|
||||
<wd-img :src="appLogo" width="120px" height="120px" radius="24rpx"></wd-img>
|
||||
</view>
|
||||
<view class="app-name">{{ appTitle }}</view>
|
||||
<view class="app-version">版本 {{ packageJson.version }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">联系我们</view>
|
||||
<view class="section-content">
|
||||
<view class="contact-item">
|
||||
<wd-icon name="phone" size="20px" class="contact-icon"></wd-icon>
|
||||
<text class="contact-text">客服电话:400-XXX-XXXX</text>
|
||||
</view>
|
||||
<view class="contact-item">
|
||||
<wd-icon name="mail" size="20px" class="contact-icon"></wd-icon>
|
||||
<text class="contact-text">邮箱:support@unibest.tech</text>
|
||||
</view>
|
||||
<view class="contact-item">
|
||||
<wd-icon name="location" size="20px" class="contact-icon"></wd-icon>
|
||||
<text class="contact-text">地址:中国·深圳</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 版权信息 -->
|
||||
<view class="copyright">
|
||||
<text>Copyright © 2025-{{ currentYear }} {{ appTitle }}</text>
|
||||
<text>All Rights Reserved</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import packageJson from '@/../package.json'
|
||||
|
||||
const appTitle = ref(import.meta.env.VITE_APP_TITLE || 'unibest')
|
||||
const appLogo = ref(import.meta.env.VITE_APP_LOGO || '/static/logo.svg')
|
||||
|
||||
// 当前年份
|
||||
const currentYear = computed(() => new Date().getFullYear())
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.about-container {
|
||||
background-color: #f5f7fa;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.about-card {
|
||||
background-color: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
||||
overflow: hidden;
|
||||
padding: 40rpx 30rpx;
|
||||
}
|
||||
|
||||
/* 应用信息 */
|
||||
.app-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 30rpx 0 50rpx;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.logo-wrapper {
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
border-radius: 24rpx;
|
||||
}
|
||||
|
||||
.app-name {
|
||||
font-size: 40rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.app-version {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 信息区块 */
|
||||
.info-section {
|
||||
padding: 40rpx 0;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
position: relative;
|
||||
padding-left: 24rpx;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 8rpx;
|
||||
height: 32rpx;
|
||||
background: linear-gradient(135deg, #4a7bff, #6a5acd);
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.section-content {
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.content-text {
|
||||
font-size: 30rpx;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
/* 联系方式 */
|
||||
.contact-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.contact-icon {
|
||||
margin-right: 20rpx;
|
||||
color: #4a7bff;
|
||||
}
|
||||
|
||||
.contact-text {
|
||||
font-size: 30rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 版权信息 */
|
||||
.copyright {
|
||||
padding-top: 40rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
text {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,374 +0,0 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationBarTitleText: '我的',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="profile-container">
|
||||
{{ JSON.stringify(userInfo) }}
|
||||
<!-- 用户信息区域 -->
|
||||
<view class="user-info-section">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button class="avatar-button" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
|
||||
<wd-img :src="userInfo.avatar" width="80px" height="80px" radius="50%"></wd-img>
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<view class="avatar-wrapper" @click="run">
|
||||
<wd-img :src="userInfo.avatar" width="100%" height="100%" radius="50%"></wd-img>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view class="user-details">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<input
|
||||
type="nickname"
|
||||
class="weui-input"
|
||||
placeholder="请输入昵称"
|
||||
v-model="userInfo.username"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<view class="username">{{ userInfo.username }}</view>
|
||||
<!-- #endif -->
|
||||
<view class="user-id">ID: {{ userInfo.id }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 功能区块 -->
|
||||
<view class="function-section">
|
||||
<view class="cell-group">
|
||||
<view class="group-title">账号管理</view>
|
||||
<wd-cell title="个人资料" is-link @click="handleProfileInfo">
|
||||
<template #icon>
|
||||
<wd-icon name="user" size="20px"></wd-icon>
|
||||
</template>
|
||||
</wd-cell>
|
||||
<wd-cell title="账号安全" is-link @click="handlePassword">
|
||||
<template #icon>
|
||||
<wd-icon name="lock-on" size="20px"></wd-icon>
|
||||
</template>
|
||||
</wd-cell>
|
||||
</view>
|
||||
|
||||
<view class="cell-group">
|
||||
<view class="group-title">通用设置</view>
|
||||
<wd-cell title="消息通知" is-link @click="handleInform">
|
||||
<template #icon>
|
||||
<wd-icon name="notification" size="20px"></wd-icon>
|
||||
</template>
|
||||
</wd-cell>
|
||||
<wd-cell title="清理缓存" is-link @click="handleClearCache">
|
||||
<template #icon>
|
||||
<wd-icon name="clear" size="20px"></wd-icon>
|
||||
</template>
|
||||
</wd-cell>
|
||||
<wd-cell title="应用更新" is-link @click="handleAppUpdate">
|
||||
<template #icon>
|
||||
<wd-icon name="refresh1" size="20px"></wd-icon>
|
||||
</template>
|
||||
</wd-cell>
|
||||
<wd-cell title="关于我们" is-link @click="handleAbout">
|
||||
<template #icon>
|
||||
<wd-icon name="info-circle" size="20px"></wd-icon>
|
||||
</template>
|
||||
</wd-cell>
|
||||
</view>
|
||||
|
||||
<view class="logout-button-wrapper">
|
||||
<wd-button type="error" v-if="hasLogin" block @click="handleLogout">退出登录</wd-button>
|
||||
<wd-button type="primary" v-else block @click="handleLogin">登录</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useUserStore } from '@/store'
|
||||
import { useToast } from 'wot-design-uni'
|
||||
import { useUpload } from '@/utils/uploadFile'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { IUploadSuccessInfo } from '@/api/login.typings'
|
||||
|
||||
const userStore = useUserStore()
|
||||
// 使用storeToRefs解构userInfo
|
||||
const { userInfo } = storeToRefs(userStore)
|
||||
const toast = useToast()
|
||||
const hasLogin = ref(false)
|
||||
|
||||
onShow((options) => {
|
||||
hasLogin.value = !!uni.getStorageSync('token')
|
||||
console.log('个人中心onShow', hasLogin.value, options)
|
||||
|
||||
hasLogin.value && useUserStore().getUserInfo()
|
||||
})
|
||||
// #ifndef MP-WEIXIN
|
||||
// 上传头像
|
||||
const { run } = useUpload<IUploadSuccessInfo>(
|
||||
import.meta.env.VITE_UPLOAD_BASEURL,
|
||||
{},
|
||||
{
|
||||
onSuccess: (res) => {
|
||||
console.log('h5头像上传成功', res)
|
||||
useUserStore().setUserAvatar(res.url)
|
||||
},
|
||||
},
|
||||
)
|
||||
// #endif
|
||||
|
||||
// 微信小程序下登录
|
||||
const handleLogin = async () => {
|
||||
// #ifdef MP-WEIXIN
|
||||
|
||||
// 微信登录
|
||||
await userStore.wxLogin()
|
||||
hasLogin.value = true
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
uni.navigateTo({ url: '/pages/login/index' })
|
||||
// #endif
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
|
||||
// 微信小程序下选择头像事件
|
||||
const onChooseAvatar = (e: any) => {
|
||||
console.log('选择头像', e.detail)
|
||||
const { avatarUrl } = e.detail
|
||||
const { run } = useUpload<IUploadSuccessInfo>(
|
||||
import.meta.env.VITE_UPLOAD_BASEURL,
|
||||
{},
|
||||
{
|
||||
onSuccess: (res) => {
|
||||
console.log('wx头像上传成功', res)
|
||||
useUserStore().setUserAvatar(res.url)
|
||||
},
|
||||
},
|
||||
avatarUrl,
|
||||
)
|
||||
run()
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
// 微信小程序下设置用户名
|
||||
const getUserInfo = (e: any) => {
|
||||
console.log(e.detail)
|
||||
}
|
||||
// #endif
|
||||
|
||||
// 个人资料
|
||||
const handleProfileInfo = () => {
|
||||
uni.navigateTo({ url: `/pages/mine/info/index` })
|
||||
}
|
||||
// 账号安全
|
||||
const handlePassword = () => {
|
||||
uni.navigateTo({ url: `/pages/mine/password/index` })
|
||||
}
|
||||
// 消息通知
|
||||
const handleInform = () => {
|
||||
// uni.navigateTo({ url: `/pages/mine/inform/index` })
|
||||
toast.show('功能开发中')
|
||||
}
|
||||
// 应用更新
|
||||
const handleAppUpdate = () => {
|
||||
// #ifdef MP
|
||||
// #ifndef MP-HARMONY
|
||||
const updateManager = uni.getUpdateManager()
|
||||
updateManager.onCheckForUpdate(function (res) {
|
||||
// 请求完新版本信息的回调
|
||||
// console.log(res.hasUpdate)
|
||||
if (res.hasUpdate) {
|
||||
toast.show('检测到新版本,正在下载中...')
|
||||
} else {
|
||||
toast.show('已是最新版本')
|
||||
}
|
||||
})
|
||||
updateManager.onUpdateReady(function (res) {
|
||||
uni.showModal({
|
||||
title: '更新提示',
|
||||
content: '新版本已经准备好,是否重启应用?',
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
|
||||
updateManager.applyUpdate()
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
updateManager.onUpdateFailed(function (res) {
|
||||
// 新的版本下载失败
|
||||
toast.error('新版本下载失败')
|
||||
})
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
// #ifndef MP
|
||||
toast.show('功能开发中')
|
||||
// #endif
|
||||
}
|
||||
// 关于我们
|
||||
const handleAbout = () => {
|
||||
uni.navigateTo({ url: `/pages/mine/about/index` })
|
||||
}
|
||||
// 清除缓存
|
||||
const handleClearCache = () => {
|
||||
uni.showModal({
|
||||
title: '清除缓存',
|
||||
content: '确定要清除所有缓存吗?\n清除后需要重新登录',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
// 清除所有缓存
|
||||
uni.clearStorageSync()
|
||||
// 清除用户信息并跳转到登录页
|
||||
useUserStore().logout()
|
||||
toast.show('清除缓存成功')
|
||||
} catch (err) {
|
||||
console.error('清除缓存失败:', err)
|
||||
toast.error('清除缓存失败')
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
// 退出登录
|
||||
const handleLogout = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要退出登录吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 清空用户信息
|
||||
useUserStore().logout()
|
||||
hasLogin.value = false
|
||||
// 执行退出登录逻辑
|
||||
toast.show('退出登录成功')
|
||||
// #ifdef MP-WEIXIN
|
||||
// 微信小程序,去首页
|
||||
// uni.reLaunch({ url: '/pages/index/index' })
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
// 非微信小程序,去登录页
|
||||
// uni.reLaunch({ url: '/pages/login/index' })
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 基础样式 */
|
||||
.profile-container {
|
||||
overflow: hidden;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
/* 用户信息区域 */
|
||||
.user-info-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 40rpx;
|
||||
margin: 30rpx 30rpx 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
margin-right: 40rpx;
|
||||
overflow: hidden;
|
||||
border: 4rpx solid #f5f5f5;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
.avatar-button {
|
||||
height: 160rpx;
|
||||
padding: 0;
|
||||
margin-right: 40rpx;
|
||||
overflow: hidden;
|
||||
border: 4rpx solid #f5f5f5;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
.user-details {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.username {
|
||||
margin-bottom: 12rpx;
|
||||
font-size: 38rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
letter-spacing: 0.5rpx;
|
||||
}
|
||||
|
||||
.user-id {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.user-created {
|
||||
margin-top: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
/* 功能区块 */
|
||||
.function-section {
|
||||
padding: 0 20rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.cell-group {
|
||||
margin-bottom: 20rpx;
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.group-title {
|
||||
padding: 24rpx 30rpx 16rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #999;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
:deep(.wd-cell) {
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.wd-cell__title {
|
||||
margin-left: 5px;
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.cell-icon {
|
||||
margin-right: 20rpx;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
}
|
||||
/* 退出登录按钮 */
|
||||
.logout-button-wrapper {
|
||||
padding: 40rpx 30rpx;
|
||||
}
|
||||
|
||||
:deep(.wd-button--danger) {
|
||||
height: 88rpx;
|
||||
font-size: 32rpx;
|
||||
line-height: 88rpx;
|
||||
color: #fff;
|
||||
background-color: #f53f3f;
|
||||
border-radius: 44rpx;
|
||||
}
|
||||
</style>
|
@ -1,190 +0,0 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationBarTitleText: '个人资料',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="profile-info-container">
|
||||
<view class="profile-card">
|
||||
<view class="form-wrapper">
|
||||
<wd-form ref="formRef" :model="formData" label-width="160rpx" class="profile-form">
|
||||
<wd-cell-group class="form-group">
|
||||
<!-- 昵称 -->
|
||||
<view class="sex-field">
|
||||
<text class="field-label">昵称</text>
|
||||
<wd-input
|
||||
prop="name"
|
||||
clearable
|
||||
v-model="formData.name"
|
||||
placeholder="请输入昵称"
|
||||
:rules="[{ required: true, message: '请填写昵称' }]"
|
||||
class="form-input"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 性别 -->
|
||||
<view class="sex-field">
|
||||
<text class="field-label">性别</text>
|
||||
<wd-radio-group
|
||||
v-model="formData.sex"
|
||||
shape="button"
|
||||
:rules="[{ required: true, message: '请选择性别' }]"
|
||||
>
|
||||
<wd-radio :value="'1'">男</wd-radio>
|
||||
<wd-radio :value="'0'">女</wd-radio>
|
||||
</wd-radio-group>
|
||||
</view>
|
||||
</wd-cell-group>
|
||||
</wd-form>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="form-actions">
|
||||
<wd-button type="primary" size="large" @click="handleSubmit">保存修改</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { useUserStore } from '@/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { toast } from '@/utils/toast'
|
||||
import { updateInfo } from '@/api/login'
|
||||
|
||||
// 表单引用
|
||||
const formRef = ref()
|
||||
|
||||
// 用户信息
|
||||
const userStore = useUserStore()
|
||||
const { userInfo } = storeToRefs(userStore)
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
id: userInfo.value.id,
|
||||
name: userInfo.value.name,
|
||||
sex: userInfo.value.sex,
|
||||
})
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
// 表单验证
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
const { message } = await updateInfo(formData.value)
|
||||
await useUserStore().getUserInfo()
|
||||
toast.success(message)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.profile-info-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f7fa;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.profile-card {
|
||||
background-color: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
padding: 40rpx 30rpx 20rpx;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding-bottom: 16rpx;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 60rpx;
|
||||
height: 6rpx;
|
||||
background: linear-gradient(90deg, #4a7bff, #6a5acd);
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.form-wrapper {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.sex-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 30rpx;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
width: 160rpx;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.radio-btn {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
font-size: 30rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f5f7fa;
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
background: linear-gradient(135deg, #4a7bff, #6a5acd);
|
||||
box-shadow: 0 8rpx 16rpx rgba(74, 123, 255, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 4rpx 8rpx rgba(74, 123, 255, 0.15);
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,203 +0,0 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationBarTitleText: '修改密码',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="profile-info-container">
|
||||
<view class="profile-card">
|
||||
<view class="form-wrapper">
|
||||
<wd-form ref="formRef" :model="formData" label-width="160rpx" class="profile-form">
|
||||
<wd-cell-group class="form-group">
|
||||
<!-- 昵称 -->
|
||||
<view class="sex-field">
|
||||
<text class="field-label">旧密码</text>
|
||||
<wd-input
|
||||
prop="oldPassword"
|
||||
clearable
|
||||
v-model="formData.oldPassword"
|
||||
placeholder="请输入旧密码"
|
||||
show-password
|
||||
:rules="[{ required: true, message: '请填写旧密码' }]"
|
||||
class="form-input"
|
||||
/>
|
||||
</view>
|
||||
<view class="sex-field">
|
||||
<text class="field-label">新密码</text>
|
||||
<wd-input
|
||||
prop="newPassword"
|
||||
clearable
|
||||
v-model="formData.newPassword"
|
||||
placeholder="请输入新密码"
|
||||
show-password
|
||||
:rules="[{ required: true, message: '请填写新密码' }]"
|
||||
class="form-input"
|
||||
/>
|
||||
</view>
|
||||
<view class="sex-field">
|
||||
<text class="field-label">确认密码</text>
|
||||
<wd-input
|
||||
prop="confirmPassword"
|
||||
clearable
|
||||
v-model="formData.confirmPassword"
|
||||
placeholder="请输入新密码"
|
||||
show-password
|
||||
:rules="[{ required: true, message: '请填写新密码' }]"
|
||||
class="form-input"
|
||||
/>
|
||||
</view>
|
||||
</wd-cell-group>
|
||||
</wd-form>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="form-actions">
|
||||
<wd-button type="primary" size="large" @click="handleSubmit">保存修改</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { useUserStore } from '@/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { toast } from '@/utils/toast'
|
||||
import { updateInfo, updateUserPassword } from '@/api/login'
|
||||
|
||||
// 表单引用
|
||||
const formRef = ref()
|
||||
|
||||
// 用户信息
|
||||
const userStore = useUserStore()
|
||||
const { userInfo } = storeToRefs(userStore)
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
id: userInfo.value.id,
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
})
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
// 表单验证
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
const { message } = await updateUserPassword(formData.value)
|
||||
await useUserStore().logout()
|
||||
toast.success('修改成功,请重新登录')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.profile-info-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f7fa;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.profile-card {
|
||||
background-color: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
padding: 40rpx 30rpx 20rpx;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding-bottom: 16rpx;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 60rpx;
|
||||
height: 6rpx;
|
||||
background: linear-gradient(90deg, #4a7bff, #6a5acd);
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.form-wrapper {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.sex-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 30rpx;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
width: 160rpx;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.radio-btn {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
font-size: 30rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f5f7fa;
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
background: linear-gradient(135deg, #4a7bff, #6a5acd);
|
||||
box-shadow: 0 8rpx 16rpx rgba(74, 123, 255, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 4rpx 8rpx rgba(74, 123, 255, 0.15);
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
x
Reference in New Issue
Block a user