index.vue 4.9 KB
<template>
  <view class="login-page">
    <!-- 登录表单区域 -->
    <view class="login-form">
      <!-- 账号输入框 -->
      <view class="form-item">
        <up-input
            v-model="form.account"
            placeholder="请输入登录账号"
            border="surround"
            clearable
            input-align="left"
            :disabled="isLoading"
            @blur="checkAccount"
        >
          <template #prefix>
            <up-icon name="account" color="#909399" size="20"></up-icon>
          </template>
        </up-input>
        <!-- 账号错误提示 -->
        <view class="error-tip" v-if="error.account">{{ error.account }}</view>
      </view>

      <!-- 密码输入框(移除查看密码功能) -->
      <view class="form-item">
        <up-input
            v-model="form.password"
            placeholder="请输入登录密码"
            border="surround"
            clearable
            input-align="left"
            type="password"
            :disabled="isLoading"
            @blur="checkPassword"
        >
          <template #prefix>
            <up-icon name="lock" color="#909399" size="20"></up-icon>
          </template>
        </up-input>
        <!-- 密码错误提示 -->
        <view class="error-tip" v-if="error.password">{{ error.password }}</view>
      </view>

      <!-- 登录按钮 -->
      <up-button
          class="login-btn"
          type="primary"
          size="large"
          :loading="isLoading"
          @click="handleLogin"
      >
        登录
      </up-button>
    </view>
  </view>
</template>

<script setup>
import { ref, reactive, onMounted } from 'vue';
import { useUserStore } from '@/pinia/user';
import globalConfig from '@/common/config/global';

// 表单数据
const form = reactive({
  account: '', // 账号
  password: '' // 密码
});

// 状态管理
const isLoading = ref(false);
const error = reactive({
  account: '',
  password: ''
});

// 实例化 Pinia 用户仓库
const userStore = useUserStore();

// 页面加载时校验登录态
onMounted(() => {
  try {
    // 已登录则直接跳首页
    if (userStore.isLogin) {
      uni.switchTab({
        url: globalConfig.router.tabBarList[1].path,
        fail: () => {
          // 非tabBar页面用redirectTo
          uni.redirectTo({ url: '/pages/workbench/index' });
        }
      });
      return;
    }
  } catch (err) {
    console.warn('检查登录状态失败:', err);
  }
});

// 校验账号
const checkAccount = () => {
  if (!form.account) {
    error.account = '请输入登录账号';
  } else if (!/^[a-zA-Z0-9_-]{4,16}$/.test(form.account)) {
    error.account = '账号格式错误(4-16位字母/数字/下划线)';
  } else {
    error.account = '';
  }
};

// 校验密码
const checkPassword = () => {
  if (!form.password) {
    error.password = '请输入登录密码';
  } else if (form.password.length < 6) {
    error.password = '密码长度不能少于6位';
  } else {
    error.password = '';
  }
};

// 表单整体校验
const validateForm = () => {
  checkAccount();
  checkPassword();
  return !error.account && !error.password;
};

// 登录处理(核心:补充跳转逻辑)
const handleLogin = async () => {
  if (!validateForm()) return;

  isLoading.value = true;

  try {
    await userStore.login({
      username: form.account,
      password: form.password
    });

    uni.showToast({ title: '登录成功', icon: 'success', duration: 1500 });

    // 登录成功后跳转首页(优先tabBar,兼容普通页面)
    setTimeout(() => {
      // 方式1:跳tabBar首页(推荐,需在pages.json配置tabBar)
      uni.switchTab({
        url: globalConfig.router.tabBarList[1].path,
        fail: (err) => {
          console.warn('tabBar跳转失败,切换为普通跳转:', err);
          // 方式2:跳普通首页(非tabBar页面)
          uni.redirectTo({ url: '/pages/workbench/index' });
        }
      });
    }, 1500);

  } catch (err) {
    console.error('登录失败详情:', err);
    const errorMsg = err.message === '网络异常,请稍后重试'
        ? '网络异常,请稍后重试'
        : err.message || '登录失败,请检查账号密码';
    uni.showToast({
      title: errorMsg,
      icon: 'none',
      duration: 2000
    });
  } finally {
    isLoading.value = false;
  }
};
</script>

<style scoped lang="scss">
.login-page {
  min-height: 100vh;
  background-color: #f5f5f5;
  padding: 40rpx 30rpx;
  box-sizing: border-box;
}

.login-form {
  background-color: #fff;
  padding: 40rpx 30rpx;
  border-radius: 12rpx;
  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}

.form-item {
  margin-bottom: 30rpx;
  position: relative;
}

.error-tip {
  font-size: 24rpx;
  color: #f56c6c;
  margin-top: 10rpx;
  line-height: 1.2;
}

.login-btn {
  width: 100%;
  height: 88rpx;
  line-height: 88rpx;
  font-size: 32rpx;
  border-radius: 44rpx;
  background-color: #409eff;
  margin-top: 10rpx;
}
</style>