|
- <template>
- <view class="page">
- <view class="logo-area">
- <image class="logo" src="https://cdn.csybhelp.com/images/cytx/logo.png" mode="aspectFit" />
- <text class="title">肠愈同行</text>
- <text class="subtitle">患者关爱</text>
- </view>
-
- <view class="btn-area">
- <!-- #ifdef MP-WEIXIN -->
- <button class="login-btn" @tap="handleWxLogin" :loading="loading">
- 微信一键登录
- </button>
- <!-- #endif -->
-
- <!-- #ifdef H5 -->
- <view class="phone-form">
- <view class="form-item">
- <input class="form-input" type="number" v-model="phone" placeholder="请输入手机号" maxlength="11" />
- </view>
- <view class="form-item code-row">
- <input class="form-input code-input" type="number" v-model="smsCode" placeholder="请输入验证码" maxlength="6" />
- <button class="sms-btn" :disabled="countdown > 0" @tap="sendSms">
- {{ countdown > 0 ? countdown + 's' : '获取验证码' }}
- </button>
- </view>
- <button class="login-btn" @tap="handlePhoneLogin" :loading="loading">
- 登录
- </button>
- </view>
- <!-- #endif -->
-
- <view class="tip">登录即表示同意
- <text class="link" @tap="goPrivacy">《隐私协议》</text>
- </view>
- </view>
- </view>
- </template>
-
- <script setup>
- import { ref, onUnmounted } from 'vue'
- import { post } from '@/utils/request.js'
- import { setToken, setUserInfo } from '@/utils/cache.js'
-
- const loading = ref(false)
- const phone = ref('')
- const smsCode = ref('')
- const countdown = ref(0)
- let timer = null
-
- onUnmounted(() => {
- if (timer) { clearInterval(timer); timer = null }
- })
-
- const loginSuccess = (res) => {
- setToken(res.data.token)
- setUserInfo(res.data.userInfo)
- uni.showToast({ title: '登录成功', icon: 'success' })
- setTimeout(() => {
- const pages = getCurrentPages()
- if (pages.length > 1) {
- uni.navigateBack()
- } else {
- uni.switchTab({ url: '/pages/profile/profile' })
- }
- }, 500)
- }
-
- // #ifdef MP-WEIXIN
- const handleWxLogin = async () => {
- if (loading.value) return
- loading.value = true
- try {
- const code = await new Promise((resolve, reject) => {
- uni.login({
- provider: 'weixin',
- success: (res) => resolve(res.code),
- fail: () => reject({ msg: '微信登录失败' })
- })
- })
- const res = await post('/api/mp/login', { code })
- loginSuccess(res)
- } catch (e) {
- if (e && e.msg) uni.showToast({ title: e.msg, icon: 'none' })
- } finally {
- loading.value = false
- }
- }
- // #endif
-
- // #ifdef H5
- const sendSms = async () => {
- if (countdown.value > 0) return
- if (!phone.value || phone.value.length !== 11) {
- return uni.showToast({ title: '请输入正确的手机号', icon: 'none' })
- }
- try {
- const res = await post('/api/mp/sendSmsCode', { mobile: phone.value, bizType: 'login' })
- if (res.data && res.data.code) {
- uni.showToast({ title: `验证码: ${res.data.code}`, icon: 'none', duration: 3000 })
- } else {
- uni.showToast({ title: '验证码已发送', icon: 'none' })
- }
- countdown.value = 60
- timer = setInterval(() => {
- countdown.value--
- if (countdown.value <= 0) { clearInterval(timer); timer = null }
- }, 1000)
- } catch (e) {
- if (e && e.msg) uni.showToast({ title: e.msg, icon: 'none' })
- }
- }
-
- const handlePhoneLogin = async () => {
- if (loading.value) return
- if (!phone.value || phone.value.length !== 11) {
- return uni.showToast({ title: '请输入正确的手机号', icon: 'none' })
- }
- if (!smsCode.value || smsCode.value.length !== 6) {
- return uni.showToast({ title: '请输入6位验证码', icon: 'none' })
- }
- loading.value = true
- try {
- const res = await post('/api/mp/phoneLogin', { mobile: phone.value, code: smsCode.value })
- loginSuccess(res)
- } catch (e) {
- if (e && e.msg) uni.showToast({ title: e.msg, icon: 'none' })
- } finally {
- loading.value = false
- }
- }
- // #endif
-
- const goPrivacy = () => {
- // #ifdef H5
- uni.navigateTo({ url: '/pages/content/content?key=privacy_policy_h5' })
- // #endif
- // #ifdef MP-WEIXIN
- uni.navigateTo({ url: '/pages/content/content?key=privacy_policy' })
- // #endif
- }
- </script>
-
- <style lang="scss" scoped>
- .page {
- min-height: 100vh;
- background: #fff;
- display: flex;
- flex-direction: column;
- align-items: center;
- padding-top: 25vh;
- /* #ifdef H5 */
- padding-top: 10vh;
- /* #endif */
- }
-
- .logo-area {
- display: flex;
- flex-direction: column;
- align-items: center;
- margin-bottom: 80rpx;
-
- .logo {
- width: 180rpx;
- height: 180rpx;
- border-radius: 24rpx;
- margin-bottom: 32rpx;
- }
-
- .title {
- font-size: 44rpx;
- font-weight: 600;
- color: #303133;
- margin-bottom: 8rpx;
- }
-
- .subtitle {
- font-size: 26rpx;
- color: #b0b3b8;
- letter-spacing: 2rpx;
- }
- }
-
- .btn-area {
- width: 100%;
- padding: 0 64rpx;
- box-sizing: border-box;
-
- .login-btn {
- width: 100%;
- height: 88rpx;
- line-height: 88rpx;
- background: #0F78E9;
- color: #fff;
- font-size: 32rpx;
- border-radius: 44rpx;
- border: none;
-
- &::after {
- border: none;
- }
-
- &:active {
- opacity: 0.85;
- }
- }
-
- .tip {
- text-align: center;
- font-size: 24rpx;
- color: #909399;
- margin-top: 32rpx;
-
- .link {
- color: #0F78E9;
- }
- }
- }
-
- .phone-form {
- width: 100%;
-
- .form-item {
- margin-bottom: 24rpx;
- }
-
- .form-input {
- width: 100%;
- height: 88rpx;
- border: 1rpx solid #dcdfe6;
- border-radius: 44rpx;
- padding: 0 36rpx;
- font-size: 30rpx;
- box-sizing: border-box;
- background: #f8f9fa;
- }
-
- .code-row {
- display: flex;
- gap: 20rpx;
-
- .code-input {
- flex: 2;
- }
- }
-
- .sms-btn {
- flex: 1;
- height: 88rpx;
- line-height: 88rpx;
- padding: 0;
- background: #0F78E9;
- color: #fff;
- border: none;
- border-radius: 44rpx;
- font-size: 26rpx;
- white-space: nowrap;
- text-align: center;
-
- &::after {
- border: none;
- }
-
- &[disabled] {
- background: #a0cfff;
- color: #fff;
- }
- }
-
- .login-btn {
- margin-top: 16rpx;
- }
- }
- </style>
|