index.vue 4.75 KB
<!--
 * @Date: 2026-01-08 13:01:56
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2026-01-08 13:02: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 Taro from '@tarojs/taro'
import { mainStore } from '@/stores/main'
import { volunteerLoginAPI, getUserInfoAPI } from '@/api/index'
import { useGo } from '@/hooks/useGo'
import logo from '@/assets/images/logo.png'

const store = mainStore()
const go = useGo()
const username = ref('')
const password = ref('')

const handleLogin = async () => {
  if (!username.value || !password.value) {
    Taro.showToast({ title: '请输入账号密码', icon: 'none' })
    return
  }

  Taro.showLoading({ title: '登录中...' })
  // 1. 执行登录
  const loginRes = await volunteerLoginAPI({ username: username.value, password: password.value })

  if (loginRes.code === 1) {
    // 2. 登录成功后,获取用户信息来验证和更新状态
    const userRes = await getUserInfoAPI()
    Taro.hideLoading()

    if (userRes.code === 1 && userRes.data) {
        // 更新 store 中的用户信息 (isVolunteer 会自动通过 getter 更新)
        store.changeUserInfo(userRes.data)

        if (store.isVolunteer) {
            Taro.showToast({ title: '登录成功', icon: 'success' })
            setTimeout(() => {
                triggerScan()
            }, 1500)
        } else {
            Taro.showToast({ title: '非义工账号', icon: 'none' })
        }
    } else {
        Taro.showToast({ title: '获取用户信息失败', icon: 'none' })
    }
  } else {
    Taro.hideLoading()
    Taro.showToast({ title: loginRes.msg || '登录失败', icon: 'none' })
  }
}

const triggerScan = () => {
    Taro.scanCode({
        success: (res) => {
            go(`/pages/verificationResult/index?result=${res.result}`)
        },
        fail: (err) => {
            console.log('Scan failed', err)
        }
    })
}
</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: 36rpx;
      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>