用户中心样式调整
This commit is contained in:
@@ -240,8 +240,10 @@
|
|||||||
"join": "Join",
|
"join": "Join",
|
||||||
"log-out-successfully": "Log out successfully",
|
"log-out-successfully": "Log out successfully",
|
||||||
"login-out-tip": "Are you sure you want to log out of your current login account?",
|
"login-out-tip": "Are you sure you want to log out of your current login account?",
|
||||||
|
"member": "Member",
|
||||||
"member-desc": "Unlock members to enjoy more discounts and promotions.",
|
"member-desc": "Unlock members to enjoy more discounts and promotions.",
|
||||||
"member-title": "Free trial of CHEFLINK",
|
"member-title": "Free trial of CHEFLINK",
|
||||||
|
"openMember": "Activate",
|
||||||
"order": "Order",
|
"order": "Order",
|
||||||
"platformAgreement": "Platform Agreement",
|
"platformAgreement": "Platform Agreement",
|
||||||
"privacyPolicy": "Privacy Policy",
|
"privacyPolicy": "Privacy Policy",
|
||||||
@@ -565,6 +567,7 @@
|
|||||||
},
|
},
|
||||||
"complaints": {
|
"complaints": {
|
||||||
"contact-information": "Contact information",
|
"contact-information": "Contact information",
|
||||||
|
"contact-information-placeholder": "Please enter your contact phone",
|
||||||
"contact-information-tip": "Your contact information helps us communicate and solve problems, only visible to staff",
|
"contact-information-tip": "Your contact information helps us communicate and solve problems, only visible to staff",
|
||||||
"description": "You are welcome to give us feedback on the use of our products and suggestions.",
|
"description": "You are welcome to give us feedback on the use of our products and suggestions.",
|
||||||
"feedback-content": "Feedback content",
|
"feedback-content": "Feedback content",
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
"goSettle": "去结算",
|
"goSettle": "去结算",
|
||||||
"google-map": "谷歌地图",
|
"google-map": "谷歌地图",
|
||||||
"googleLoginFailed": "谷歌登录授权失败,请重试",
|
"googleLoginFailed": "谷歌登录授权失败,请重试",
|
||||||
"gotIt": "明白了",
|
"gotIt": "我知道了",
|
||||||
"loading": "加载中",
|
"loading": "加载中",
|
||||||
"mile": "英里",
|
"mile": "英里",
|
||||||
"minutes": "分钟",
|
"minutes": "分钟",
|
||||||
@@ -240,8 +240,10 @@
|
|||||||
"join": "加入",
|
"join": "加入",
|
||||||
"log-out-successfully": "退出登录成功",
|
"log-out-successfully": "退出登录成功",
|
||||||
"login-out-tip": "是否确定退出当前登录账号",
|
"login-out-tip": "是否确定退出当前登录账号",
|
||||||
|
"member": "会员",
|
||||||
"member-desc": "解锁会员,享受更多折扣和促销活动。",
|
"member-desc": "解锁会员,享受更多折扣和促销活动。",
|
||||||
"member-title": "CHEFLINK 免费试用",
|
"member-title": "CHEFLINK 免费试用",
|
||||||
|
"openMember": "去开通",
|
||||||
"order": "订单",
|
"order": "订单",
|
||||||
"platformAgreement": "平台协议",
|
"platformAgreement": "平台协议",
|
||||||
"privacyPolicy": "隐私政策",
|
"privacyPolicy": "隐私政策",
|
||||||
@@ -565,6 +567,7 @@
|
|||||||
},
|
},
|
||||||
"complaints": {
|
"complaints": {
|
||||||
"contact-information": "联系电话",
|
"contact-information": "联系电话",
|
||||||
|
"contact-information-placeholder": "请输入您的联系电话",
|
||||||
"contact-information-tip": "您的联系方式有助于我们沟通解决问题,仅工作人员可见",
|
"contact-information-tip": "您的联系方式有助于我们沟通解决问题,仅工作人员可见",
|
||||||
"description": "您好,欢迎您给我们反馈产品的使用感受和建议。",
|
"description": "您好,欢迎您给我们反馈产品的使用感受和建议。",
|
||||||
"feedback-content": "反馈内容",
|
"feedback-content": "反馈内容",
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ onShow(()=> {
|
|||||||
<view class="bg-white rounded-36rpx overflow-hidden mt-18rpx py-30rpx">
|
<view class="bg-white rounded-36rpx overflow-hidden mt-18rpx py-30rpx">
|
||||||
<view class="flex-center-sb pr-20rpx mb-8rpx">
|
<view class="flex-center-sb pr-20rpx mb-8rpx">
|
||||||
<view class="flex items-center">
|
<view class="flex items-center">
|
||||||
<view class="w-8rpx h-30rpx bg-#00A76D"></view>
|
<view class="w-8rpx h-40rpx bg-#00A76D" style="margin-left: 10rpx;border-radius: 20rpx;"></view>
|
||||||
<text class="ml-10rpx text-34rpx text-#333">{{ t('pages-user.balance.detail-list') }}</text>
|
<text class="ml-10rpx text-34rpx text-#333">{{ t('pages-user.balance.detail-list') }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex items-center">
|
<view class="flex items-center">
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ChooseImage from "@/components/choose-image/choose-image.vue";
|
import ChooseImage from "@/components/choose-image/choose-image.vue";
|
||||||
import {appFeedbackAddPost} from "@/service";
|
import { appFeedbackAddPost } from "@/service";
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
const {t} = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
const form = ref({
|
const form = ref({
|
||||||
content: '',
|
content: '',
|
||||||
@@ -24,9 +24,37 @@ const createValidationSchema = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const chooseImageRef = ref()
|
const chooseImageRef = ref()
|
||||||
|
const showNoticePopup = ref(true)
|
||||||
|
const confirmCountdown = ref(5)
|
||||||
|
let countdownTimer: ReturnType<typeof setInterval> | null = null
|
||||||
|
|
||||||
// 校验单个字段
|
function startNoticeCountdown() {
|
||||||
const validateField = (field: keyof typeof form.value) => {
|
if (countdownTimer) {
|
||||||
|
clearInterval(countdownTimer)
|
||||||
|
}
|
||||||
|
confirmCountdown.value = 5
|
||||||
|
countdownTimer = setInterval(() => {
|
||||||
|
if (confirmCountdown.value <= 1) {
|
||||||
|
confirmCountdown.value = 0
|
||||||
|
if (countdownTimer) {
|
||||||
|
clearInterval(countdownTimer)
|
||||||
|
countdownTimer = null
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
confirmCountdown.value -= 1
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCloseNoticePopup() {
|
||||||
|
if (confirmCountdown.value > 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
showNoticePopup.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验单个字段(只校验 schema 中存在的字段)
|
||||||
|
const validateField = (field: 'content' | 'contactPhone') => {
|
||||||
try {
|
try {
|
||||||
const schema = createValidationSchema()
|
const schema = createValidationSchema()
|
||||||
const fieldSchema = schema.shape[field]
|
const fieldSchema = schema.shape[field]
|
||||||
@@ -69,7 +97,7 @@ const handleSubmit = () => {
|
|||||||
body: {
|
body: {
|
||||||
...form.value
|
...form.value
|
||||||
}
|
}
|
||||||
}).then(res=> {
|
}).then(res => {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: t('toast.submitSuccess'),
|
title: t('toast.submitSuccess'),
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
@@ -88,79 +116,217 @@ const handleChooseImage = () => {
|
|||||||
function onImageChange(files: string[]) {
|
function onImageChange(files: string[]) {
|
||||||
form.value.images = files[0]
|
form.value.images = files[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
startNoticeCountdown()
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnload(() => {
|
||||||
|
if (countdownTimer) {
|
||||||
|
clearInterval(countdownTimer)
|
||||||
|
countdownTimer = null
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<navbar :title="t('pages-user.complaints.title')" />
|
<view class="complaints-root">
|
||||||
<view class="px-18rpx">
|
<navbar :title="t('pages-user.complaints.title')" />
|
||||||
<view class="mb-27rpx mt-32rpx text-28rpx text-#333">
|
<view class="complaints-page">
|
||||||
{{ t('pages-user.complaints.description') }}
|
|
||||||
</view>
|
|
||||||
<view class="bg-white rounded-14rpx px-18rpx pt-30rpx pb-24rpx">
|
|
||||||
<view class="text-28rpx text-#333 mb-28rpx">{{ t('pages-user.complaints.feedback-content') }}:</view>
|
|
||||||
<view
|
|
||||||
class="min-h-234rpx box-border bg-#F6F6F6 rounded-14rpx overflow-hidden px-18rpx py-10rpx"
|
|
||||||
>
|
|
||||||
<wd-textarea
|
|
||||||
v-model="form.content"
|
|
||||||
:maxlength="500"
|
|
||||||
custom-class="!bg-#F6F6F6"
|
|
||||||
custom-textarea-container-class="!bg-#F6F6F6"
|
|
||||||
no-border
|
|
||||||
auto-height
|
|
||||||
:placeholder="t('pages-user.complaints.feedback-content-placeholder')"
|
|
||||||
@blur="validateField('content')"
|
|
||||||
/>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
|
|
||||||
<view>
|
<view class="form-card">
|
||||||
<view class="text-28rpx text-#333 mt-32rpx mb-24rpx">{{ t('pages-user.complaints.image') }}:</view>
|
<view class="field">
|
||||||
<view @click="handleChooseImage" class="relative w-210rpx h-210rpx">
|
<view class="field__label">{{ t('pages-user.complaints.feedback-content') }}</view>
|
||||||
<image
|
<view class="field__box field__box--textarea">
|
||||||
v-if="form.images"
|
<wd-textarea v-model="form.content" :maxlength="500" custom-class="!bg-transparent"
|
||||||
src="@img/chef/113.png"
|
custom-textarea-container-class="!bg-transparent" no-border auto-height
|
||||||
class="absolute top--10rpx right--10rpx z-10 w-36rpx h-36rpx"
|
:placeholder="t('pages-user.complaints.feedback-content-placeholder')" @blur="validateField('content')" />
|
||||||
></image>
|
</view>
|
||||||
<image
|
|
||||||
v-if="!form.images"
|
|
||||||
src="@img/chef/112.png"
|
|
||||||
class="w-210rpx h-210rpx"
|
|
||||||
></image>
|
|
||||||
<image
|
|
||||||
v-else
|
|
||||||
:src="form.images"
|
|
||||||
class="w-210rpx h-210rpx rounded-16rpx"
|
|
||||||
mode="aspectFill"
|
|
||||||
></image>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-14rpx flex-center-sb bg-white h-86rpx rounded-14rpx px-18rpx">
|
|
||||||
<view class="text-28rpx text-#333 ">{{ t('pages-user.complaints.contact-information') }}:</view>
|
|
||||||
<wd-input
|
|
||||||
no-border
|
|
||||||
custom-class="!p-[12rpx+20rpx] rounded-10rpx"
|
|
||||||
v-model.trim="form.contactPhone"
|
|
||||||
placeholderStyle="font-size: 28rpx;line-height: 40rpx;color: #B1B1B1; text-align: right;"
|
|
||||||
:placeholder="t('common.enter')"
|
|
||||||
:maxlength="50"
|
|
||||||
custom-input-class="text-right"
|
|
||||||
@blur="validateField('contactPhone')"
|
|
||||||
/>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="mt-38rpx text-28rpx text-#999">
|
<view class="field field--mt">
|
||||||
{{ t('pages-user.complaints.contact-information-tip') }}
|
<view class="field__label">{{ t('pages-user.complaints.image') }}</view>
|
||||||
|
<view class="upload" @click="handleChooseImage">
|
||||||
|
<image v-if="form.images" src="@img/chef/113.png" class="upload__remove"></image>
|
||||||
|
<image v-if="!form.images" src="@img/chef/112.png" class="upload__placeholder"></image>
|
||||||
|
<image v-else :src="form.images" class="upload__image" mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="field field--mt">
|
||||||
|
<view class="field__label">{{ t('pages-user.complaints.contact-information') }}</view>
|
||||||
|
<view class="field__box field__box--input">
|
||||||
|
<wd-input v-model.trim="form.contactPhone" no-border custom-class="!p-0 !bg-transparent"
|
||||||
|
custom-input-class="complaints-input" :placeholder="t('pages-user.complaints.contact-information-placeholder')" :maxlength="50"
|
||||||
|
@blur="validateField('contactPhone')" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="complaints-page__desc">
|
||||||
|
{{ t('pages-user.complaints.description') }}
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部固定提交按钮 -->
|
||||||
|
<view class="bottom-actions">
|
||||||
|
<wd-button custom-class="submit-btn" block @click="handleSubmit">
|
||||||
|
{{ t('common.submit') }}
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<ChooseImage ref="chooseImageRef" @change="onImageChange" />
|
||||||
|
|
||||||
|
<wd-popup v-model="showNoticePopup" :close-on-click-modal="false" custom-class="!bg-transparent">
|
||||||
|
<view class="notice-dialog">
|
||||||
|
<view class="notice-dialog__title">{{ t('pages-user.complaints.title') }}</view>
|
||||||
|
<view class="notice-dialog__content">
|
||||||
|
{{ t('pages-user.complaints.contact-information-tip') }}
|
||||||
|
</view>
|
||||||
|
<wd-button
|
||||||
|
custom-class="notice-dialog__btn"
|
||||||
|
block
|
||||||
|
:disabled="confirmCountdown > 0"
|
||||||
|
@click="handleCloseNoticePopup"
|
||||||
|
>
|
||||||
|
{{ confirmCountdown > 0 ? `${t('common.gotIt')} (${confirmCountdown}s)` : t('common.gotIt') }}
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
</wd-popup>
|
||||||
</view>
|
</view>
|
||||||
<fixed-bottom-large-btn
|
|
||||||
class="z-100"
|
|
||||||
fixed
|
|
||||||
:text="`${t('common.submit')}`"
|
|
||||||
@click="handleSubmit"
|
|
||||||
/>
|
|
||||||
<ChooseImage ref="chooseImageRef" @change="onImageChange" />
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.complaints-page {
|
||||||
|
padding: 32rpx 30rpx calc(160rpx + env(safe-area-inset-bottom));
|
||||||
|
background: #fff;
|
||||||
|
min-height: 100vh;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.complaints-page__desc {
|
||||||
|
font-size: 22rpx;
|
||||||
|
line-height: 36rpx;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 18rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 26rpx 24rpx 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field__label {
|
||||||
|
font-size: 26rpx;
|
||||||
|
line-height: 36rpx;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field--mt {
|
||||||
|
margin-top: 26rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field__box {
|
||||||
|
border: 1rpx solid #ececec;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
background: #fff;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field__box--textarea {
|
||||||
|
padding: 14rpx 16rpx;
|
||||||
|
min-height: 240rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field__box--input {
|
||||||
|
padding: 18rpx 16rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.complaints-input) {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 26rpx;
|
||||||
|
line-height: 36rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload {
|
||||||
|
width: 176rpx;
|
||||||
|
height: 176rpx;
|
||||||
|
border: 1rpx solid #ececec;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload__placeholder,
|
||||||
|
.upload__image {
|
||||||
|
width: 176rpx;
|
||||||
|
height: 176rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload__remove {
|
||||||
|
position: absolute;
|
||||||
|
top: -10rpx;
|
||||||
|
right: -10rpx;
|
||||||
|
z-index: 2;
|
||||||
|
width: 36rpx;
|
||||||
|
height: 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-actions {
|
||||||
|
position: fixed;
|
||||||
|
left: 30rpx;
|
||||||
|
right: 30rpx;
|
||||||
|
bottom: calc(36rpx + env(safe-area-inset-bottom));
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.submit-btn) {
|
||||||
|
height: 108rpx !important;
|
||||||
|
border-radius: 999rpx !important;
|
||||||
|
background: #111 !important;
|
||||||
|
color: #fff !important;
|
||||||
|
font-size: 32rpx !important;
|
||||||
|
font-weight: 800 !important;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-dialog {
|
||||||
|
width: 620rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 36rpx 28rpx 28rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-dialog__title {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
line-height: 40rpx;
|
||||||
|
color: #222;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-dialog__content {
|
||||||
|
margin-top: 18rpx;
|
||||||
|
margin-bottom: 28rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
line-height: 38rpx;
|
||||||
|
color: #666;
|
||||||
|
// text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.notice-dialog__btn) {
|
||||||
|
height: 84rpx !important;
|
||||||
|
border-radius: 999rpx !important;
|
||||||
|
font-size: 28rpx !important;
|
||||||
|
font-weight: 700 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -101,11 +101,11 @@ function handleSubmit() {
|
|||||||
bg-color="#fff"
|
bg-color="#fff"
|
||||||
>
|
>
|
||||||
<template #top>
|
<template #top>
|
||||||
<navbar />
|
<navbar :title="t('pages-user.coupon.title')" />
|
||||||
<view class="px-30rpx pb-42rpx">
|
<view class="px-30rpx pb-42rpx">
|
||||||
<view class="text-46rpx text-#333 font-bold lh-46rpx mb-36rpx mt-10rpx">
|
<!-- <view class="text-46rpx text-#333 font-bold lh-46rpx mb-36rpx mt-10rpx">
|
||||||
{{ t("pages-user.coupon.title") }}</view
|
{{ t("pages-user.coupon.title") }}</view
|
||||||
>
|
> -->
|
||||||
<view
|
<view
|
||||||
class="flex items-center h-88rpx px-30rpx bg-#F2F3F6 rounded-88rpx box-border"
|
class="flex items-center h-88rpx px-30rpx bg-#F2F3F6 rounded-88rpx box-border"
|
||||||
>
|
>
|
||||||
@@ -131,10 +131,11 @@ function handleSubmit() {
|
|||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<view class="px-30rpx my-38rpx" v-if="isSearch">
|
<view class="px-30rpx my-34rpx" style="position: fixed; bottom: 10rpx; left: 0; right: 0; z-index: 100;" v-if="isSearch">
|
||||||
<wd-button
|
<wd-button
|
||||||
block
|
block
|
||||||
custom-class="!h-108rpx !text-36rpx !rounded-16rpx"
|
custom-class="!h-98rpx !text-32rpx !rounded-46rpx"
|
||||||
|
style="background-color: #000;"
|
||||||
:disabled="isDisabled"
|
:disabled="isDisabled"
|
||||||
@click="handleSubmit"
|
@click="handleSubmit"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: ISFP_T 68358856@qq.com
|
||||||
|
* @Date: 2026-02-25 10:02:44
|
||||||
|
* @LastEditors: ISFP_T 68358856@qq.com
|
||||||
|
* @LastEditTime: 2026-04-01 15:51:38
|
||||||
|
* @FilePath: \chef-link-uniapp\src\pages-user\pages\edit-nickname\index.vue
|
||||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||||
|
-->
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import Config from '@/config'
|
import Config from '@/config'
|
||||||
import {useUserStore} from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
import { appUserEditUserInfoPost } from '@/service'
|
import { appUserEditUserInfoPost } from '@/service'
|
||||||
import {debounce} from 'throttle-debounce';
|
import { debounce } from 'throttle-debounce';
|
||||||
import {z} from "zod";
|
import { z } from "zod";
|
||||||
import * as R from "ramda";
|
import * as R from "ramda";
|
||||||
|
|
||||||
const {t} = useI18n()
|
const { t } = useI18n()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
const form = ref({
|
const form = ref({
|
||||||
@@ -15,8 +23,8 @@ const form = ref({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
firstName: z.string().min(1, {message: t('pages-login.prompt.first-name')}),
|
firstName: z.string().min(1, { message: t('pages-login.prompt.first-name') }),
|
||||||
surname: z.string().min(1, {message: t('pages-login.prompt.last-name')}),
|
surname: z.string().min(1, { message: t('pages-login.prompt.last-name') }),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@@ -26,10 +34,10 @@ function checkForm(): boolean {
|
|||||||
const fieldErrorMessage = validateFormField.error.flatten().fieldErrors
|
const fieldErrorMessage = validateFormField.error.flatten().fieldErrors
|
||||||
const errorMessage: string | undefined = R.path([0, 0], R.values(fieldErrorMessage))
|
const errorMessage: string | undefined = R.path([0, 0], R.values(fieldErrorMessage))
|
||||||
errorMessage &&
|
errorMessage &&
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: errorMessage,
|
title: errorMessage,
|
||||||
icon: 'none',
|
icon: 'none',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return validateFormField.success
|
return validateFormField.success
|
||||||
}
|
}
|
||||||
@@ -42,7 +50,7 @@ async function submit() {
|
|||||||
...form.value,
|
...form.value,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
await uni.showToast({title: t('common.prompt.save-successfully'), icon: 'none'})
|
await uni.showToast({ title: t('common.prompt.save-successfully'), icon: 'none' })
|
||||||
await userStore.getUserInfo()
|
await userStore.getUserInfo()
|
||||||
setTimeout(uni.navigateBack, 1000)
|
setTimeout(uni.navigateBack, 1000)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -57,47 +65,28 @@ const handleSubmit = R.when(checkForm, debounce(Config.debounceLongTime, submit,
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<navbar :title="t('navbar-nickname')"/>
|
<navbar :title="t('navbar-nickname')" />
|
||||||
<view class="py-36rpx px-30rpx bg-#fff">
|
<view class="py-36rpx px-30rpx bg-#fff">
|
||||||
<view class="">
|
<view class="">
|
||||||
<view class="text-28-bold">{{ t("pages-login.sign-up.first-name") }}</view>
|
<view class="text-28-bold">{{ t("pages-login.sign-up.first-name") }}</view>
|
||||||
<view
|
<view class="mt-20rpx flex px-30rpx items-center h-88rpx border-2rpx border-solid border-#D4D4D4 rounded-20rpx">
|
||||||
class="mt-20rpx flex px-30rpx items-center h-88rpx border-2rpx border-solid border-#D4D4D4 rounded-20rpx">
|
<wd-input no-border clearable :focus-when-clear="false" :cursorSpacing="20" :maxlength="40"
|
||||||
<wd-input
|
v-model.trim="form.firstName" custom-class="flex-1" placeholder="">
|
||||||
no-border
|
</wd-input>
|
||||||
clearable
|
|
||||||
:focus-when-clear="false"
|
|
||||||
:cursorSpacing="20"
|
|
||||||
:maxlength="40"
|
|
||||||
v-model.trim="form.firstName"
|
|
||||||
custom-class="flex-1"
|
|
||||||
placeholder=""
|
|
||||||
>
|
|
||||||
</wd-input>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="mt-36rpx">
|
|
||||||
<view class="text-28-bold">{{ t("pages-login.sign-up.last-name") }}</view>
|
|
||||||
<view
|
|
||||||
class="mt-20rpx flex px-30rpx items-center h-88rpx border-2rpx border-solid border-#D4D4D4 rounded-20rpx">
|
|
||||||
<wd-input
|
|
||||||
no-border
|
|
||||||
clearable
|
|
||||||
:focus-when-clear="false"
|
|
||||||
use-prefix-slot
|
|
||||||
:maxlength="40"
|
|
||||||
:cursorSpacing="20"
|
|
||||||
v-model.trim="form.surname"
|
|
||||||
custom-class="flex-1"
|
|
||||||
placeholder=""
|
|
||||||
>
|
|
||||||
</wd-input>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="mt-36rpx">
|
||||||
|
<view class="text-28-bold">{{ t("pages-login.sign-up.last-name") }}</view>
|
||||||
|
<view class="mt-20rpx flex px-30rpx items-center h-88rpx border-2rpx border-solid border-#D4D4D4 rounded-20rpx">
|
||||||
|
<wd-input no-border clearable :focus-when-clear="false" use-prefix-slot :maxlength="40" :cursorSpacing="20"
|
||||||
|
v-model.trim="form.surname" custom-class="flex-1" placeholder="">
|
||||||
|
</wd-input>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view class="mt-318rpx px-30rpx">
|
<view class="mt-318rpx px-30rpx" style="position: fixed; bottom: 30rpx; left: 0; right: 0; z-index: 100;">
|
||||||
<wd-button custom-class="!h-108rpx !text-36rpx font-bold !rounded-16rpx" block @click="handleSubmit">
|
<wd-button custom-class="!h-108rpx !text-36rpx font-bold !rounded-46rpx" block @click="handleSubmit">
|
||||||
{{ t('common.save') }}
|
{{ t('common.save') }}
|
||||||
</wd-button>
|
</wd-button>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ onLoad(()=> {
|
|||||||
:auto="false"
|
:auto="false"
|
||||||
>
|
>
|
||||||
<template #top>
|
<template #top>
|
||||||
<navbar />
|
<navbar :title="t('pages.mine.help')" />
|
||||||
<view class="px-30rpx pb-42rpx">
|
<view class="px-30rpx pb-42rpx">
|
||||||
<view class="text-46rpx text-#333 font-bold lh-46rpx mb-36rpx mt-10rpx">{{ t("pages.mine.help") }}</view>
|
<!-- <view class="text-46rpx text-#333 font-bold lh-46rpx mb-36rpx mt-10rpx">{{ t("pages.mine.help") }}</view> -->
|
||||||
<view
|
<view
|
||||||
class="flex items-center h-88rpx px-30rpx bg-#F2F3F6 rounded-88rpx box-border"
|
class="flex items-center h-88rpx px-30rpx bg-#F2F3F6 rounded-88rpx box-border"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -0,0 +1,464 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
type PayPwdMode = 'set' | 'change'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
t: (key: string) => string
|
||||||
|
isSend: number
|
||||||
|
payPwdMode: PayPwdMode
|
||||||
|
showLoginPwdPopup: boolean
|
||||||
|
showLoginPwdForgetPopup: boolean
|
||||||
|
showPayPwdPopup: boolean
|
||||||
|
showPayPwdForgetPopup: boolean
|
||||||
|
loginPwdForm: { oldLoginPwd: string; newLoginPwd: string; confirmPwd: string }
|
||||||
|
loginPwdForgetForm: { phone: string; captcha: string; newLoginPwd: string; confirmPwd: string }
|
||||||
|
payPwdSetForm: { phone: string; captcha: string; payPwd: string; confirmPwd: string }
|
||||||
|
payPwdChangeForm: { oldPayPwd: string; newPayPwd: string; confirmPwd: string }
|
||||||
|
payPwdForgetForm: { phone: string; captcha: string; payPwd: string; confirmPwd: string }
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:showLoginPwdPopup', value: boolean): void
|
||||||
|
(e: 'update:showLoginPwdForgetPopup', value: boolean): void
|
||||||
|
(e: 'update:showPayPwdPopup', value: boolean): void
|
||||||
|
(e: 'update:showPayPwdForgetPopup', value: boolean): void
|
||||||
|
(e: 'submit-login-pwd'): void
|
||||||
|
(e: 'submit-login-pwd-forget'): void
|
||||||
|
(e: 'submit-pay-pwd-set'): void
|
||||||
|
(e: 'submit-pay-pwd-change'): void
|
||||||
|
(e: 'submit-pay-pwd-forget'): void
|
||||||
|
(e: 'request-login-forget-code'): void
|
||||||
|
(e: 'request-pay-set-code'): void
|
||||||
|
(e: 'request-pay-forget-code'): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const loginPwdPopupVisible = computed({
|
||||||
|
get: () => props.showLoginPwdPopup,
|
||||||
|
set: (value: boolean) => emit('update:showLoginPwdPopup', value),
|
||||||
|
})
|
||||||
|
|
||||||
|
const loginPwdForgetPopupVisible = computed({
|
||||||
|
get: () => props.showLoginPwdForgetPopup,
|
||||||
|
set: (value: boolean) => emit('update:showLoginPwdForgetPopup', value),
|
||||||
|
})
|
||||||
|
|
||||||
|
const payPwdPopupVisible = computed({
|
||||||
|
get: () => props.showPayPwdPopup,
|
||||||
|
set: (value: boolean) => emit('update:showPayPwdPopup', value),
|
||||||
|
})
|
||||||
|
|
||||||
|
const payPwdForgetPopupVisible = computed({
|
||||||
|
get: () => props.showPayPwdForgetPopup,
|
||||||
|
set: (value: boolean) => emit('update:showPayPwdForgetPopup', value),
|
||||||
|
})
|
||||||
|
|
||||||
|
function openLoginPwdForget() {
|
||||||
|
emit('update:showLoginPwdPopup', false)
|
||||||
|
emit('update:showLoginPwdForgetPopup', true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function openPayPwdForget() {
|
||||||
|
emit('update:showPayPwdPopup', false)
|
||||||
|
emit('update:showPayPwdForgetPopup', true)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<wd-popup
|
||||||
|
v-model="loginPwdPopupVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
position="bottom"
|
||||||
|
custom-class="ios-popup-mask"
|
||||||
|
>
|
||||||
|
<view class="ios-dialog">
|
||||||
|
<view class="ios-dialog__header">
|
||||||
|
<view class="ios-dialog__title">{{ t('navbar-change-password') }}</view>
|
||||||
|
<view class="ios-dialog__close" @click="emit('update:showLoginPwdPopup', false)">×</view>
|
||||||
|
</view>
|
||||||
|
<view class="ios-dialog__body">
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="loginPwdForm.oldLoginPwd"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="20"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-old-password')"
|
||||||
|
/>
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="loginPwdForm.newLoginPwd"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="16"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-new-password')"
|
||||||
|
/>
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="loginPwdForm.confirmPwd"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="16"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-new-password-again')"
|
||||||
|
/>
|
||||||
|
<view class="ios-dialog__link-row">
|
||||||
|
<text class="ios-dialog__link" @click="openLoginPwdForget">
|
||||||
|
{{ t('navbar-forget-password') }}?
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="ios-dialog__footer">
|
||||||
|
<wd-button custom-class="ios-dialog__btn ios-dialog__btn--primary" block @click="emit('submit-login-pwd')">
|
||||||
|
{{ t('common.confirm') }}
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</wd-popup>
|
||||||
|
|
||||||
|
<wd-popup
|
||||||
|
v-model="loginPwdForgetPopupVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
position="bottom"
|
||||||
|
custom-class="ios-popup-mask"
|
||||||
|
>
|
||||||
|
<view class="ios-dialog">
|
||||||
|
<view class="ios-dialog__header">
|
||||||
|
<view class="ios-dialog__title">{{ t('navbar-forget-password') }}</view>
|
||||||
|
<view class="ios-dialog__close" @click="emit('update:showLoginPwdForgetPopup', false)">×</view>
|
||||||
|
</view>
|
||||||
|
<view class="ios-dialog__body">
|
||||||
|
<wd-input :model-value="loginPwdForgetForm.phone" disabled disabledColor="transparent" no-border />
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="loginPwdForgetForm.captcha"
|
||||||
|
style="color:#000 !important;"
|
||||||
|
no-border
|
||||||
|
clearable
|
||||||
|
:maxlength="6"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-verification-code')"
|
||||||
|
>
|
||||||
|
<template #suffix>
|
||||||
|
<wd-button :disabled="!!isSend" custom-class="ios-code-btn" @click="emit('request-login-forget-code')">
|
||||||
|
{{ isSend ? isSend + 'S' : t('common.obtain') }}
|
||||||
|
</wd-button>
|
||||||
|
</template>
|
||||||
|
</wd-input>
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="loginPwdForgetForm.newLoginPwd"
|
||||||
|
style="color:#000 !important;"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="20"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-new-password')"
|
||||||
|
/>
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="loginPwdForgetForm.confirmPwd"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="20"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-new-password-again')"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<view class="ios-dialog__footer">
|
||||||
|
<wd-button custom-class="ios-dialog__btn ios-dialog__btn--primary" block @click="emit('submit-login-pwd-forget')">
|
||||||
|
{{ t('common.confirm') }}
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</wd-popup>
|
||||||
|
|
||||||
|
<wd-popup
|
||||||
|
v-model="payPwdPopupVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
position="bottom"
|
||||||
|
custom-class="ios-popup-mask"
|
||||||
|
>
|
||||||
|
<view class="ios-dialog">
|
||||||
|
<view class="ios-dialog__header">
|
||||||
|
<view class="ios-dialog__title">
|
||||||
|
{{ payPwdMode === 'set' ? t('navbar-set-payment-password') : t('navbar-change-payment-password') }}
|
||||||
|
</view>
|
||||||
|
<view class="ios-dialog__close" @click="emit('update:showPayPwdPopup', false)">×</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="ios-dialog__body" v-if="payPwdMode === 'set'">
|
||||||
|
<wd-input :model-value="payPwdSetForm.phone" disabled disabledColor="transparent" no-border />
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="payPwdSetForm.captcha"
|
||||||
|
no-border
|
||||||
|
clearable
|
||||||
|
:maxlength="6"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-verification-code')"
|
||||||
|
>
|
||||||
|
<template #suffix>
|
||||||
|
<wd-button :disabled="!!isSend" custom-class="ios-code-btn" @click="emit('request-pay-set-code')">
|
||||||
|
{{ isSend ? isSend + 'S' : t('common.obtain') }}
|
||||||
|
</wd-button>
|
||||||
|
</template>
|
||||||
|
</wd-input>
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="payPwdSetForm.payPwd"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="6"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-new-password')"
|
||||||
|
/>
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="payPwdSetForm.confirmPwd"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="6"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-new-password-again')"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="ios-dialog__body" v-else>
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="payPwdChangeForm.oldPayPwd"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="6"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-old-password')"
|
||||||
|
/>
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="payPwdChangeForm.newPayPwd"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="6"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-new-password')"
|
||||||
|
/>
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="payPwdChangeForm.confirmPwd"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="6"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-new-password-again')"
|
||||||
|
/>
|
||||||
|
<view class="ios-dialog__link-row">
|
||||||
|
<text class="ios-dialog__link" @click="openPayPwdForget">
|
||||||
|
{{ t('navbar-forget-password') }}?
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="ios-dialog__footer">
|
||||||
|
<wd-button
|
||||||
|
custom-class="ios-dialog__btn ios-dialog__btn--primary"
|
||||||
|
block
|
||||||
|
@click="payPwdMode === 'set' ? emit('submit-pay-pwd-set') : emit('submit-pay-pwd-change')"
|
||||||
|
>
|
||||||
|
{{ t('common.confirm') }}
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</wd-popup>
|
||||||
|
|
||||||
|
<wd-popup
|
||||||
|
v-model="payPwdForgetPopupVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
position="bottom"
|
||||||
|
custom-class="ios-popup-mask"
|
||||||
|
>
|
||||||
|
<view class="ios-dialog">
|
||||||
|
<view class="ios-dialog__header">
|
||||||
|
<view class="ios-dialog__title">{{ t('navbar-forget-payment-password') }}</view>
|
||||||
|
<view class="ios-dialog__close" @click="emit('update:showPayPwdForgetPopup', false)">×</view>
|
||||||
|
</view>
|
||||||
|
<view class="ios-dialog__body">
|
||||||
|
<wd-input :model-value="payPwdForgetForm.phone" disabled disabledColor="transparent" no-border />
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="payPwdForgetForm.captcha"
|
||||||
|
style="color:#000 !important;"
|
||||||
|
no-border
|
||||||
|
clearable
|
||||||
|
:maxlength="6"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-verification-code')"
|
||||||
|
>
|
||||||
|
<template #suffix>
|
||||||
|
<wd-button :disabled="!!isSend" custom-class="ios-code-btn" @click="emit('request-pay-forget-code')">
|
||||||
|
{{ isSend ? isSend + 'S' : t('common.obtain') }}
|
||||||
|
</wd-button>
|
||||||
|
</template>
|
||||||
|
</wd-input>
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="payPwdForgetForm.payPwd"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="6"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-new-password')"
|
||||||
|
/>
|
||||||
|
<view class="ios-dialog__divider" />
|
||||||
|
<wd-input
|
||||||
|
v-model.trim="payPwdForgetForm.confirmPwd"
|
||||||
|
no-border
|
||||||
|
show-password
|
||||||
|
clearable
|
||||||
|
:maxlength="6"
|
||||||
|
:placeholder="t('pages-user.pay-password.input-placeholder.enter-new-password-again')"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<view class="ios-dialog__footer">
|
||||||
|
<wd-button custom-class="ios-dialog__btn ios-dialog__btn--primary" block @click="emit('submit-pay-pwd-forget')">
|
||||||
|
{{ t('common.confirm') }}
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</wd-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.ios-dialog {
|
||||||
|
width: 100vw;
|
||||||
|
max-height: 88vh;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 40rpx 40rpx 0 0;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ios-dialog__header {
|
||||||
|
height: 96rpx;
|
||||||
|
padding: 0 28rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ios-dialog__title {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 36rpx;
|
||||||
|
line-height: 44rpx;
|
||||||
|
color: #1c1c1e;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ios-dialog__close {
|
||||||
|
position: absolute;
|
||||||
|
right: 28rpx;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 56rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 44rpx;
|
||||||
|
line-height: 44rpx;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ios-dialog__body {
|
||||||
|
margin: 0 24rpx 12rpx;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ios-dialog__divider {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ios-dialog__link-row {
|
||||||
|
padding: 12rpx 8rpx 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ios-dialog__link {
|
||||||
|
font-size: 34rpx;
|
||||||
|
line-height: 34rpx;
|
||||||
|
color: #3c3c43;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ios-dialog__footer {
|
||||||
|
padding: 210rpx 24rpx 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ios-dialog__btn) {
|
||||||
|
height: 88rpx !important;
|
||||||
|
border-radius: 999rpx !important;
|
||||||
|
font-size: 34rpx !important;
|
||||||
|
font-weight: 600 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ios-dialog__btn--primary) {
|
||||||
|
background: #000 !important;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ios-code-btn) {
|
||||||
|
min-width: 92rpx !important;
|
||||||
|
height: 52rpx !important;
|
||||||
|
padding: 0 20rpx !important;
|
||||||
|
border-radius: 16rpx !important;
|
||||||
|
font-size: 26rpx !important;
|
||||||
|
font-weight: 400 !important;
|
||||||
|
line-height: 52rpx !important;
|
||||||
|
background: #000 !important;
|
||||||
|
color: #fff !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ios-code-btn.is-disabled) {
|
||||||
|
background: #8e8e93 !important;
|
||||||
|
color: #fff !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.wd-input) {
|
||||||
|
height: 84rpx !important;
|
||||||
|
border: 1rpx solid #dedede !important;
|
||||||
|
border-radius: 24rpx !important;
|
||||||
|
padding: 0 24rpx !important;
|
||||||
|
box-sizing: border-box !important;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 14rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.wd-input__inner) {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
border: none !important;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.wd-input__suffix) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ios-popup-mask) {
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ios-popup-mask.wd-popup--bottom) {
|
||||||
|
border-radius: 40rpx 40rpx 0 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,21 +1,260 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {useMessage} from "wot-design-uni";
|
import {useMessage} from "wot-design-uni";
|
||||||
import {useConfigStore, useUserStore} from "@/store";
|
import {useConfigStore, useUserStore} from "@/store";
|
||||||
import {conversionMobile} from "@/utils";
|
|
||||||
import {Agreement} from "@/constant/enums";
|
|
||||||
import ChooseLanguage from "./components/choose-language/choose-language.vue";
|
import ChooseLanguage from "./components/choose-language/choose-language.vue";
|
||||||
import Logout from "./components/log-out/log-out.vue";
|
import Logout from "./components/log-out/log-out.vue";
|
||||||
|
import PasswordDialogs from "./components/password-dialogs/password-dialogs.vue";
|
||||||
import Config from "@/config";
|
import Config from "@/config";
|
||||||
import {appUserLogOffPost} from "@/service";
|
import {appUserLogOffPost, appUserEditLoginPwdPost, appUserForgetPwdPost} from "@/service";
|
||||||
|
import { setPayPwd, editPayPwd, forgetPayPwd } from "@/pages-user/service";
|
||||||
|
import { SmsType } from "@/constant/enums";
|
||||||
|
import { z } from "zod";
|
||||||
|
import useGetMsgCode from "@/hooks/useGetMsgCode";
|
||||||
|
|
||||||
const {t} = useI18n();
|
const {t} = useI18n();
|
||||||
const {locale} = useI18n();
|
const {locale} = useI18n();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const configStore = useConfigStore()
|
const configStore = useConfigStore()
|
||||||
const message = useMessage();
|
const message = useMessage();
|
||||||
const currentVersion = ref(configStore.appVersion)
|
|
||||||
const chooseLanguageRef = ref<InstanceType<typeof ChooseLanguage>>()
|
const chooseLanguageRef = ref<InstanceType<typeof ChooseLanguage>>()
|
||||||
const logoutRef = ref<InstanceType<typeof Logout>>()
|
const logoutRef = ref<InstanceType<typeof Logout>>()
|
||||||
|
const currentLanguageLabel = computed(() => (locale.value === 'en' ? 'English' : '中文'))
|
||||||
|
const { isSend, getMsgCode } = useGetMsgCode()
|
||||||
|
|
||||||
|
const showLoginPwdPopup = ref(false)
|
||||||
|
const showLoginPwdForgetPopup = ref(false)
|
||||||
|
const showPayPwdPopup = ref(false)
|
||||||
|
const showPayPwdForgetPopup = ref(false)
|
||||||
|
const payPwdMode = ref<'set' | 'change'>('set')
|
||||||
|
|
||||||
|
const loginPwdForm = ref({
|
||||||
|
oldLoginPwd: '',
|
||||||
|
newLoginPwd: '',
|
||||||
|
confirmPwd: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const loginPwdSchema = computed(() =>
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
oldLoginPwd: z.string().min(1, { message: t('pages-user.pay-password.input-placeholder.enter-old-password') }),
|
||||||
|
newLoginPwd: z
|
||||||
|
.string()
|
||||||
|
.min(8, { message: t('pages-user.pay-password.password-length-limit') })
|
||||||
|
.max(16, { message: t('pages-user.pay-password.password-length-limit') }),
|
||||||
|
confirmPwd: z.string().min(1, { message: t('pages-user.pay-password.input-placeholder.enter-new-password-again') }),
|
||||||
|
})
|
||||||
|
.refine((data) => data.newLoginPwd === data.confirmPwd, {
|
||||||
|
path: ['confirmPwd'],
|
||||||
|
message: t('pages-user.pay-password.two-passwords-inconsistent'),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
function validateBySchema(schema: z.ZodTypeAny, data: any) {
|
||||||
|
const res = schema.safeParse(data)
|
||||||
|
if (!res.success) {
|
||||||
|
const errors = res.error.flatten().fieldErrors
|
||||||
|
const first = Object.values(errors).find((arr) => Array.isArray(arr) && arr.length)?.[0]
|
||||||
|
if (first) uni.showToast({ title: String(first), icon: 'none' })
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitLoginPwd() {
|
||||||
|
if (!validateBySchema(loginPwdSchema.value, loginPwdForm.value)) return
|
||||||
|
await appUserEditLoginPwdPost({ body: { ...loginPwdForm.value } })
|
||||||
|
uni.showToast({ title: t('pages-user.password.change-password-successfully'), icon: 'none' })
|
||||||
|
showLoginPwdPopup.value = false
|
||||||
|
loginPwdForm.value = { oldLoginPwd: '', newLoginPwd: '', confirmPwd: '' }
|
||||||
|
setTimeout(() => {
|
||||||
|
userStore.clear()
|
||||||
|
uni.navigateTo({ url: Config.loginPath })
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
const loginPwdForgetForm = ref({
|
||||||
|
areaCode: userStore.userInfo?.areaCode || '',
|
||||||
|
phone: userStore.userInfo?.phone || '',
|
||||||
|
captcha: '',
|
||||||
|
confirmPwd: '',
|
||||||
|
newLoginPwd: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const loginPwdForgetSchema = computed(() =>
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
captcha: z.string().min(1, { message: t('pages-user.pay-password.input-placeholder.enter-verification-code') }),
|
||||||
|
confirmPwd: z
|
||||||
|
.string()
|
||||||
|
.min(1, { message: t('pages-user.pay-password.input-placeholder.enter-new-password') })
|
||||||
|
.regex(/^\d{6}$/, { message: t('pages-user.pay-password.enter-6-digit-password') }),
|
||||||
|
newLoginPwd: z.string().min(1, { message: t('pages-user.pay-password.input-placeholder.enter-new-password-again') }),
|
||||||
|
})
|
||||||
|
.refine((data) => data.confirmPwd === data.newLoginPwd, {
|
||||||
|
path: ['newLoginPwd'],
|
||||||
|
message: t('pages-user.pay-password.two-passwords-inconsistent'),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
function openLoginPwdPopup() {
|
||||||
|
showLoginPwdPopup.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function openPayPwdPopup() {
|
||||||
|
payPwdMode.value = userStore.userInfo?.payPwd ? 'change' : 'set'
|
||||||
|
showPayPwdPopup.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestLoginForgetCode() {
|
||||||
|
if (isSend.value > 0) return
|
||||||
|
getMsgCode({
|
||||||
|
type: SmsType.USER_FORGET_PASSWORD,
|
||||||
|
phone: loginPwdForgetForm.value.phone,
|
||||||
|
areaCode: loginPwdForgetForm.value.areaCode,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitLoginPwdForget() {
|
||||||
|
if (!validateBySchema(loginPwdForgetSchema.value, loginPwdForgetForm.value)) return
|
||||||
|
await appUserForgetPwdPost({ body: { ...loginPwdForgetForm.value } })
|
||||||
|
uni.showToast({ title: t('pages-user.password.forget-password-successfully'), icon: 'none' })
|
||||||
|
await userStore.getUserInfo()
|
||||||
|
showLoginPwdForgetPopup.value = false
|
||||||
|
loginPwdForgetForm.value = {
|
||||||
|
areaCode: userStore.userInfo?.areaCode || '',
|
||||||
|
phone: userStore.userInfo?.phone || '',
|
||||||
|
captcha: '',
|
||||||
|
confirmPwd: '',
|
||||||
|
newLoginPwd: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const payPwdSetForm = ref({
|
||||||
|
areaCode: userStore.userInfo?.areaCode || '',
|
||||||
|
phone: userStore.userInfo?.phone || '',
|
||||||
|
captcha: '',
|
||||||
|
payPwd: '',
|
||||||
|
confirmPwd: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const payPwdSetSchema = computed(() =>
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
captcha: z.string().min(1, { message: t('pages-user.pay-password.input-placeholder.enter-verification-code') }),
|
||||||
|
payPwd: z
|
||||||
|
.string()
|
||||||
|
.min(1, { message: t('pages-user.pay-password.input-placeholder.enter-new-password') })
|
||||||
|
.regex(/^\d{6}$/, { message: t('pages-user.pay-password.enter-6-digit-password') }),
|
||||||
|
confirmPwd: z.string().min(1, { message: t('pages-user.pay-password.input-placeholder.enter-new-password-again') }),
|
||||||
|
})
|
||||||
|
.refine((data) => data.payPwd === data.confirmPwd, {
|
||||||
|
path: ['confirmPwd'],
|
||||||
|
message: t('pages-user.pay-password.two-passwords-inconsistent'),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
function requestPaySetCode() {
|
||||||
|
if (isSend.value > 0) return
|
||||||
|
getMsgCode({
|
||||||
|
type: SmsType.USER_SET_PAYMENT_PASSWORD,
|
||||||
|
phone: payPwdSetForm.value.phone,
|
||||||
|
areaCode: payPwdSetForm.value.areaCode,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitPayPwdSet() {
|
||||||
|
if (!validateBySchema(payPwdSetSchema.value, payPwdSetForm.value)) return
|
||||||
|
await setPayPwd(payPwdSetForm.value as any)
|
||||||
|
uni.showToast({ title: t('pages-user.pay-password.set-payment-password-successfully'), icon: 'none' })
|
||||||
|
await userStore.getUserInfo()
|
||||||
|
showPayPwdPopup.value = false
|
||||||
|
payPwdSetForm.value = {
|
||||||
|
areaCode: userStore.userInfo?.areaCode || '',
|
||||||
|
phone: userStore.userInfo?.phone || '',
|
||||||
|
captcha: '',
|
||||||
|
payPwd: '',
|
||||||
|
confirmPwd: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const payPwdChangeForm = ref({
|
||||||
|
oldPayPwd: '',
|
||||||
|
newPayPwd: '',
|
||||||
|
confirmPwd: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const payPwdChangeSchema = computed(() =>
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
oldPayPwd: z.string().min(1, { message: t('pages-user.pay-password.input-placeholder.enter-old-password') }),
|
||||||
|
newPayPwd: z
|
||||||
|
.string()
|
||||||
|
.min(1, { message: t('pages-user.pay-password.input-placeholder.enter-new-password') })
|
||||||
|
.regex(/^\d{6}$/, { message: t('pages-user.pay-password.enter-6-digit-password') }),
|
||||||
|
confirmPwd: z.string().min(1, { message: t('pages-user.pay-password.input-placeholder.enter-new-password-again') }),
|
||||||
|
})
|
||||||
|
.refine((data) => data.newPayPwd === data.confirmPwd, {
|
||||||
|
path: ['confirmPwd'],
|
||||||
|
message: t('pages-user.pay-password.two-passwords-inconsistent'),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
async function submitPayPwdChange() {
|
||||||
|
if (!validateBySchema(payPwdChangeSchema.value, payPwdChangeForm.value)) return
|
||||||
|
await editPayPwd(payPwdChangeForm.value as any)
|
||||||
|
uni.showToast({ title: t('pages-user.pay-password.change-payment-password-successfully'), icon: 'none' })
|
||||||
|
await userStore.getUserInfo()
|
||||||
|
showPayPwdPopup.value = false
|
||||||
|
payPwdChangeForm.value = { oldPayPwd: '', newPayPwd: '', confirmPwd: '' }
|
||||||
|
}
|
||||||
|
|
||||||
|
const payPwdForgetForm = ref({
|
||||||
|
areaCode: userStore.userInfo?.areaCode || '',
|
||||||
|
phone: userStore.userInfo?.phone || '',
|
||||||
|
captcha: '',
|
||||||
|
payPwd: '',
|
||||||
|
confirmPwd: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const payPwdForgetSchema = computed(() =>
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
captcha: z.string().min(1, { message: t('pages-user.pay-password.input-placeholder.enter-verification-code') }),
|
||||||
|
payPwd: z
|
||||||
|
.string()
|
||||||
|
.min(1, { message: t('pages-user.pay-password.input-placeholder.enter-new-password') })
|
||||||
|
.regex(/^\d{6}$/, { message: t('pages-user.pay-password.enter-6-digit-password') }),
|
||||||
|
confirmPwd: z.string().min(1, { message: t('pages-user.pay-password.input-placeholder.enter-new-password-again') }),
|
||||||
|
})
|
||||||
|
.refine((data) => data.payPwd === data.confirmPwd, {
|
||||||
|
path: ['confirmPwd'],
|
||||||
|
message: t('pages-user.pay-password.two-passwords-inconsistent'),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
function requestPayForgetCode() {
|
||||||
|
if (isSend.value > 0) return
|
||||||
|
getMsgCode({
|
||||||
|
type: SmsType.USER_FORGET_PAYMENT_PASSWORD,
|
||||||
|
phone: payPwdForgetForm.value.phone,
|
||||||
|
areaCode: payPwdForgetForm.value.areaCode,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitPayPwdForget() {
|
||||||
|
if (!validateBySchema(payPwdForgetSchema.value, payPwdForgetForm.value)) return
|
||||||
|
await forgetPayPwd(payPwdForgetForm.value as any)
|
||||||
|
uni.showToast({ title: t('pages-user.pay-password.forget-payment-password-successfully'), icon: 'none' })
|
||||||
|
await userStore.getUserInfo()
|
||||||
|
showPayPwdForgetPopup.value = false
|
||||||
|
payPwdForgetForm.value = {
|
||||||
|
areaCode: userStore.userInfo?.areaCode || '',
|
||||||
|
phone: userStore.userInfo?.phone || '',
|
||||||
|
captcha: '',
|
||||||
|
payPwd: '',
|
||||||
|
confirmPwd: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleChooseLanguage() {
|
function handleChooseLanguage() {
|
||||||
if (chooseLanguageRef.value) {
|
if (chooseLanguageRef.value) {
|
||||||
@@ -30,10 +269,7 @@ function navigateTo(url: string) {
|
|||||||
|
|
||||||
|
|
||||||
function handleSetOrUpdatePassword() {
|
function handleSetOrUpdatePassword() {
|
||||||
if (userStore.userInfo?.payPwd) {
|
openPayPwdPopup()
|
||||||
return navigateTo(`/pages-user/pages/pay-password/change/index`)
|
|
||||||
}
|
|
||||||
navigateTo(`/pages-user/pages/pay-password/set/index`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleLogout() {
|
function handleLogout() {
|
||||||
@@ -74,76 +310,160 @@ function handleLogoutAccount() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<navbar :title="t('navbar-settings')"/>
|
<view class="setting-root">
|
||||||
<view class="pt-20rpx">
|
<navbar :title="t('navbar-settings')"/>
|
||||||
<view class="text-30-bold bg-#fff">
|
<view class="setting-page">
|
||||||
<view
|
<view class="setting-card">
|
||||||
class="flex justify-between items-center border-bottom font-bold p-[40rpx+20rpx]"
|
<view
|
||||||
@click="navigateTo('/pages-user/pages/password/change/index')"
|
class="setting-row setting-row--border"
|
||||||
>
|
@click="openLoginPwdPopup"
|
||||||
<view>{{ t("pages-user.setting.modification") }}</view>
|
>
|
||||||
<image
|
<text class="setting-row__label">{{ t("pages-user.setting.modification") }}</text>
|
||||||
src="@img/chef/100202.png"
|
<image src="@img/chef/100202.png" class="setting-row__arrow"></image>
|
||||||
class="shrink-0 ml-16rpx w-22rpx h-30rpx"
|
</view>
|
||||||
></image>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view
|
<view class="setting-row" @click="handleSetOrUpdatePassword">
|
||||||
@click="
|
<text class="setting-row__label">{{ t("pages-user.setting.payPwd") }}</text>
|
||||||
handleSetOrUpdatePassword
|
<view class="setting-row__right">
|
||||||
"
|
<text class="setting-row__value">{{ t('pages.mine.set') }}</text>
|
||||||
class="flex justify-between items-center p-[40rpx+20rpx] border-bottom"
|
<image src="@img/chef/100202.png" class="setting-row__arrow"></image>
|
||||||
>
|
</view>
|
||||||
<view>{{ t("pages-user.setting.payPwd") }}</view>
|
|
||||||
<view class="flex items-center">
|
|
||||||
<text>{{ t('navbar-settings') }}</text>
|
|
||||||
<image
|
|
||||||
src="@img/chef/100202.png"
|
|
||||||
class="shrink-0 ml-16rpx w-22rpx h-30rpx"
|
|
||||||
></image>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view
|
<view class="setting-card setting-card--gap">
|
||||||
class="flex justify-between items-center p-[40rpx+20rpx] border-bottom before:!bg-common"
|
<view class="setting-row" @click="handleChooseLanguage">
|
||||||
@click="handleChooseLanguage"
|
<text class="setting-row__label">{{ t("pages-user.setting.language") }}</text>
|
||||||
>
|
<view class="setting-row__right">
|
||||||
<view>{{ t("pages-user.setting.language") }}</view>
|
<text class="setting-row__value">{{ currentLanguageLabel }}</text>
|
||||||
<view class="flex items-center">
|
<image src="@img/chef/100202.png" class="setting-row__arrow"></image>
|
||||||
<text>{{ locale === 'en' ? 'English' : '中文'}}</text>
|
</view>
|
||||||
<image
|
|
||||||
src="@img/chef/100202.png"
|
|
||||||
class="shrink-0 ml-16rpx w-22rpx h-30rpx"
|
|
||||||
></image>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view
|
<view class="setting-card setting-card--gap">
|
||||||
class="flex justify-between items-center font-bold p-[40rpx+20rpx]"
|
<view class="setting-row" @click="handleLogoutAccount">
|
||||||
@click="handleLogoutAccount"
|
<text class="setting-row__label setting-row__label--strong">{{ t('pages-user.setting.cancelAccount') }}</text>
|
||||||
>
|
<!-- <image src="@img/chef/100202.png" class="setting-row__arrow"></image> -->
|
||||||
<view>{{ t('pages-user.setting.cancelAccount') }}</view>
|
</view>
|
||||||
<image
|
|
||||||
src="@img/chef/100202.png"
|
|
||||||
class="shrink-0 ml-16rpx w-22rpx h-30rpx"
|
|
||||||
></image>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="px-30rpx mt-180rpx">
|
|
||||||
<wd-button
|
|
||||||
custom-class="!h-108rpx !text-36rpx !text-white !bg-#14181B !rounded-16rpx"
|
|
||||||
block
|
|
||||||
@click="handleLogout"
|
|
||||||
>
|
|
||||||
{{ t('pages-user.setting.logout') }}
|
|
||||||
</wd-button>
|
|
||||||
|
|
||||||
|
<view class="logout-actions">
|
||||||
|
<wd-button custom-class="logout-btn" block @click="handleLogout">
|
||||||
|
{{ t('pages-user.setting.logout') }}
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<choose-language ref="chooseLanguageRef"/>
|
<choose-language ref="chooseLanguageRef"/>
|
||||||
<logout ref="logoutRef"/>
|
<logout ref="logoutRef"/>
|
||||||
|
<password-dialogs
|
||||||
|
:t="t"
|
||||||
|
:is-send="isSend"
|
||||||
|
:pay-pwd-mode="payPwdMode"
|
||||||
|
:show-login-pwd-popup="showLoginPwdPopup"
|
||||||
|
:show-login-pwd-forget-popup="showLoginPwdForgetPopup"
|
||||||
|
:show-pay-pwd-popup="showPayPwdPopup"
|
||||||
|
:show-pay-pwd-forget-popup="showPayPwdForgetPopup"
|
||||||
|
:login-pwd-form="loginPwdForm"
|
||||||
|
:login-pwd-forget-form="loginPwdForgetForm"
|
||||||
|
:pay-pwd-set-form="payPwdSetForm"
|
||||||
|
:pay-pwd-change-form="payPwdChangeForm"
|
||||||
|
:pay-pwd-forget-form="payPwdForgetForm"
|
||||||
|
@update:show-login-pwd-popup="showLoginPwdPopup = $event"
|
||||||
|
@update:show-login-pwd-forget-popup="showLoginPwdForgetPopup = $event"
|
||||||
|
@update:show-pay-pwd-popup="showPayPwdPopup = $event"
|
||||||
|
@update:show-pay-pwd-forget-popup="showPayPwdForgetPopup = $event"
|
||||||
|
@submit-login-pwd="submitLoginPwd"
|
||||||
|
@submit-login-pwd-forget="submitLoginPwdForget"
|
||||||
|
@submit-pay-pwd-set="submitPayPwdSet"
|
||||||
|
@submit-pay-pwd-change="submitPayPwdChange"
|
||||||
|
@submit-pay-pwd-forget="submitPayPwdForget"
|
||||||
|
@request-login-forget-code="requestLoginForgetCode"
|
||||||
|
@request-pay-set-code="requestPaySetCode"
|
||||||
|
@request-pay-forget-code="requestPayForgetCode"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped lang="scss">
|
||||||
|
.setting-root {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-page {
|
||||||
|
padding: 20rpx 30rpx calc(160rpx + env(safe-area-inset-bottom));
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-card--gap {
|
||||||
|
margin-top: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-row {
|
||||||
|
height: 102rpx;
|
||||||
|
padding: 0 28rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
&--border {
|
||||||
|
border-bottom: 1rpx solid #ededed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-size: 34rpx;
|
||||||
|
line-height: 34rpx;
|
||||||
|
color: #2c2c2c;
|
||||||
|
// font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label--strong {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value {
|
||||||
|
font-size: 30rpx;
|
||||||
|
line-height: 30rpx;
|
||||||
|
color: #2c2c2c;
|
||||||
|
// font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__arrow {
|
||||||
|
width: 22rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-actions {
|
||||||
|
position: fixed;
|
||||||
|
left: 30rpx;
|
||||||
|
right: 30rpx;
|
||||||
|
bottom: calc(36rpx + env(safe-area-inset-bottom));
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.logout-btn) {
|
||||||
|
height: 108rpx !important;
|
||||||
|
border-radius: 22rpx !important;
|
||||||
|
background: #111 !important;
|
||||||
|
color: #fff !important;
|
||||||
|
font-size: 36rpx !important;
|
||||||
|
font-weight: 700 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Config from '@/config'
|
import Config from '@/config'
|
||||||
import {useUserStore} from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
import type chooseImageVue from '@/components/choose-image/choose-image.vue'
|
import type chooseImageVue from '@/components/choose-image/choose-image.vue'
|
||||||
import { appUserEditUserInfoPost } from '@/service'
|
import { appUserEditUserInfoPost } from '@/service'
|
||||||
import {debounce} from 'throttle-debounce';
|
import { debounce } from 'throttle-debounce';
|
||||||
import {upload} from '@/utils/upload/alioss'
|
import { upload } from '@/utils/upload/alioss'
|
||||||
import {EventEnum} from "@/constant/enums";
|
import { EventEnum } from "@/constant/enums";
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const {t} = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
|
||||||
const chooseImageRef = ref<InstanceType<typeof chooseImageVue> | null>(null)
|
const chooseImageRef = ref<InstanceType<typeof chooseImageVue> | null>(null)
|
||||||
@@ -18,16 +18,16 @@ const form = ref({
|
|||||||
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => userStore.userInfo,
|
() => userStore.userInfo,
|
||||||
(newValue) => {
|
(newValue) => {
|
||||||
console.log('userInfo', newValue)
|
console.log('userInfo', newValue)
|
||||||
form.value = {
|
form.value = {
|
||||||
avatar: newValue?.avatar || '',
|
avatar: newValue?.avatar || '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
deep: true,
|
deep: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
async function handleCropperAvatarSuccess(avatarUrl: string) {
|
async function handleCropperAvatarSuccess(avatarUrl: string) {
|
||||||
@@ -61,13 +61,13 @@ async function submit() {
|
|||||||
avatar: form.value.avatar,
|
avatar: form.value.avatar,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
await uni.showToast({title: t('common.prompt.save-successfully'), icon: 'none'})
|
await uni.showToast({ title: t('common.prompt.save-successfully'), icon: 'none' })
|
||||||
await userStore.getUserInfo()
|
await userStore.getUserInfo()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSubmit = debounce(Config.debounceLongTime, submit, {atBegin: true})
|
const handleSubmit = debounce(Config.debounceLongTime, submit, { atBegin: true })
|
||||||
|
|
||||||
function handleAddImg() {
|
function handleAddImg() {
|
||||||
chooseImageRef.value?.init()
|
chooseImageRef.value?.init()
|
||||||
@@ -91,7 +91,7 @@ function handlePreviewImage() {
|
|||||||
|
|
||||||
|
|
||||||
function navigateTo(url: string) {
|
function navigateTo(url: string) {
|
||||||
uni.navigateTo({url})
|
uni.navigateTo({ url })
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoad(async () => {
|
onLoad(async () => {
|
||||||
@@ -119,37 +119,31 @@ onBackPress(() => {
|
|||||||
</template>
|
</template>
|
||||||
</choose-image>
|
</choose-image>
|
||||||
<view class="h-full flex flex-col">
|
<view class="h-full flex flex-col">
|
||||||
<navbar :title="t('navbar-personal-information')"/>
|
<navbar :title="t('navbar-personal-information')" />
|
||||||
<view class="bg-#fff">
|
<view class="bg-#fff">
|
||||||
<view class="p-18rpx flex items-center justify-between border-bottom">
|
<view class="p-18rpx flex items-center justify-between border-bottom">
|
||||||
<view class="shrink-0 mr-20rpx text-30rpx text-primary">{{ t('pages-user.user-info.head-portrait') }}</view>
|
<view class="shrink-0 mr-20rpx text-30rpx text-primary">{{ t('pages-user.user-info.head-portrait') }}</view>
|
||||||
<view class="flex items-center" @click="handleAddImg">
|
<view class="flex items-center" @click="handleAddImg">
|
||||||
<image :src="form.avatar" class="shrink-0 w-80rpx h-80rpx rounded-full"></image>
|
<image :src="form.avatar" class="shrink-0 w-80rpx h-80rpx rounded-full"></image>
|
||||||
<image
|
<image src="@img/chef/100202.png" class="shrink-0 ml-16rpx w-22rpx h-30rpx"></image>
|
||||||
src="@img/chef/100202.png"
|
|
||||||
class="shrink-0 ml-16rpx w-22rpx h-30rpx"
|
|
||||||
></image>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="px-18rpx py-37rpx flex items-center justify-between"
|
<view class="px-18rpx py-37rpx flex items-center justify-between"
|
||||||
@click="navigateTo('/pages-user/pages/edit-nickname/index')">
|
@click="navigateTo('/pages-user/pages/edit-nickname/index')">
|
||||||
<view class="shrink-0 mr-20rpx text-30rpx text-primary">{{ t('pages-user.user-info.nickname') }}</view>
|
<view class="shrink-0 mr-20rpx text-30rpx text-primary">{{ t('pages-user.user-info.nickname') }}</view>
|
||||||
<view class="flex-1 flex items-center justify-end text-30rpx text-primary">
|
<view class="flex-1 flex items-center justify-end text-30rpx text-primary">
|
||||||
<text>{{ `${userStore.userInfo.firstName} ${userStore.userInfo.surname}` }}</text>
|
<text>{{ `${userStore.userInfo.firstName} ${userStore.userInfo.surname}` }}</text>
|
||||||
<image
|
<image src="@img/chef/100202.png" class="shrink-0 ml-16rpx w-22rpx h-30rpx"></image>
|
||||||
src="@img/chef/100202.png"
|
|
||||||
class="shrink-0 ml-16rpx w-22rpx h-30rpx"
|
|
||||||
></image>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
<view class="mt-318rpx px-30rpx">
|
<view class="mt-318rpx px-30rpx" style="position: fixed; bottom: 30rpx; left: 0; right: 0; z-index: 100;">
|
||||||
<wd-button custom-class="!h-108rpx !text-36rpx font-bold !rounded-16rpx" block @click="handleSubmit">
|
<wd-button custom-class="!h-108rpx !text-36rpx font-bold !rounded-46rpx" block @click="handleSubmit">
|
||||||
{{ t('common.save') }}
|
{{ t('common.save') }}
|
||||||
</wd-button>
|
</wd-button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,48 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="mine-skeleton">
|
<view class="mine-skeleton-page">
|
||||||
<!-- 用户信息区域 -->
|
<!-- 顶部用户信息(对应新布局) -->
|
||||||
<view class="user-info-section flex-center-sb">
|
<view class="sk-header">
|
||||||
<view class="user-name-skeleton skeleton-item"></view>
|
<view class="sk-header__left">
|
||||||
<view class="user-avatar-skeleton skeleton-item"></view>
|
<view class="sk-name skeleton-item"></view>
|
||||||
</view>
|
<view class="sk-sub-row">
|
||||||
|
<view class="sk-sub-text skeleton-item"></view>
|
||||||
<!-- 统计卡片区域 -->
|
<view class="sk-badge skeleton-item"></view>
|
||||||
<view class="stats-section">
|
|
||||||
<view class="stats-list">
|
|
||||||
<view
|
|
||||||
v-for="i in 3"
|
|
||||||
:key="i"
|
|
||||||
class="stat-card-skeleton skeleton-item"
|
|
||||||
>
|
|
||||||
<view class="stat-number-skeleton skeleton-item"></view>
|
|
||||||
<view class="stat-label-skeleton skeleton-item"></view>
|
|
||||||
</view>
|
</view>
|
||||||
|
<view class="sk-date skeleton-item"></view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="sk-avatar skeleton-item"></view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 会员横幅区域 -->
|
<!-- 三项数据胶囊卡 -->
|
||||||
<view class="member-banner-section">
|
<view class="sk-stats skeleton-item">
|
||||||
<view class="member-banner-skeleton skeleton-item">
|
<view class="sk-stats__cell" v-for="i in 3" :key="i">
|
||||||
<view class="banner-content">
|
<view class="sk-num skeleton-item"></view>
|
||||||
<view class="banner-title-skeleton skeleton-item"></view>
|
<view class="sk-label skeleton-item"></view>
|
||||||
<view class="banner-subtitle-skeleton skeleton-item"></view>
|
|
||||||
</view>
|
|
||||||
<view class="banner-icon-skeleton skeleton-item"></view>
|
|
||||||
</view>
|
</view>
|
||||||
|
<view class="sk-divider" v-if="true"></view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 菜单列表区域 -->
|
<!-- 会员横幅 -->
|
||||||
<view class="menu-section">
|
<view class="sk-banner skeleton-item">
|
||||||
<view class="menu-list">
|
<view class="sk-banner__title skeleton-item"></view>
|
||||||
<view
|
<view class="sk-banner__sub skeleton-item"></view>
|
||||||
v-for="i in 9"
|
</view>
|
||||||
:key="i"
|
|
||||||
class="menu-item-skeleton"
|
<!-- 菜单列表卡片 -->
|
||||||
>
|
<view class="sk-menu">
|
||||||
<view class="menu-icon-skeleton skeleton-item"></view>
|
<view class="sk-menu__row" v-for="i in 9" :key="i">
|
||||||
<view class="menu-text-skeleton skeleton-item"></view>
|
<view class="sk-menu__left">
|
||||||
<view class="menu-arrow-skeleton skeleton-item"></view>
|
<view class="sk-menu__icon skeleton-item"></view>
|
||||||
|
<view class="sk-menu__text skeleton-item"></view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="sk-menu__arrow skeleton-item"></view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -70,161 +63,166 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mine-skeleton {
|
.mine-skeleton-page {
|
||||||
background-color: #fff;
|
background-color: #f5f5f5;
|
||||||
padding: 0 30rpx;
|
padding: 0 30rpx 30rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户信息区域
|
.sk-header {
|
||||||
.user-info-section {
|
padding-top: 32rpx;
|
||||||
padding: 36rpx 0 0;
|
padding-bottom: 28rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 20rpx;
|
justify-content: space-between;
|
||||||
|
gap: 24rpx;
|
||||||
|
|
||||||
.user-avatar-skeleton {
|
&__left {
|
||||||
width: 130rpx;
|
flex: 1;
|
||||||
height: 130rpx;
|
min-width: 0;
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-name-skeleton {
|
|
||||||
width: 233rpx;
|
|
||||||
height: 56rpx;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 统计卡片区域
|
|
||||||
.stats-section {
|
|
||||||
padding: 90rpx 0 0;
|
|
||||||
|
|
||||||
.stats-list {
|
|
||||||
display: flex;
|
|
||||||
gap: 36rpx;
|
|
||||||
|
|
||||||
.stat-card-skeleton {
|
|
||||||
flex: 1;
|
|
||||||
height: 194rpx;
|
|
||||||
border-radius: 24rpx;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
gap: 20rpx;
|
|
||||||
|
|
||||||
.stat-number-skeleton {
|
|
||||||
width: 80rpx;
|
|
||||||
height: 44rpx;
|
|
||||||
border-radius: 6rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-label-skeleton {
|
|
||||||
width: 120rpx;
|
|
||||||
height: 28rpx;
|
|
||||||
border-radius: 6rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 会员横幅区域
|
|
||||||
.member-banner-section {
|
|
||||||
padding: 40rpx 0 0;
|
|
||||||
|
|
||||||
.member-banner-skeleton {
|
|
||||||
width: 690rpx;
|
|
||||||
height: 152rpx;
|
|
||||||
border-radius: 24rpx;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 28rpx;
|
|
||||||
|
|
||||||
.banner-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 12rpx;
|
|
||||||
|
|
||||||
.banner-title-skeleton {
|
|
||||||
width: 457rpx;
|
|
||||||
height: 57rpx;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner-subtitle-skeleton {
|
|
||||||
width: 497rpx;
|
|
||||||
height: 48rpx;
|
|
||||||
border-radius: 6rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner-icon-skeleton {
|
|
||||||
width: 80rpx;
|
|
||||||
height: 80rpx;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 菜单列表区域
|
|
||||||
.menu-section {
|
|
||||||
padding: 80rpx 0 0;
|
|
||||||
|
|
||||||
.menu-list {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0;
|
|
||||||
|
|
||||||
.menu-item-skeleton {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 22rpx 0;
|
|
||||||
// border-bottom: 1rpx solid #f0f0f0;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-icon-skeleton {
|
|
||||||
width: 44rpx;
|
|
||||||
height: 44rpx;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
margin-right: 20rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-text-skeleton {
|
|
||||||
flex: 1;
|
|
||||||
height: 30rpx;
|
|
||||||
border-radius: 6rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-arrow-skeleton {
|
|
||||||
width: 22rpx;
|
|
||||||
height: 30rpx;
|
|
||||||
border-radius: 4rpx;
|
|
||||||
margin-left: 20rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 响应式设计
|
.sk-name {
|
||||||
@media (max-width: 750rpx) {
|
width: 420rpx;
|
||||||
.stats-list {
|
height: 44rpx;
|
||||||
flex-direction: column;
|
border-radius: 10rpx;
|
||||||
gap: 20rpx;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.member-banner-skeleton {
|
.sk-sub-row {
|
||||||
flex-direction: column;
|
margin-top: 12rpx;
|
||||||
gap: 20rpx;
|
display: flex;
|
||||||
padding: 20rpx;
|
align-items: center;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.banner-content {
|
.sk-sub-text {
|
||||||
align-items: center;
|
width: 200rpx;
|
||||||
text-align: center;
|
height: 22rpx;
|
||||||
}
|
border-radius: 999rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-badge {
|
||||||
|
width: 120rpx;
|
||||||
|
height: 22rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-date {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
width: 360rpx;
|
||||||
|
height: 22rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-avatar {
|
||||||
|
width: 130rpx;
|
||||||
|
height: 130rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-stats {
|
||||||
|
margin-top: 24rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
border-radius: 60rpx;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 12rpx 30rpx rgba(0, 0, 0, 0.06);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-stats__cell {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-num {
|
||||||
|
width: 70rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-label {
|
||||||
|
width: 90rpx;
|
||||||
|
height: 20rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-divider {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-banner {
|
||||||
|
margin-top: 24rpx;
|
||||||
|
height: 152rpx;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fff;
|
||||||
|
padding: 22rpx 28rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-banner__title {
|
||||||
|
width: 420rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-banner__sub {
|
||||||
|
width: 520rpx;
|
||||||
|
height: 20rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-menu {
|
||||||
|
margin-top: 14rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-menu__row {
|
||||||
|
padding: 28rpx 24rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: 1rpx solid #efefef;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sk-menu__left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-menu__icon {
|
||||||
|
width: 44rpx;
|
||||||
|
height: 44rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-menu__text {
|
||||||
|
width: 240rpx;
|
||||||
|
height: 26rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sk-menu__arrow {
|
||||||
|
width: 22rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -173,7 +173,7 @@ defineExpose({
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view
|
<view
|
||||||
class="bg-#fff"
|
class="view-bg"
|
||||||
:style="[
|
:style="[
|
||||||
{
|
{
|
||||||
height: configStore.windowHeight + 'px',
|
height: configStore.windowHeight + 'px',
|
||||||
@@ -194,127 +194,103 @@ defineExpose({
|
|||||||
v-show="!loading"
|
v-show="!loading"
|
||||||
class="animate-in fade-in animate-ease-in animate-duration-300"
|
class="animate-in fade-in animate-ease-in animate-duration-300"
|
||||||
>
|
>
|
||||||
<view class="px-30rpx">
|
<view class="mine-page ">
|
||||||
<view
|
<!-- 顶部用户信息 -->
|
||||||
@click="navigateTo('/pages-user/pages/user-info/index')"
|
<view class="mine-header" @click="navigateTo('/pages-user/pages/user-info/index')">
|
||||||
class="flex-center-sb mt-32rpx mb-82rpx"
|
<view class="mine-header__left">
|
||||||
>
|
<text class="mine-header__name">
|
||||||
<!-- <text class="text-56rpx text-#333 leading-56rpx font-bold tracking-[.04em]"-->
|
{{
|
||||||
<!-- >{{ userStore.isLogin ? `${userStore.userInfo.firstName} ${userStore.userInfo.surname}` : t('common.pleaseLogin') }}-->
|
userStore.isLogin
|
||||||
<!-- </text>-->
|
? ([userStore.userInfo.firstName, userStore.userInfo.surname].filter(Boolean).join(' ') ||
|
||||||
|
t('common.unknownUser'))
|
||||||
<text
|
|
||||||
class="text-56rpx text-#333 leading-56rpx font-bold tracking-[.04em]"
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
userStore.isLogin
|
|
||||||
? ([userStore.userInfo.firstName, userStore.userInfo.surname].filter(Boolean).join(' ') || t('common.unknownUser'))
|
|
||||||
: t('common.pleaseLogin')
|
: t('common.pleaseLogin')
|
||||||
}}
|
}}
|
||||||
</text>
|
</text>
|
||||||
|
<view class="mine-header__sub" v-if="userStore.isLogin">
|
||||||
|
<text class="mine-header__member">{{ Config.appName }} {{ t('pages.mine.member') }}</text>
|
||||||
|
<view class="mine-header__badge" v-if="!isUserMember">
|
||||||
|
{{ t('pages.mine.openMember') }}
|
||||||
|
</view>
|
||||||
|
<text class="mine-header__chev">›</text>
|
||||||
|
</view>
|
||||||
|
<text class="mine-header__date" v-if="isUserMember && userStore.userInfo.userMembershipVo?.expireTime">
|
||||||
|
{{ t('common.expireTime') }}:{{ formatTimestampWithMonthName(userStore.userInfo.userMembershipVo?.expireTime) }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
<image
|
<image
|
||||||
v-if="userStore.isLogin"
|
v-if="userStore.isLogin"
|
||||||
:src="userStore.userInfo.avatar"
|
:src="userStore.userInfo.avatar"
|
||||||
class="w-130rpx h-130rpx rounded-50%"
|
class="mine-header__avatar"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
/>
|
|
||||||
<image
|
|
||||||
v-else
|
|
||||||
class="w-130rpx h-130rpx rounded-50%"
|
|
||||||
mode="aspectFill"
|
|
||||||
src="@img/chef/default_avatar.png"
|
|
||||||
/>
|
/>
|
||||||
|
<image v-else class="mine-header__avatar" mode="aspectFill" src="@img/chef/default_avatar.png" />
|
||||||
</view>
|
</view>
|
||||||
<view class="flex-center-sb mb-36rpx">
|
|
||||||
<view
|
<!-- 三项数据胶囊卡 -->
|
||||||
@click="navigateTo('/pages-user/pages/collection/index')"
|
<view class="mine-stats">
|
||||||
class="flex-1 flex-col center bg-#F6F6F6 rounded-24rpx h-194rpx"
|
<view class="mine-stats__item" @click="navigateTo('/pages-user/pages/collection/index')">
|
||||||
>
|
<text class="mine-stats__num">{{ userStore.userInfo.collectNum || 0 }}</text>
|
||||||
<view
|
<text class="mine-stats__label">{{ t('pages.mine.collection') }}</text>
|
||||||
class="text-44rpx text-#333 leading-44rpx font-bold mb-24rpx"
|
|
||||||
>{{ userStore.userInfo.collectNum || 0 }}</view
|
|
||||||
>
|
|
||||||
<view class="text-28rpx text-#333 leading-28rpx tracking-[.04em]">{{
|
|
||||||
t("pages.mine.collection")
|
|
||||||
}}</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view class="mine-stats__divider" />
|
||||||
@click="navigateTo('/pages-user/pages/balance/index')"
|
<view class="mine-stats__item" @click="navigateTo('/pages-user/pages/balance/index')">
|
||||||
class="flex-1 mx-32rpx flex-col center bg-#F6F6F6 rounded-24rpx h-194rpx"
|
<text class="mine-stats__num">{{ userStore.userInfo?.balance || 0 }}</text>
|
||||||
>
|
<text class="mine-stats__label">{{ t('pages.mine.wallet') }}</text>
|
||||||
<view
|
|
||||||
class="text-44rpx text-#333 leading-44rpx font-bold mb-24rpx"
|
|
||||||
>{{ userStore.userInfo?.balance || 0 }}</view
|
|
||||||
>
|
|
||||||
<view class="text-28rpx text-#333 leading-28rpx tracking-[.04em]">{{
|
|
||||||
t("pages.mine.wallet")
|
|
||||||
}}</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view class="mine-stats__divider" />
|
||||||
@click="changeOrderFn"
|
<view class="mine-stats__item" @click="changeOrderFn">
|
||||||
class="flex-1 flex-col center bg-#F6F6F6 rounded-24rpx h-194rpx"
|
<text class="mine-stats__num">{{ userStore.userInfo.orderNum || 0 }}</text>
|
||||||
>
|
<text class="mine-stats__label">{{ t('pages.mine.order') }}</text>
|
||||||
<view
|
|
||||||
class="text-44rpx text-#333 leading-44rpx font-bold mb-24rpx"
|
|
||||||
>{{ userStore.userInfo.orderNum || 0 }}</view
|
|
||||||
>
|
|
||||||
<view class="text-28rpx text-#333 leading-28rpx tracking-[.04em]">{{
|
|
||||||
t("pages.mine.order")
|
|
||||||
}}</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<template v-if="isUserMember">
|
<template v-if="isUserMember">
|
||||||
<view @click="navigateTo('/pages-user/pages/member/index')" class="w-full h-152rpx relative mb-52rpx">
|
<view @click="navigateTo('/pages-user/pages/member/index')" class="member-banner">
|
||||||
<image src="@img/chef/100203.png" class="w-full h-full absolute top-0 left-0"></image>
|
<image src="@img/chef/100203.png" class="member-banner__bg"></image>
|
||||||
<view class="pl-28rpx py-22rpx pr-165rpx relative z-1 h-full flex flex-col justify-between">
|
<view class="member-banner__content">
|
||||||
<view class="text-40rpx text-#333 font-bold">
|
<view class="member-banner__title">{{ Config.appName }}</view>
|
||||||
{{ Config.appName }}
|
<view class="member-banner__sub">
|
||||||
</view>
|
|
||||||
<view class="text-24rpx lh-24rpx text-#935D04 tracking-[.08em]">
|
|
||||||
{{ t('common.expireTime') }}:{{ formatTimestampWithMonthName(userStore.userInfo.userMembershipVo?.expireTime) }}
|
{{ t('common.expireTime') }}:{{ formatTimestampWithMonthName(userStore.userInfo.userMembershipVo?.expireTime) }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<view @click="navigateTo('/pages-user/pages/member/index')" class="w-full h-152rpx relative mb-52rpx">
|
<view @click="navigateTo('/pages-user/pages/member/index')" class="member-banner">
|
||||||
<image src="@img/chef/100203.png" class="w-full h-full absolute top-0 left-0"></image>
|
<image src="@img/chef/100203.png" class="member-banner__bg"></image>
|
||||||
<view class="pl-28rpx py-22rpx pr-165rpx relative z-1 h-full flex flex-col justify-between">
|
<view class="member-banner__content">
|
||||||
<view class="text-40rpx text-#333 font-bold">
|
<view class="member-banner__title">
|
||||||
<!--用户没有试用过会员-->
|
|
||||||
<template v-if="!userStore.userInfo.userMembershipVo">{{ t('pages.mine.member-title') }}</template>
|
<template v-if="!userStore.userInfo.userMembershipVo">{{ t('pages.mine.member-title') }}</template>
|
||||||
<template v-else>{{ t('pages.mine.join') }} {{ Config.appName }}</template>
|
<template v-else>{{ t('pages.mine.join') }} {{ Config.appName }}</template>
|
||||||
</view>
|
</view>
|
||||||
<view class="text-24rpx lh-24rpx text-#935D04 tracking-[.08em]">{{ t('pages.mine.member-desc') }}</view>
|
<view class="member-banner__sub">{{ t('pages.mine.member-desc') }}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<view style="height: 30rpx;background-color: #f5f5f5;" />
|
||||||
|
|
||||||
<view
|
<!-- 菜单列表卡片 -->
|
||||||
class="flex-center-sb py-28rpx bg-#fff"
|
<view class="mine-menu">
|
||||||
v-for="(item, index) in tabBarList"
|
<view
|
||||||
:key="item.code"
|
class="mine-menu__row"
|
||||||
:class="[
|
v-for="(item, index) in tabBarList"
|
||||||
index === tabBarList.length - 1 ? 'mb-58rpx' : 'border-bottom',
|
:key="item.code"
|
||||||
]"
|
:class="[index === tabBarList.length - 1 ? 'mine-menu__row--last' : '']"
|
||||||
@click="handleTabClick(item)"
|
@click="handleTabClick(item)"
|
||||||
>
|
>
|
||||||
<view class="flex items-center">
|
<view class="mine-menu__left">
|
||||||
<image
|
<image class="mine-menu__icon" :src="item.iconPath"></image>
|
||||||
class="w-44rpx h-44rpx shrink-0 mr-18rpx"
|
<text class="mine-menu__text">{{ item.text }}</text>
|
||||||
:src="item.iconPath"
|
</view>
|
||||||
></image>
|
<image class="mine-menu__arrow" src="@img/chef/100202.png"></image>
|
||||||
<text class="text-30rpx text-primary font-500 lh-30rpx tracking-[.04em]">{{
|
|
||||||
item.text
|
|
||||||
}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center shrink-0 ml-20rpx">
|
|
||||||
<image class="w-22rpx h-30rpx" src="@img/chef/100202.png"></image>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<view class="mine-bottom-spacer" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<template #bottom>
|
<template #bottom>
|
||||||
<view class="h-50px"></view>
|
<view class="h-50px"></view>
|
||||||
@@ -325,7 +301,229 @@ defineExpose({
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.border-bottom {
|
.view-bg {
|
||||||
border-bottom: 1rpx solid #dfdfdf;
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mine-page {
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mine-header {
|
||||||
|
margin: 0 30rpx;
|
||||||
|
padding: 32rpx 0 28rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
&__left {
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__name {
|
||||||
|
font-size: 38rpx;
|
||||||
|
line-height: 40rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #333;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
max-width: 520rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__sub {
|
||||||
|
margin-top: 12rpx;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
color: #b68b3e;
|
||||||
|
font-size: 22rpx;
|
||||||
|
line-height: 22rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__member {
|
||||||
|
color: #b68b3e;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__badge {
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: rgba(182, 139, 62, 0.12);
|
||||||
|
color: #b68b3e;
|
||||||
|
font-size: 20rpx;
|
||||||
|
line-height: 20rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__chev {
|
||||||
|
transform: translateY(-1rpx);
|
||||||
|
color: #b68b3e;
|
||||||
|
font-size: 24rpx;
|
||||||
|
line-height: 22rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__date {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
line-height: 22rpx;
|
||||||
|
color: #999;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__avatar {
|
||||||
|
width: 90rpx;
|
||||||
|
height: 90rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mine-stats {
|
||||||
|
margin: 15rpx 35rpx;
|
||||||
|
// margin-top: 24rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 36rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
box-shadow: 0 12rpx 30rpx rgba(10, 10, 10, 0.06);
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&__num {
|
||||||
|
font-size: 32rpx;
|
||||||
|
line-height: 30rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-size: 26rpx;
|
||||||
|
line-height: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
// font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__divider {
|
||||||
|
width: 1rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
background: #eaeaea;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.member-banner {
|
||||||
|
margin: 15rpx 30rpx;
|
||||||
|
height: 152rpx;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 36rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__bg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
height: 100%;
|
||||||
|
padding: 22rpx 165rpx 22rpx 28rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
line-height: 32rpx;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__sub {
|
||||||
|
font-size: 20rpx;
|
||||||
|
line-height: 20rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #935d04;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mine-menu {
|
||||||
|
margin:20rpx 30rpx 30rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__row {
|
||||||
|
padding: 28rpx 24rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: 1rpx solid #efefef;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__row--last {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__left {
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
width: 44rpx;
|
||||||
|
height: 44rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
line-height: 26rpx;
|
||||||
|
color: #333;
|
||||||
|
// font-weight: 600;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__arrow {
|
||||||
|
width: 22rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mine-bottom-spacer {
|
||||||
|
height: 58rpx;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user