Browse Source

Merge branch 'wangyi/feature-20251022162725-启动页登录注册' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into dongqian/feature-20251022181325-deepmate简版

wangyi/feature-20251022162725-启动页登录注册
wangyetao 4 weeks ago
parent
commit
6fc67da169
  1. 9
      pages.json
  2. 284
      pages/start/Registration/Registration.vue
  3. 1341
      pages/start/Registration/list.js
  4. 259
      pages/start/login/login.vue
  5. 69
      pages/start/login/verification.js
  6. 985
      pages/start/recoverPassword/recoverPassword.vue
  7. 47
      pages/start/select/select.vue
  8. 4
      pages/start/startup/startup.vue
  9. BIN
      static/icons/To.png
  10. BIN
      static/icons/back.png
  11. BIN
      static/icons/look.png
  12. BIN
      static/icons/start-logo.png
  13. BIN
      static/icons/unlook.png
  14. BIN
      static/select.png
  15. BIN
      static/start-logo.png
  16. 18
      uni_modules/uni-popup/changelog.md
  17. 28
      uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue
  18. 9
      uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue
  19. 27
      uni_modules/uni-popup/components/uni-popup/uni-popup.vue
  20. 83
      uni_modules/uni-popup/package.json
  21. 7
      uni_modules/uni-transition/changelog.md
  22. 72
      uni_modules/uni-transition/components/uni-transition/uni-transition.vue
  23. 103
      uni_modules/uni-transition/package.json

9
pages.json

@ -137,6 +137,15 @@
"navigationStyle": "custom", "navigationStyle": "custom",
"titleNView": false "titleNView": false
} }
},
{
"path" : "pages/start/recoverPassword/recoverPassword",
"style" :
{
"navigationBarTitleText": "",
"navigationStyle": "custom",
"titleNView": false
}
} }
], ],
"globalStyle": { "globalStyle": {

284
pages/start/Registration/Registration.vue

@ -145,17 +145,23 @@
> >
</view> </view>
<!-- 注册按钮 --> <!-- 注册按钮 -->
<button class="register-btn" @click="register">注册</button> <button class="register-btn" @click="register">注册</button>
<!-- 或者 --> <!-- 或者 -->
<text class="or-text" @click="goToLogin"
>已有账号登录
</text>
<text class="or-text" @click="goToLogin">已有账号登录 </text>
<!-- 同意弹窗 -->
<uniPopup ref="agreementPopup" type="dialog">
<view class="popup-content">
<text class="popup-title">同意并继续</text>
<text class="popup-message">请阅读并同意服务协议和隐私权限</text>
<button class="agree-button" @click="handleAgree">
<text class="agree-text">同意</text>
</button>
</view>
</uniPopup>
<footerBar class="static-footer" :type="type"></footerBar> <footerBar class="static-footer" :type="type"></footerBar>
</view> </view>
</template> </template>
@ -163,15 +169,17 @@
import { ref } from "vue"; import { ref } from "vue";
// //
import countryList from "../login/list"; import countryList from "../login/list";
import footerBar from '../../../components/footerBar-cn.vue'
import footerBar from "../../../components/footerBar-cn.vue";
import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue";
import { verificationPhone, verificationEmail } from "../login/verification";
const type = ref('member')
const type = ref("member");
const email = ref(""); const email = ref("");
const password = ref(""); const password = ref("");
const phone = ref(""); const phone = ref("");
const country = ref("+86");
const agreed = ref(false); const agreed = ref(false);
const switchType = ref("Email"); //
const switchType = ref("Phone"); //
const { safeAreaInsets } = uni.getSystemInfoSync(); const { safeAreaInsets } = uni.getSystemInfoSync();
const codeBtnText = ref("获取验证码"); const codeBtnText = ref("获取验证码");
const isCodeBtnDisabled = ref(false); // const isCodeBtnDisabled = ref(false); //
@ -223,7 +231,63 @@ function switchPhone() {
switchType.value = "Phone"; switchType.value = "Phone";
} }
// function register() {
// if (switchType.value === "Email") {
// //
// if (!email.value) {
// uni.showToast({
// title: "",
// icon: "none",
// });
// return;
// }
// //
// console.log(":", email.value);
// }
// if (switchType.value === "Phone") {
// //
// if (!phone.value) {
// uni.showToast({
// title: "",
// icon: "none",
// });
// return;
// }
// //
// console.log(":", phone.value);
// }
// }
function register() { function register() {
if (switchType.value === "Phone") {
//
if (!phone.value) {
uni.showToast({
title: "请输入手机号码",
icon: "none",
});
return;
}
if (!password.value) {
uni.showToast({
title: "请输入验证码",
icon: "none",
});
return;
}
const phoneAll = `${country.value}${phone.value}`;
console.log("完整手机号" + phoneAll);
if (validatePhoneNumber(country.value, phone.value)) {
console.log("登录成功:", phoneAll);
}
//
// console.log(":", phone.value);
}
if (switchType.value === "Email") { if (switchType.value === "Email") {
// //
if (!email.value) { if (!email.value) {
@ -234,26 +298,42 @@ function register() {
return; return;
} }
//
console.log("登录:", email.value);
if (!password.value) {
uni.showToast({
title: "请输入验证码",
icon: "none",
});
return;
} }
if (switchType.value === "Phone") {
//
if (!phone.value) {
const bool = verificationEmail(email.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({ uni.showToast({
title: "请输入手机号码",
title: "邮箱格式不正确",
icon: "none", icon: "none",
}); });
return; return;
} }
// //
console.log("登录:", phone.value);
}
console.log("登录:", email.value);
} }
if (!agreed.value) {
//
agreementPopup.value.open();
return;
}
//
// uni.showToast({
// title: "",
// icon: "success",
// });
}
function goToLogin() { function goToLogin() {
// //
@ -273,7 +353,72 @@ function onPhoneInput(e) {
} }
} }
// function sendCode() {
// //
// if (isCodeBtnDisabled.value) return;
// //
// isCodeBtnDisabled.value = true;
// codeBtnText.value = "";
// let time = 6;
// const timer = setInterval(() => {
// time--;
// codeBtnText.value = " " + time + "S";
// if (time <= 0) {
// clearInterval(timer);
// codeBtnText.value = "";
// //
// isCodeBtnDisabled.value = false;
// }
// }, 1000);
// return;
// }
function sendCode() { function sendCode() {
if (switchType.value === "Phone") {
if (!phone.value) {
uni.showToast({
title: "请输入手机号",
icon: "none",
});
return;
}
const bool = verificationPhone(country.value, phone.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "手机号格式不正确",
icon: "none",
});
return;
}
}
if (switchType.value === "Email") {
if (!email.value) {
uni.showToast({
title: "请输入邮箱地址",
icon: "none",
});
return;
}
const bool = verificationEmail(email.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "邮箱格式不正确",
icon: "none",
});
return;
}
}
// //
if (isCodeBtnDisabled.value) return; if (isCodeBtnDisabled.value) return;
@ -311,13 +456,61 @@ function openPrivacy() {
}); });
} }
function changeCheckbox() { function changeCheckbox() {
agreed.value = !agreed.value; agreed.value = !agreed.value;
checkboxUrl.value = agreed.value checkboxUrl.value = agreed.value
? "../../../static/icons/Check-one-true.png" ? "../../../static/icons/Check-one-true.png"
: "../../../static/icons/Check-one-false.png"; : "../../../static/icons/Check-one-false.png";
} }
//
function validatePhoneNumber(countryCode, phoneNumber) {
//
if (!phoneNumber || phoneNumber.trim() === "") {
uni.showToast({
title: "手机号不能为空",
icon: "none",
});
return false;
}
const bool = verificationPhone(countryCode, phoneNumber);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "手机号格式不正确",
icon: "none",
});
return false;
}
// +715
const cleanNumber = phoneNumber.replace(/^\+/, "");
if (cleanNumber.length < 7 || cleanNumber.length > 15) {
uni.showToast({
title: "手机号长度不正确",
icon: "none",
});
return false;
}
return true;
}
//
const agreementPopup = ref(null);
//
function handleAgree() {
//
agreementPopup.value.close();
//
agreed.value = true;
checkboxUrl.value = "../../../static/icons/Check-one-true.png";
//
}
</script> </script>
<style scoped> <style scoped>
@ -604,7 +797,8 @@ function changeCheckbox() {
flex-direction: column; flex-direction: column;
font-size: 24rpx; font-size: 24rpx;
color: #999999; color: #999999;
margin-bottom: 100rpx;
margin-top: 330rpx;
margin-bottom: -22rpx;
} }
.third-party-login { .third-party-login {
@ -661,4 +855,54 @@ function changeCheckbox() {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
} }
/* 弹窗样式 */
.popup-content {
background-color: #ffffff;
padding: 40rpx;
text-align: center;
border-radius: 10rpx;
width: 550rpx;
}
.popup-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 80rpx;
text-align: center; /* 水平居中 */
display: flex; /* 使用flex布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
.popup-message {
font-size: 28rpx;
color: #000000;
margin-bottom: 80rpx;
text-align: center; /* 水平居中 */
display: flex; /* 使用flex布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
.agree-button {
width: 300rpx;
height: 80rpx;
background-color: #000000;
border-radius: 40rpx;
display: flex; /* 添加flex布局 */
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
}
.agree-text {
color: #ffffff;
font-size: 34rpx;
/* 添加垂直居中相关样式 */
display: flex;
align-items: center;
justify-content: center;
line-height: 1; /* 确保文字垂直居中 */
}
</style> </style>

1341
pages/start/Registration/list.js
File diff suppressed because it is too large
View File

259
pages/start/login/login.vue

@ -63,7 +63,7 @@
class="input-field" class="input-field"
type="text" type="text"
placeholder="请输入DeepChart ID" placeholder="请输入DeepChart ID"
v-model="email"
v-model="deepChartID"
/> />
</view> </view>
<view class="input-with-icon"> <view class="input-with-icon">
@ -195,7 +195,8 @@
<!-- 或者 --> <!-- 或者 -->
<text class="or-text" @click="goToRegistration" <text class="or-text" @click="goToRegistration"
>如果您还没有账号点击注册 >
>如果您还没有账号点击注册
<image class="to-icon" src="../../../static/icons/To.png"></image>
</text> </text>
<!-- 第三方登录 --> <!-- 第三方登录 -->
@ -218,6 +219,17 @@
<text class="third-party-text">通过 Google 登录</text> <text class="third-party-text">通过 Google 登录</text>
</view> </view>
</view> </view>
<!-- 同意弹窗 -->
<uniPopup ref="agreementPopup" type="dialog">
<view class="popup-content">
<text class="popup-title">同意并继续</text>
<text class="popup-message">请阅读并同意服务协议和隐私权限</text>
<button class="agree-button" @click="handleAgree">
<text class="agree-text">同意</text>
</button>
</view>
</uniPopup>
<footerBar class="static-footer" :type="type"></footerBar> <footerBar class="static-footer" :type="type"></footerBar>
</view> </view>
</template> </template>
@ -226,14 +238,19 @@
import { ref } from "vue"; import { ref } from "vue";
// //
import countryList from "./list.js"; import countryList from "./list.js";
import footerBar from '../../../components/footerBar-cn'
import footerBar from "../../../components/footerBar-cn";
import uniPopupDialogVue from "../../../uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue";
import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue";
import { verificationPhone, verificationEmail } from "../login/verification";
const type = ref('member')
const deepChartID = ref("");
const type = ref("member");
const email = ref(""); const email = ref("");
const password = ref(""); const password = ref("");
const country = ref("+86");
const phone = ref(""); const phone = ref("");
const agreed = ref(false); const agreed = ref(false);
const switchType = ref("Email"); //
const switchType = ref("User"); //
const { safeAreaInsets } = uni.getSystemInfoSync(); const { safeAreaInsets } = uni.getSystemInfoSync();
const codeBtnText = ref("获取验证码"); const codeBtnText = ref("获取验证码");
const isCodeBtnDisabled = ref(false); // const isCodeBtnDisabled = ref(false); //
@ -264,6 +281,7 @@ function showCountryPicker() {
), ),
success: function (res) { success: function (res) {
selectedCountry.value = countries.value[res.tapIndex]; selectedCountry.value = countries.value[res.tapIndex];
country.value = selectedCountry.value.code;
}, },
}); });
} }
@ -278,31 +296,38 @@ function goToIndex() {
function switchUser() { function switchUser() {
// //
switchType.value = "User"; switchType.value = "User";
password.value = "";
} }
function switchEmail() { function switchEmail() {
// //
switchType.value = "Email"; switchType.value = "Email";
password.value = "";
} }
function switchPhone() { function switchPhone() {
// //
switchType.value = "Phone"; switchType.value = "Phone";
password.value = "";
} }
function register() { function register() {
if (switchType.value === "Email") {
//
if (!email.value) {
if (switchType.value === "User") {
if (!deepChartID.value) {
uni.showToast({ uni.showToast({
title: "请输入邮箱地址",
title: "请输入用户名",
icon: "none", icon: "none",
}); });
return; return;
} }
//
console.log("登录:", email.value);
if (!password.value) {
uni.showToast({
title: "请输入密码",
icon: "none",
});
return;
}
} }
if (switchType.value === "Phone") { if (switchType.value === "Phone") {
@ -315,9 +340,81 @@ function register() {
return; return;
} }
if (!password.value) {
uni.showToast({
title: "请输入验证码",
icon: "none",
});
return;
}
const phoneAll = `${country.value}${phone.value}`;
console.log("完整手机号" + phoneAll);
if (validatePhoneNumber(country.value, phone.value)) {
console.log("登录成功:", phoneAll);
}
// //
console.log("登录:", phone.value);
// console.log(":", phone.value);
} }
if (switchType.value === "Email") {
//
if (!email.value) {
uni.showToast({
title: "请输入邮箱地址",
icon: "none",
});
return;
}
if (!password.value) {
uni.showToast({
title: "请输入验证码",
icon: "none",
});
return;
}
const bool = verificationEmail(email.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "邮箱格式不正确",
icon: "none",
});
return;
}
//
console.log("登录:", email.value);
}
if (!agreed.value) {
//
agreementPopup.value.open();
return;
}
//
// uni.showToast({
// title: "",
// icon: "success",
// });
}
//
const agreementPopup = ref(null);
//
function handleAgree() {
//
agreementPopup.value.close();
//
agreed.value = true;
checkboxUrl.value = "../../../static/icons/Check-one-true.png";
//
} }
function loginWithApple() { function loginWithApple() {
@ -383,6 +480,49 @@ function onPhoneInput(e) {
} }
function sendCode() { function sendCode() {
if (switchType.value === "Phone") {
if (!phone.value) {
uni.showToast({
title: "请输入手机号",
icon: "none",
});
return;
}
const bool = verificationPhone(country.value, phone.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "手机号格式不正确",
icon: "none",
});
return;
}
}
if (switchType.value === "Email") {
if (!email.value) {
uni.showToast({
title: "请输入邮箱地址",
icon: "none",
});
return;
}
const bool = verificationEmail(email.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "邮箱格式不正确",
icon: "none",
});
return;
}
}
// //
if (isCodeBtnDisabled.value) return; if (isCodeBtnDisabled.value) return;
@ -422,7 +562,10 @@ function openPrivacy() {
function recoverPassword() { function recoverPassword() {
// //
console.log("忘记密码");
// console.log("");
uni.navigateTo({
url: "/pages/start/recoverPassword/recoverPassword",
});
} }
function changeCheckbox() { function changeCheckbox() {
@ -431,6 +574,42 @@ function changeCheckbox() {
? "../../../static/icons/Check-one-true.png" ? "../../../static/icons/Check-one-true.png"
: "../../../static/icons/Check-one-false.png"; : "../../../static/icons/Check-one-false.png";
} }
//
function validatePhoneNumber(countryCode, phoneNumber) {
//
if (!phoneNumber || phoneNumber.trim() === "") {
uni.showToast({
title: "手机号不能为空",
icon: "none",
});
return false;
}
const bool = verificationPhone(countryCode, phoneNumber);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "手机号格式不正确",
icon: "none",
});
return false;
}
// +715
const cleanNumber = phoneNumber.replace(/^\+/, "");
if (cleanNumber.length < 7 || cleanNumber.length > 15) {
uni.showToast({
title: "手机号长度不正确",
icon: "none",
});
return false;
}
return true;
}
</script> </script>
<style scoped> <style scoped>
@ -720,6 +899,11 @@ function changeCheckbox() {
margin-bottom: 40rpx; margin-bottom: 40rpx;
} }
.to-icon{
width: 10rpx;
height: 16rpx;
}
.third-party-login { .third-party-login {
width: 100%; width: 100%;
margin-bottom: 60rpx; margin-bottom: 60rpx;
@ -774,4 +958,53 @@ function changeCheckbox() {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
} }
/* 弹窗样式 */
.popup-content {
background-color: #ffffff;
padding: 40rpx;
text-align: center;
border-radius: 10rpx;
width: 550rpx;
}
.popup-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 80rpx;
text-align: center; /* 水平居中 */
display: flex; /* 使用flex布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
.popup-message {
font-size: 28rpx;
color: #000000;
margin-bottom: 80rpx;
text-align: center; /* 水平居中 */
display: flex; /* 使用flex布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
.agree-button {
width: 300rpx;
height: 80rpx;
background-color: #000000;
border-radius: 40rpx;
display: flex; /* 添加flex布局 */
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
}
.agree-text {
color: #ffffff;
font-size: 34rpx;
/* 添加垂直居中相关样式 */
display: flex;
align-items: center;
justify-content: center;
line-height: 1; /* 确保文字垂直居中 */
}
</style> </style>

69
pages/start/login/verification.js

@ -0,0 +1,69 @@
function verificationPhone(countryCode,phoneNumber) {
switch (countryCode) {
case '+86':
return verificationChina(phoneNumber);
case '+1':
return verificationAmerica(phoneNumber);
case '+65':
return verificationSingapore(phoneNumber);
case '+60':
return verificationMalaysia(phoneNumber);
case '+66':
return verificationThailand(phoneNumber);
case '+852':
return verificationHongKong(phoneNumber);
case '+84':
return verificationVietnam(phoneNumber);
default:
return true;
}
}
function verificationChina(phoneNumber){
const phoneRegex = /^1[3-9]\d{9}$/;
return phoneRegex.test(phoneNumber);
}
function verificationAmerica(phoneNumber){
const phoneRegex = /^[2-9]\d{2}[- ]?\d{4}$/;
return phoneRegex.test(phoneNumber);
}
function verificationSingapore(phoneNumber){
const phoneRegex = /^[89]\d{7}$/;
return phoneRegex.test(phoneNumber);
}
function verificationMalaysia(phoneNumber){
const phoneRegex = /^01\d{8}$/;
return phoneRegex.test(phoneNumber);
}
function verificationHongKong(phoneNumber){
const phoneRegex = /^0[896]\d{8}$/;
return phoneRegex.test(phoneNumber);
}
function verificationThailand(phoneNumber){
const phoneRegex = /^[5-9]\d{7}$/;
return phoneRegex.test(phoneNumber);
}
function verificationVietnam(phoneNumber){
const phoneRegex = /^(0)?[3-9]\d{8}$/;
return phoneRegex.test(phoneNumber);
}
function verificationEmail(email) {
const emailRegex = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/;
return emailRegex.test(email);
}
export {verificationPhone,verificationEmail}

985
pages/start/recoverPassword/recoverPassword.vue

@ -0,0 +1,985 @@
<template>
<view class="login-registration-container">
<!-- 自定义导航栏 -->
<view
class="custom-navbar"
:style="{ paddingTop: safeAreaInsets?.top + 'px' }"
>
<view class="nav-left">
<image
class="icons"
@click="goToBack"
src="../../../static/icons/back.png"
alt="返回首页"
/>
</view>
<view class="nav-right">
<image
class="icons"
src="../../../static/icons/Headset.png"
alt="联系客服"
/>
</view>
</view>
<!-- Logo -->
<!-- <image class="logo" src="/static/logo.png" mode="aspectFit"></image> -->
<!-- 欢迎语 -->
<text class="welcome-text">找回密码</text>
<!-- 邮箱/手机号切换 -->
<view v-if="!isRecovering" class="switch-container">
<text
class="switch-item"
:class="{ active: switchType === 'Email' }"
@click="switchEmail"
>邮箱</text
>
<text
class="switch-item"
:class="{ active: switchType === 'Phone' }"
@click="switchPhone"
>手机号</text
>
</view>
<view v-else class="switch-container-occupy"> </view>
<!-- 输入框 -->
<view v-if="isRecovering" class="input-container">
<view v-if="switchType === 'Email'">
<!-- 修改邮箱输入框容器将图标包含在内 -->
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Unlock.png"
alt=""
/>
<input
class="input-field"
:type="newPasswordLookFirst ? 'text' : 'password'"
placeholder="输入新密码"
v-model="newPasswordFirst"
/>
<image
class="input-icon-eye"
@click="newPasswordLookFirst = !newPasswordLookFirst"
:src="
!newPasswordLookFirst
? '../../../static/icons/unlook.png'
: '../../../static/icons/look.png'
"
alt=""
/>
</view>
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Unlock.png"
alt=""
/>
<input
class="input-field"
:type="newPasswordLookSecond ? 'text' : 'password'"
placeholder="再次确认"
v-model="newPasswordSecond"
/>
<image
class="input-icon-eye"
@click="newPasswordLookSecond = !newPasswordLookSecond"
:src="
!newPasswordLookSecond
? '../../../static/icons/unlook.png'
: '../../../static/icons/look.png'
"
alt=""
/>
</view>
</view>
</view>
<view v-else class="input-container">
<view v-if="switchType === 'Email'">
<!-- 修改邮箱输入框容器将图标包含在内 -->
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Mail.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入邮箱"
v-model="email"
/>
<view>
<button
class="send-code-btn-email"
:disabled="isCodeBtnDisabled"
:class="{ 'send-code-btn-disabled': isCodeBtnDisabled }"
@click="sendCode"
>
<text
class="send-code-text"
:class="{ 'send-code-btn-disabled-text': isCodeBtnDisabled }"
>{{ codeBtnText }}</text
>
</button>
</view>
</view>
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Text-recognition.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入验证码"
v-model="password"
/>
</view>
</view>
<view v-if="switchType === 'Phone'" class="phone-input-container">
<view class="country-code-selector" @click="showCountryPicker">
<image
class="country-flag-img"
src="../../../static/icons/Iphone.png"
mode="aspectFit"
></image>
<text class="country-code">{{ selectedCountry.code }}</text>
<!-- <text class="arrow-down"></text> -->
</view>
<input
class="input-field phone-input"
type="number"
placeholder="输入手机号"
v-model="phone"
@input="onPhoneInput"
/>
<view>
<button
class="send-code-btn"
:disabled="isCodeBtnDisabled"
:class="{ 'send-code-btn-disabled': isCodeBtnDisabled }"
@click="sendCode"
>
<text
class="send-code-text"
:class="{ 'send-code-btn-disabled-text': isCodeBtnDisabled }"
>{{ codeBtnText }}</text
>
</button>
</view>
</view>
<view v-if="switchType === 'Phone'" class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Text-recognition.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入验证码"
v-model="password"
/>
</view>
</view>
<!-- 用户协议 -->
<view @click="changeCheckbox" class="agreement-container-one">
<text
class="agreement-text-one"
:style="!isRecovering ? 'visibility: hidden' : 'visibility: visible'"
>
密码最少8位数
</text>
</view>
<!-- 注册按钮 -->
<button class="register-btn" @click="register">
{{ isRecovering ? "确认" : "下一步" }}
</button>
<!-- 或者 -->
<text class="or-text-one" @click="goToRegistration"
>如果您还没有账号点击注册
<image class="to-icon" src="../../../static/icons/To.png"></image>
</text>
<!-- 或者 -->
<text class="or-text" @click="goToLogin">已有账号登录 </text>
<!-- 同意弹窗 -->
<uniPopup ref="agreementPopup" type="dialog">
<view class="popup-content">
<text class="popup-title">同意并继续</text>
<text class="popup-message">请阅读并同意服务协议和隐私权限</text>
<button class="agree-button" @click="handleAgree">
<text class="agree-text">同意</text>
</button>
</view>
</uniPopup>
<footerBar class="static-footer" :type="type"></footerBar>
</view>
</template>
<script setup>
import { ref } from "vue";
//
import countryList from "../login/list";
import footerBar from "../../../components/footerBar-cn.vue";
import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue";
import { verificationPhone, verificationEmail } from "../login/verification";
const type = ref("member");
const email = ref("");
const password = ref("");
const newPasswordFirst = ref("");
const newPasswordSecond = ref("");
const phone = ref("");
const country = ref("+86");
const agreed = ref(false);
const switchType = ref("Phone"); //
const { safeAreaInsets } = uni.getSystemInfoSync();
const codeBtnText = ref("获取验证码");
const isCodeBtnDisabled = ref(false); //
const checkboxUrl = ref("../../../static/icons/Check-one-false.png");
const isRecovering = ref(false);
const newPasswordLookFirst = ref(false);
const newPasswordLookSecond = ref(false);
// 使list.js
const countries = ref(
countryList.list.map((item) => ({
name: item.name,
code: `+${item.tel}`,
flag: item.flag,
short: item.short,
en: item.en,
}))
);
//
const selectedCountry = ref(
countries.value.find((country) => country.short === "CN") ||
countries.value[0]
);
//
function showCountryPicker() {
uni.showActionSheet({
itemList: countries.value.map(
(country) => `${country.name} ${country.code}`
),
success: function (res) {
selectedCountry.value = countries.value[res.tapIndex];
},
});
}
function goToBack() {
//
uni.navigateBack(-1);
}
function switchEmail() {
//
switchType.value = "Email";
}
function switchPhone() {
//
switchType.value = "Phone";
}
function register() {
if (isRecovering.value) {
if(!newPasswordFirst.value || !newPasswordSecond.value){
uni.showToast({
title: "密码不能为空",
icon: "none",
});
return;
}
if (newPasswordFirst.value !== newPasswordSecond.value) {
uni.showToast({
title: "前后密码不一致",
icon: "none",
});
return;
}
//
return;
}
if (switchType.value === "Phone") {
//
if (!phone.value) {
uni.showToast({
title: "请输入手机号码",
icon: "none",
});
return;
}
if (!password.value) {
uni.showToast({
title: "请输入验证码",
icon: "none",
});
return;
}
const phoneAll = `${country.value}${phone.value}`;
console.log("完整手机号" + phoneAll);
if (validatePhoneNumber(country.value, phone.value)) {
console.log("登录成功:", phoneAll);
}
//
// console.log(":", phone.value);
}
if (switchType.value === "Email") {
//
if (!email.value) {
uni.showToast({
title: "请输入邮箱地址",
icon: "none",
});
return;
}
if (!password.value) {
uni.showToast({
title: "请输入验证码",
icon: "none",
});
return;
}
const bool = verificationEmail(email.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "邮箱格式不正确",
icon: "none",
});
return;
}
//
console.log("登录:", email.value);
}
isRecovering.value = !isRecovering.value;
//
// uni.showToast({
// title: "",
// icon: "success",
// });
}
function goToLogin() {
//
uni.navigateTo({
url: "/pages/start/login/login",
});
}
function onPhoneInput(e) {
//
const value = e.detail.value;
// 使 isNaN
if (isNaN(value)) {
phone.value = "";
} else {
phone.value = value;
}
}
// function sendCode() {
// //
// if (isCodeBtnDisabled.value) return;
// //
// isCodeBtnDisabled.value = true;
// codeBtnText.value = "";
// let time = 6;
// const timer = setInterval(() => {
// time--;
// codeBtnText.value = " " + time + "S";
// if (time <= 0) {
// clearInterval(timer);
// codeBtnText.value = "";
// //
// isCodeBtnDisabled.value = false;
// }
// }, 1000);
// return;
// }
function sendCode() {
if (switchType.value === "Phone") {
if (!phone.value) {
uni.showToast({
title: "请输入手机号",
icon: "none",
});
return;
}
const bool = verificationPhone(country.value, phone.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "手机号格式不正确",
icon: "none",
});
return;
}
}
if (switchType.value === "Email") {
if (!email.value) {
uni.showToast({
title: "请输入邮箱地址",
icon: "none",
});
return;
}
const bool = verificationEmail(email.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "邮箱格式不正确",
icon: "none",
});
return;
}
}
//
if (isCodeBtnDisabled.value) return;
//
isCodeBtnDisabled.value = true;
codeBtnText.value = "重新发送";
let time = 6;
const timer = setInterval(() => {
time--;
codeBtnText.value = "重新发送 " + time + "s";
if (time <= 0) {
clearInterval(timer);
codeBtnText.value = "重新发送";
//
isCodeBtnDisabled.value = false;
}
}, 1000);
return;
}
function openAgreement() {
//
console.log("打开用户协议");
uni.navigateTo({
url: "/pages/start/agreement/agreement",
});
}
function openPrivacy() {
//
console.log("打开隐私政策");
uni.navigateTo({
url: "/pages/start/privacy/privacy",
});
}
function changeCheckbox() {
agreed.value = !agreed.value;
checkboxUrl.value = agreed.value
? "../../../static/icons/Check-one-true.png"
: "../../../static/icons/Check-one-false.png";
}
//
function validatePhoneNumber(countryCode, phoneNumber) {
//
if (!phoneNumber || phoneNumber.trim() === "") {
uni.showToast({
title: "手机号不能为空",
icon: "none",
});
return false;
}
const bool = verificationPhone(countryCode, phoneNumber);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "手机号格式不正确",
icon: "none",
});
return false;
}
// +715
const cleanNumber = phoneNumber.replace(/^\+/, "");
if (cleanNumber.length < 7 || cleanNumber.length > 15) {
uni.showToast({
title: "手机号长度不正确",
icon: "none",
});
return false;
}
return true;
}
//
const agreementPopup = ref(null);
//
function handleAgree() {
//
agreementPopup.value.close();
//
agreed.value = true;
checkboxUrl.value = "../../../static/icons/Check-one-true.png";
//
}
</script>
<style scoped>
.login-registration-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 70rpx;
height: 100vh;
background-color: #ffffff;
}
/* 自定义导航栏样式 */
.custom-navbar {
position: absolute;
top: 0;
left: 0;
/* z-index: 999; */
width: 90%;
height: 80rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10rpx 40rpx;
margin-bottom: 20rpx;
}
.nav-left,
.nav-right {
flex: 1;
}
.nav-right {
display: flex;
justify-content: flex-end;
}
.nav-left {
display: flex;
justify-content: flex-start;
}
.icons {
margin: 20rpx;
width: 40rpx;
height: 40rpx;
/* margin-right: 10rpx; */
}
.back-btn,
.headphone-btn {
font-size: 36rpx;
font-weight: bold;
color: #333333;
padding: 10rpx;
}
.logo {
width: 120rpx;
height: 120rpx;
margin-bottom: 60rpx;
border-radius: 20%;
}
.welcome-text {
font-size: 48rpx;
font-weight: bold;
color: #333333;
margin-bottom: 60rpx;
/* text-align: left; */
/* align-self: flex-start; */
}
.switch-container {
display: flex;
margin-bottom: 40rpx;
align-self: flex-start;
}
.switch-item {
font-size: 28rpx;
color: #999999;
padding: 10rpx 20rpx;
position: relative;
}
.switch-item::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60%;
/* 控制边框宽度 */
height: 2rpx;
background-color: transparent;
}
.switch-item.active {
color: #333333;
font-weight: 700;
}
.switch-item.active::after {
content: "";
position: absolute;
top: 60rpx;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 30%;
/* 控制边框宽度 */
height: 7rpx;
background-color: #333333;
}
.input-container {
width: 100%;
}
/* 添加图标输入框样式 */
.input-with-icon {
display: flex;
align-items: center;
width: 100%;
height: 80rpx;
border-bottom: 2rpx solid #e5e5e5;
margin-bottom: 20rpx;
}
.input-icon {
width: 40rpx;
height: 40rpx;
margin: 0 20rpx;
}
.input-icon-eye {
width: 40rpx;
height: 20rpx;
margin: 0 20rpx;
}
.input-field {
flex: 1;
height: 80rpx;
padding: 15rpx 0;
font-size: 28rpx;
color: #333333;
border: none;
background-color: transparent;
}
.phone-input-container {
display: flex;
align-items: center;
width: 95.8%;
height: 80rpx;
/* border-radius: 20rpx; */
/* border: 2rpx solid #e5e5e5; */
/* background-color: #f5f5f5; */
padding: 0 10rpx;
border-bottom: 2rpx solid #e5e5e5;
margin-bottom: 20rpx;
}
.country-code-selector {
display: flex;
align-items: center;
padding: 0 10rpx;
padding-bottom: 1rpx;
height: 100%;
/* border-right: 2rpx solid #e5e5e5; */
/* background-color: #f5f5f5; */
border-radius: 20rpx 0 0 20rpx;
}
.country-code {
font-size: 28rpx;
color: #333333;
margin-right: 10rpx;
}
.country-flag-img {
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
.arrow-down {
font-size: 20rpx;
color: #999999;
}
.phone-input {
flex: 1;
width: auto;
height: 100%;
border: none;
background-color: transparent;
padding: 0 0rpx;
}
.send-code-btn {
width: 200rpx;
height: 60rpx;
display: inline-flex;
padding: 0rpx 10rpx;
justify-content: center;
align-items: center;
gap: 10px;
border-radius: 4px;
background: #000;
}
.send-code-btn-email {
width: 200rpx;
height: 60rpx;
display: inline-flex;
padding: 0rpx 10rpx;
justify-content: center;
align-items: center;
gap: 10px;
border-radius: 4px;
background: #000;
margin-right: 15rpx;
}
.send-code-btn-disabled {
background: #e6e6e6;
/* 禁用状态下的灰色背景 */
}
.send-code-btn-disabled-text {
color: #999999 !important;
}
.send-code-text {
color: #fff;
font-size: 28rpx;
}
.agreement-container-one {
display: flex;
align-items: center;
align-self: flex-start;
margin-bottom: 80rpx;
}
.agreement-container {
display: flex;
align-items: center;
margin-bottom: 40rpx;
margin-top: -75.5rpx;
align-self: flex-start;
}
.checkbox {
width: 30rpx;
height: 30rpx;
margin-left: 20rpx;
/* flex: content; */
}
.agreement-text-one {
font-size: 22rpx;
color: #666666;
text-align: center;
margin-left: 10rpx;
}
.agreement-text {
margin-left: 20rpx;
font-size: 24rpx;
color: #666666;
}
.link {
color: #333333;
font-weight: bold;
text-decoration: underline;
}
.register-btn {
width: 100%;
height: 80rpx;
background-color: #000000;
color: white;
font-size: 32rpx;
font-weight: bold;
border-radius: 40rpx;
margin-bottom: 40rpx;
}
.or-text {
flex-direction: column;
font-size: 24rpx;
color: #999999;
margin-top: 294rpx;
margin-bottom: -22rpx;
}
.to-icon {
width: 10rpx;
height: 16rpx;
}
.or-text-one {
flex-direction: column;
font-size: 24rpx;
color: #999999;
}
.third-party-login {
width: 100%;
margin-bottom: 60rpx;
}
.third-party-text {
color: #ffffff;
font-weight: bold;
white-space: pre;
}
.third-party-btn {
width: 100%;
height: 80rpx;
background-color: rgb(0, 0, 0);
border: 2rpx solid #e5e5e5;
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20rpx;
font-size: 28rpx;
color: #333333;
}
.google-icon,
.apple-icon {
width: 60rpx;
height: 60rpx;
margin-right: 20rpx;
}
.existing-account {
display: flex;
align-items: center;
}
.account-text {
font-size: 24rpx;
color: #666666;
}
.login-link {
font-size: 24rpx;
font-weight: bold;
color: #333333;
margin-left: 10rpx;
text-decoration: underline;
}
.static-footer {
position: fixed;
bottom: 0;
}
/* 弹窗样式 */
.popup-content {
background-color: #ffffff;
padding: 40rpx;
text-align: center;
border-radius: 10rpx;
width: 550rpx;
}
.popup-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 80rpx;
text-align: center; /* 水平居中 */
display: flex; /* 使用flex布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
.popup-message {
font-size: 28rpx;
color: #000000;
margin-bottom: 80rpx;
text-align: center; /* 水平居中 */
display: flex; /* 使用flex布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
.agree-button {
width: 300rpx;
height: 80rpx;
background-color: #000000;
border-radius: 40rpx;
display: flex; /* 添加flex布局 */
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
}
.agree-text {
color: #ffffff;
font-size: 34rpx;
/* 添加垂直居中相关样式 */
display: flex;
align-items: center;
justify-content: center;
line-height: 1; /* 确保文字垂直居中 */
}
.switch-container-occupy {
margin-top: 100rpx;
}
</style>

47
pages/start/select/select.vue

@ -17,11 +17,22 @@
<button class="register-button" @click="toRegistration">注册</button> <button class="register-button" @click="toRegistration">注册</button>
</view> </view>
<footerBar class="static-footer" :type="type"></footerBar>
</view> </view>
</template> </template>
<script setup> <script setup>
import footerBar from '../../../components/footerBar-cn'
import { ref, reactive, toRefs, watch } from 'vue'
const type = ref('member')
function toRegistration() { function toRegistration() {
uni.navigateTo({ uni.navigateTo({
url: "/pages/start/Registration/Registration", url: "/pages/start/Registration/Registration",
@ -42,8 +53,11 @@ function toLogin() {
align-items: center; align-items: center;
/* justify-content: space-between; */ /* justify-content: space-between; */
padding: 40rpx; padding: 40rpx;
height: 100vh;
height: 90vh;
background-color: #ffffff; background-color: #ffffff;
overflow: hidden;
max-height: 100vh;
-webkit-overflow-scrolling: none;
} }
.title-section { .title-section {
@ -56,30 +70,32 @@ function toLogin() {
.main-title { .main-title {
text-align: center; text-align: center;
font-size: 64rpx; font-size: 64rpx;
font-weight: 800;
font-weight: 300;
color: #000000; color: #000000;
margin-bottom: 10rpx; margin-bottom: 10rpx;
} }
.subtitle-section { .subtitle-section {
margin-bottom: 100rpx;
margin-bottom: 80rpx;
} }
.subtitle { .subtitle {
font-weight: bold;
/* font-weight: bold; */
font-size: 32rpx; font-size: 32rpx;
color: #333333; color: #333333;
} }
.phone-card { .phone-card {
background-image: url("/static/images/card.jpg");
background-size: 100% 100%;
background-image: url("/static/select.png");
background-repeat: no-repeat;
background-size: contain;
background-position: center; background-position: center;
min-width: 400rpx;
min-height: 700rpx;
width: 400rpx;
height: 700rpx;
border-radius: 40rpx;
/* background-position: center; */
/* min-width: 300rpx; */
width: 420rpx;
height: 786rpx;
border-radius: 50rpx;
padding: 40rpx; padding: 40rpx;
box-shadow: 0 20rpx 40rpx rgba(0, 0, 0, 0.3);
/* box-shadow: 0 20rpx 40rpx rgba(0, 0, 0, 0.3); */
position: relative; position: relative;
overflow: hidden; overflow: hidden;
} }
@ -149,4 +165,11 @@ function toLogin() {
.nav-item.active .nav-text { .nav-item.active .nav-text {
color: #000000; color: #000000;
} }
.static-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
</style> </style>

4
pages/start/startup/startup.vue

@ -16,11 +16,13 @@ onShow(() => {
}); });
}, 3000); }, 3000);
}); });
</script> </script>
<style> <style>
.background { .background {
background: linear-gradient(180deg, #2a0c4d, #1d0836, #0d0218);
background: linear-gradient(180deg, #FB6967, #FB6967);
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
} }

BIN
static/icons/To.png

After

Width: 11  |  Height: 18  |  Size: 442 B

BIN
static/icons/back.png

After

Width: 18  |  Height: 32  |  Size: 576 B

BIN
static/icons/look.png

After

Width: 40  |  Height: 24  |  Size: 1.5 KiB

BIN
static/icons/start-logo.png

After

Width: 326  |  Height: 200  |  Size: 20 KiB

BIN
static/icons/unlook.png

After

Width: 40  |  Height: 18  |  Size: 1.0 KiB

BIN
static/select.png

After

Width: 420  |  Height: 786  |  Size: 156 KiB

BIN
static/start-logo.png

After

Width: 326  |  Height: 200  |  Size: 20 KiB

18
uni_modules/uni-popup/changelog.md

@ -1,3 +1,21 @@
## 1.9.11(2025-08-20)
- 修复 uni-popup-dialog组件设置 borderRadius 不生效的 Bug
## 1.9.10(2025-07-18)
- 修复 nvue 下弹窗样式错乱的问题 ,更新依赖 uni-transition 组件
- 更新 示例取消 borderRadius 属性 ,如需内容圆角,用户应该直接在内容插槽中实现
## 1.9.9(2025-06-11)
- 修复 uni-popup-dialog 中 setVal 方法报错的问题
- 修复 uni-popup-dialog 数据双向绑定问题。
## 1.9.8(2025-04-16)
- 修复 更新组件示例 ,解决更新数据或保存项目导致弹窗消失的问题
## 1.9.7(2025-04-14)
- 修复 uni-popup-dialog 弹出框在vue3中双向绑定问题
## 1.9.6(2025-01-08)
- 修复 示例中过期图片地址
## 1.9.5(2024-10-15)
- 修复 微信小程序中的getSystemInfo警告
## 1.9.2(2024-09-21)
- 修复 uni-popup在android上的重复点击弹出位置不正确的bug
## 1.9.1(2024-04-02) ## 1.9.1(2024-04-02)
- 修复 uni-popup-dialog vue3下使用value无法进行绑定的bug(双向绑定兼容旧写法) - 修复 uni-popup-dialog vue3下使用value无法进行绑定的bug(双向绑定兼容旧写法)
## 1.9.0(2024-03-28) ## 1.9.0(2024-03-28)

28
uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue

@ -1,5 +1,5 @@
<template> <template>
<view class="uni-popup-dialog">
<view class="uni-popup-dialog" :style="{ borderRadius }">
<view class="uni-dialog-title"> <view class="uni-dialog-title">
<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text> <text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text>
</view> </view>
@ -124,6 +124,10 @@
focus: { focus: {
type: Boolean, type: Boolean,
default: true, default: true,
},
borderRadius: {
type: String,
default: '11px',
} }
}, },
data() { data() {
@ -156,12 +160,13 @@
} }
}, },
value(val) { value(val) {
if (this.maxlength != -1 && this.mode === 'input') {
this.val = val.slice(0, this.maxlength);
} else {
this.val = val
}
this.setVal(val)
},
// #ifdef VUE3
modelValue(val) {
this.setVal(val)
}, },
// #endif
val(val) { val(val) {
// #ifdef VUE2 // #ifdef VUE2
// TODO vue2 // TODO vue2
@ -189,6 +194,16 @@
}, },
methods: { methods: {
/** /**
* 给val属性赋值
*/
setVal(val) {
if (this.maxlength != -1 && this.mode === 'input') {
this.val = val.slice(0, this.maxlength);
} else {
this.val = val
}
},
/**
* 点击确认按钮 * 点击确认按钮
*/ */
onOk() { onOk() {
@ -218,7 +233,6 @@
<style lang="scss"> <style lang="scss">
.uni-popup-dialog { .uni-popup-dialog {
width: 300px; width: 300px;
border-radius: 11px;
background-color: #fff; background-color: #fff;
} }

9
uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue

@ -39,24 +39,25 @@
}, },
data() { data() {
return { return {
// TODO
bottomData: [{ bottomData: [{
text: '微信', text: '微信',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/c2b17470-50be-11eb-b680-7980c8a877b8.png',
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
name: 'wx' name: 'wx'
}, },
{ {
text: '支付宝', text: '支付宝',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/d684ae40-50be-11eb-8ff1-d5dcf8779628.png',
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
name: 'ali' name: 'ali'
}, },
{ {
text: 'QQ', text: 'QQ',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/e7a79520-50be-11eb-b997-9918a5dda011.png',
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
name: 'qq' name: 'qq'
}, },
{ {
text: '新浪', text: '新浪',
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/0dacdbe0-50bf-11eb-8ff1-d5dcf8779628.png',
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
name: 'sina' name: 'sina'
}, },
// { // {

27
uni_modules/uni-popup/components/uni-popup/uni-popup.vue

@ -192,6 +192,17 @@
}, },
mounted() { mounted() {
const fixSize = () => { const fixSize = () => {
// #ifdef MP-WEIXIN
const {
windowWidth,
windowHeight,
windowTop,
safeArea,
screenHeight,
safeAreaInsets
} = uni.getWindowInfo()
// #endif
// #ifndef MP-WEIXIN
const { const {
windowWidth, windowWidth,
windowHeight, windowHeight,
@ -200,6 +211,7 @@
screenHeight, screenHeight,
safeAreaInsets safeAreaInsets
} = uni.getSystemInfoSync() } = uni.getSystemInfoSync()
// #endif
this.popupWidth = windowWidth this.popupWidth = windowWidth
this.popupHeight = windowHeight + (windowTop || 0) this.popupHeight = windowHeight + (windowTop || 0)
// TODO fix by mehaotian ,ios app ios // TODO fix by mehaotian ,ios app ios
@ -350,6 +362,7 @@
this.showPopup = true this.showPopup = true
this.showTrans = true this.showTrans = true
this.$nextTick(() => { this.$nextTick(() => {
this.showPoptrans()
if (this.messageChild && this.type === 'message') { if (this.messageChild && this.type === 'message') {
this.messageChild.timerClose() this.messageChild.timerClose()
} }
@ -372,8 +385,7 @@
} }
// TODO type // TODO type
if (type) return if (type) return
this.showPopup = true
this.showTrans = true
this.showPoptrans()
}, },
/** /**
* 中间弹出样式处理 * 中间弹出样式处理
@ -403,8 +415,7 @@
} }
// TODO type // TODO type
if (type) return if (type) return
this.showPopup = true
this.showTrans = true
this.showPoptrans()
}, },
left(type) { left(type) {
this.popupstyle = 'left' this.popupstyle = 'left'
@ -423,8 +434,7 @@
} }
// TODO type // TODO type
if (type) return if (type) return
this.showPopup = true
this.showTrans = true
this.showPoptrans()
}, },
right(type) { right(type) {
this.popupstyle = 'right' this.popupstyle = 'right'
@ -443,8 +453,13 @@
} }
// TODO type // TODO type
if (type) return if (type) return
this.showPoptrans()
},
showPoptrans(){
this.$nextTick(()=>{
this.showPopup = true this.showPopup = true
this.showTrans = true this.showTrans = true
})
} }
} }
} }

83
uni_modules/uni-popup/package.json

@ -1,7 +1,7 @@
{ {
"id": "uni-popup", "id": "uni-popup",
"displayName": "uni-popup 弹出层", "displayName": "uni-popup 弹出层",
"version": "1.9.1",
"version": "1.9.11",
"description": " Popup 组件,提供常用的弹层", "description": " Popup 组件,提供常用的弹层",
"keywords": [ "keywords": [
"uni-ui", "uni-ui",
@ -12,7 +12,9 @@
], ],
"repository": "https://github.com/dcloudio/uni-ui", "repository": "https://github.com/dcloudio/uni-ui",
"engines": { "engines": {
"HBuilderX": ""
"HBuilderX": "",
"uni-app": "^4.07",
"uni-app-x": ""
}, },
"directories": { "directories": {
"example": "../../temps/example_temps" "example": "../../temps/example_temps"
@ -35,7 +37,10 @@
"permissions": "无" "permissions": "无"
}, },
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
"type": "component-vue",
"darkmode": "x",
"i18n": "x",
"widescreen": "x"
}, },
"uni_modules": { "uni_modules": {
"dependencies": [ "dependencies": [
@ -45,42 +50,56 @@
"encrypt": [], "encrypt": [],
"platforms": { "platforms": {
"cloud": { "cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "n"
"tcb": "x",
"aliyun": "x",
"alipay": "x"
}, },
"client": { "client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
"uni-app": {
"vue": {
"vue2": "√",
"vue3": "√"
}, },
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
"web": {
"safari": "√",
"chrome": "√"
}, },
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
"app": {
"vue": "√",
"nvue": "√",
"android": "√",
"ios": "√",
"harmony": "√"
}, },
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
"mp": {
"weixin": "√",
"alipay": "√",
"toutiao": "√",
"baidu": "√",
"kuaishou": "-",
"jd": "-",
"harmony": "-",
"qq": "√",
"lark": "-"
}, },
"快应用": {
"华为": "u",
"联盟": "u"
"quickapp": {
"huawei": "-",
"union": "-"
}
},
"uni-app-x": {
"web": {
"safari": "√",
"chrome": "√"
}, },
"Vue": {
"vue2": "y",
"vue3": "y"
"app": {
"android": "√",
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": "√"
}
} }
} }
} }

7
uni_modules/uni-transition/changelog.md

@ -1,3 +1,10 @@
## 1.3.6(2025-07-18)
- 修复 nvue 页面,样式错误问题
## 1.3.5(2025-06-11)
- 修复 第一次执行不显示动画的问题
## 1.3.4(2025-04-16)
- 修复 页面数据更新到底动画复原的问题
- 修复 示例页面打开报错的问题
## 1.3.3(2024-04-23) ## 1.3.3(2024-04-23)
- 修复 当元素会受变量影响自动隐藏的bug - 修复 当元素会受变量影响自动隐藏的bug
## 1.3.2(2023-05-04) ## 1.3.2(2023-05-04)

72
uni_modules/uni-transition/components/uni-transition/uni-transition.vue

@ -1,9 +1,13 @@
<template> <template>
<!-- #ifndef APP-NVUE --> <!-- #ifndef APP-NVUE -->
<view v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
<view v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick">
<slot></slot>
</view>
<!-- #endif --> <!-- #endif -->
<!-- #ifdef APP-NVUE --> <!-- #ifdef APP-NVUE -->
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick">
<slot></slot>
</view>
<!-- #endif --> <!-- #endif -->
</template> </template>
@ -63,7 +67,7 @@ export default {
return { return {
isShow: false, isShow: false,
transform: '', transform: '',
opacity: 1,
opacity: 0,
animationData: {}, animationData: {},
durationTime: 300, durationTime: 300,
config: {} config: {}
@ -136,18 +140,15 @@ export default {
* @param {Object} obj * @param {Object} obj
*/ */
step(obj, config = {}) { step(obj, config = {}) {
if (!this.animation) return
for (let i in obj) {
try {
if(typeof obj[i] === 'object'){
this.animation[i](...obj[i])
}else{
this.animation[i](obj[i])
}
} catch (e) {
console.error(`方法 ${i} 不存在`)
}
if (!this.animation) return this
Object.keys(obj).forEach(key => {
const value = obj[key]
if (typeof this.animation[key] === 'function') {
Array.isArray(value) ?
this.animation[key](...value) :
this.animation[key](value)
} }
})
this.animation.step(config) this.animation.step(config)
return this return this
}, },
@ -161,24 +162,31 @@ export default {
// //
open() { open() {
clearTimeout(this.timer) clearTimeout(this.timer)
this.transform = ''
this.isShow = true this.isShow = true
let { opacity, transform } = this.styleInit(false)
if (typeof opacity !== 'undefined') {
this.opacity = opacity
}
this.transform = transform
//
this.transform = this.styleInit(false).transform || ''
this.opacity = this.styleInit(false).opacity || 0
// nextTick wx // nextTick wx
this.$nextTick(() => { this.$nextTick(() => {
// TODO // TODO
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
this.animation = createAnimation(this.config, this) this.animation = createAnimation(this.config, this)
this.tranfromInit(false).step() this.tranfromInit(false).step()
this.animation.run()
this.animation.run(() => {
// #ifdef APP-NVUE
this.transform = this.styleInit(false).transform || ''
this.opacity = this.styleInit(false).opacity || 1
// #endif
// #ifndef APP-NVUE
this.transform = ''
this.opacity = this.styleInit(false).opacity || 1
// #endif
this.$emit('change', { this.$emit('change', {
detail: this.isShow detail: this.isShow
}) })
}, 20)
})
}, 80)
}) })
}, },
// //
@ -200,22 +208,20 @@ export default {
}, },
// //
styleInit(type) { styleInit(type) {
let styles = {
transform: ''
}
let buildStyle = (type, mode) => {
if (mode === 'fade') {
styles.opacity = this.animationType(type)[mode]
let styles = { transform: '', opacity: 1 }
const buildStyle = (type, mode) => {
const value = this.animationType(type)[mode] // 使 type
if (mode.startsWith('fade')) {
styles.opacity = value
} else { } else {
styles.transform += this.animationType(type)[mode] + ' '
styles.transform += value + ' '
} }
} }
if (typeof this.modeClass === 'string') { if (typeof this.modeClass === 'string') {
buildStyle(type, this.modeClass) buildStyle(type, this.modeClass)
} else { } else {
this.modeClass.forEach(mode => {
buildStyle(type, mode)
})
this.modeClass.forEach(mode => buildStyle(type, mode))
} }
return styles return styles
}, },
@ -254,7 +260,7 @@ export default {
}, },
animationType(type) { animationType(type) {
return { return {
fade: type ? 0 : 1,
fade: type ? 1 : 0,
'slide-top': `translateY(${type ? '0' : '-100%'})`, 'slide-top': `translateY(${type ? '0' : '-100%'})`,
'slide-right': `translateX(${type ? '0' : '100%'})`, 'slide-right': `translateX(${type ? '0' : '100%'})`,
'slide-bottom': `translateY(${type ? '0' : '100%'})`, 'slide-bottom': `translateY(${type ? '0' : '100%'})`,

103
uni_modules/uni-transition/package.json

@ -1,7 +1,7 @@
{ {
"id": "uni-transition", "id": "uni-transition",
"displayName": "uni-transition 过渡动画", "displayName": "uni-transition 过渡动画",
"version": "1.3.3",
"version": "1.3.6",
"description": "元素的简单过渡动画", "description": "元素的简单过渡动画",
"keywords": [ "keywords": [
"uni-ui", "uni-ui",
@ -12,7 +12,9 @@
], ],
"repository": "https://github.com/dcloudio/uni-ui", "repository": "https://github.com/dcloudio/uni-ui",
"engines": { "engines": {
"HBuilderX": ""
"HBuilderX": "",
"uni-app": "^4.12",
"uni-app-x": ""
}, },
"directories": { "directories": {
"example": "../../temps/example_temps" "example": "../../temps/example_temps"
@ -35,49 +37,74 @@
"permissions": "无" "permissions": "无"
}, },
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
"type": "component-vue",
"darkmode": "x",
"i18n": "x",
"widescreen": "x"
}, },
"uni_modules": { "uni_modules": {
"dependencies": ["uni-scss"],
"dependencies": [
"uni-scss"
],
"encrypt": [], "encrypt": [],
"platforms": { "platforms": {
"cloud": { "cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "n"
"tcb": "x",
"aliyun": "x",
"alipay": "x"
}, },
"client": { "client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
"uni-app": {
"vue": {
"vue2": "√",
"vue3": "√"
},
"web": {
"safari": "√",
"chrome": "√"
},
"app": {
"vue": "√",
"nvue": "√",
"android": "√",
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": {
},
"alipay": {
},
"toutiao": {
},
"baidu": {
},
"kuaishou": {
},
"jd": {
},
"harmony": "-",
"qq": "√",
"lark": "-"
},
"quickapp": {
"huawei": "√",
"union": "√"
}
},
"uni-app-x": {
"web": {
"safari": "-",
"chrome": "-"
},
"app": {
"android": "-",
"ios": "-",
"harmony": "-"
},
"mp": {
"weixin": "-"
}
} }
} }
} }

Loading…
Cancel
Save