index.vue 4.92 KB
<!--
 * @Date: 2026-01-08 13:01:56
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2026-01-20 14:00:27
 * @FilePath: /xyxBooking-weapp/src/pages/volunteerLogin/index.vue
 * @Description: 义工登录页面
-->
<template>
  <view class="login-page">
    <view class="logo-section">
      <image :src="logo" mode="aspectFit" />
      <text class="app-name">义工登录</text>
    </view>

    <view class="login-card">
      <!-- <view class="title">欢迎回来</view> -->

      <view class="input-group">
        <text class="label">账号</text>
        <input
          v-model="username"
          placeholder="请输入账号"
          placeholder-class="input-placeholder"
          cursorSpacing="40rpx"
        />
      </view>

      <view class="input-group">
        <text class="label">密码</text>
        <input
          v-model="password"
          password
          placeholder="请输入密码"
          placeholder-class="input-placeholder"
          cursorSpacing="40rpx"
        />
      </view>

      <button class="login-btn" @tap="handleLogin">立即登录</button>
    </view>
  </view>
</template>

<script setup>
import { ref } from 'vue'
import { useDidShow } from '@tarojs/taro'
import { mainStore } from '@/stores/main'
import { volunteerLoginAPI, checkRedeemPermissionAPI } from '@/api/redeem'
import { useReplace } from '@/hooks/useGo'
import { showError, showSuccess, showLoading, hideLoading } from '@/utils/toast'
import logo from '@/assets/images/logo_01.png'

const store = mainStore()
const replace = useReplace()
const username = ref('')
const password = ref('')

/**
 * @description: 检查核销权限并重定向
 */

const check_permission_and_redirect = async () => {
  try {
    const permission_res = await checkRedeemPermissionAPI()
    if (permission_res?.code !== 1) {
      return
    }
    if (permission_res?.data) {
      store.changeUserInfo(permission_res.data)
    }
    if (permission_res?.data?.can_redeem === true) {
      replace('verificationResult')
    }
  } catch (e) {
    // 忽略权限检查错误
  }
}

useDidShow(() => {
  check_permission_and_redirect()
})

const handleLogin = async () => {
  if (!username.value || !password.value) {
    showError('请输入账号密码')
    return
  }

  showLoading('登录中...')
  const login_res = await volunteerLoginAPI({ uuid: username.value, password: password.value })
  hideLoading()

  if (login_res?.code !== 1) {
    showError(login_res?.msg || '登录失败')
    return
  }

  showLoading('校验权限中...')
  const permission_res = await checkRedeemPermissionAPI()
  hideLoading()

  if (permission_res?.code !== 1) {
    showError(permission_res?.msg || '权限校验失败')
    return
  }

  if (permission_res?.data) {
    store.changeUserInfo(permission_res.data)
  }

  if (permission_res?.data?.can_redeem === true) {
    showSuccess(permission_res?.msg || login_res?.msg || '登录成功')
    setTimeout(() => replace('verificationResult'), 1200)
    return
  }

  showError(permission_res?.msg || '暂无核销权限')
}
</script>

<style lang="less">
.login-page {
  min-height: 100vh;
  background-color: #f6f6f6;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 120rpx;

  .logo-section {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 60rpx;

    image {
      width: 120rpx;
      height: 120rpx;
      border-radius: 50%;
      margin-bottom: 24rpx;
      box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.1);
      background-color: #fff;
    }

    .app-name {
      font-size: 42rpx;
      font-weight: 600;
      color: #333;
      letter-spacing: 2rpx;
    }
  }

  .login-card {
    width: 690rpx;
    background: #fff;
    border-radius: 24rpx;
    padding: 60rpx 40rpx;
    box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.04);
    box-sizing: border-box;

    .title {
      font-size: 44rpx;
      font-weight: bold;
      color: #333;
      margin-bottom: 60rpx;
      padding-left: 10rpx;
    }

    .input-group {
      background-color: #f7f8fa;
      border-radius: 12rpx;
      padding: 28rpx 30rpx;
      margin-bottom: 32rpx;
      display: flex;
      align-items: center;
      transition: all 0.3s;

      .label {
        font-size: 30rpx;
        color: #333;
        font-weight: 500;
        width: 90rpx;
        margin-right: 20rpx;
      }

      input {
        flex: 1;
        font-size: 30rpx;
        color: #333;
        height: 44rpx;
        min-height: 44rpx;
      }

      .input-placeholder {
        color: #c0c4cc;
      }
    }

    .login-btn {
      margin-top: 80rpx;
      background: #a67939;
      color: #fff;
      height: 96rpx;
      line-height: 96rpx;
      border-radius: 48rpx;
      font-size: 34rpx;
      font-weight: 500;
      box-shadow: 0 12rpx 30rpx rgba(166, 121, 57, 0.3);
      border: none;

      &::after {
        border: none;
      }

      &:active {
        opacity: 0.9;
        transform: scale(0.99);
      }
    }
  }
}
</style>