gaoluyang
2025-08-06 6abe22fc75b115d2a68103a4d8b24d0815a016f8
src/pages/login.vue
@@ -1,59 +1,94 @@
<template>
  <view class="normal-login-container">
    <view class="logo-content align-center justify-center flex">
      <image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix">
      </image>
      <text class="title">若依移动端登录</text>
    <view class="logo-content">
<!--      <image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix">-->
<!--      </image>-->
      <text>账号密码登录</text>
    </view>
    <view class="login-form-content">
      <view class="input-item flex align-center">
        <view class="iconfont icon-user icon"></view>
        <input v-model="loginForm.username" class="input" type="text" placeholder="请输入账号" maxlength="30" />
            <up-input prefixIcon="account" placeholder="请输入账号" border="bottom"
                           @blur="getUserLoginFacotryList"
                           maxlength="30" v-model="loginForm.username" clearable></up-input>
      </view>
      <view class="input-item flex align-center">
        <view class="iconfont icon-password icon"></view>
        <input v-model="loginForm.password" type="password" class="input" placeholder="请输入密码" maxlength="20" />
            <up-input prefixIcon="lock" placeholder="请输入密码" border="bottom" maxlength="20" v-model="loginForm.password" clearable type="password"></up-input>
      </view>
      <view class="input-item flex align-center" style="width: 60%;margin: 0px;" v-if="captchaEnabled">
        <view class="iconfont icon-code icon"></view>
        <input v-model="loginForm.code" type="number" class="input" placeholder="请输入验证码" maxlength="4" />
        <view class="login-code">
          <image :src="codeUrl" @click="getCode" class="login-code-img"></image>
        </view>
      </view>
      <view class="action-btn">
         <view class="input-item flex align-center select-container">
            <up-icon name="tags" size="18"></up-icon>
            <up-picker-data
               v-model="loginForm.factoryId"
               title="请选择公司"
               :options="factoryList"
               valueKey="id"
               labelKey="name">
            </up-picker-data>
         </view>
      <view>
        <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">登录</button>
      </view>
    </view>
    <view class="xieyi text-center">
      <text class="text-grey1">登录即代表同意</text>
      <text @click="handleUserAgrement" class="text-blue">《用户协议》</text>
      <text @click="handlePrivacy" class="text-blue">《隐私协议》</text>
    </view>
      <!-- 记住密码选项 -->
      <view class="remember-password">
         <up-checkbox
            :customStyle="{marginBottom: '8px'}"
            label="记住密码"
            name="agree"
            usedAlone
            v-model:checked="rememberPassword"
         >
         </up-checkbox>
      </view>
  </view>
</template>
<script setup>
import modal from '@/plugins/modal'
import { getCodeImg } from '@/api/login'
import { ref } from "vue";
import config from '@/config.js'
import { userLoginFacotryList} from '@/api/login'
import { ref, onMounted } from "vue";
import useUserStore from '@/store/modules/user'
import { getWxCode } from '@/utils/geek';
import { wxLogin } from '@/api/oauth';
import { setToken } from '@/utils/auth';
const userStore = useUserStore()
const codeUrl = ref("");
const captchaEnabled = ref(true); // 是否开启验证码
const useWxLogin = ref(false); // 是否使用微信登录
const globalConfig = ref(config);
const rememberPassword = ref(false); // 记住密码
const loginForm = ref({
  username: "admin",
  password: "admin123",
  code: "",
  uuid: ''
  username: "",
  password: "",
   factoryId: "",
   currentFatoryName: "",
});
const factoryList = ref([]) // 公司列表
// 保存密码到本地存储
function savePassword() {
  if (rememberPassword.value) {
    uni.setStorageSync('remembered_username', loginForm.value.username);
    uni.setStorageSync('remembered_password', loginForm.value.password);
    uni.setStorageSync('remember_password', true);
  } else {
    uni.removeStorageSync('remembered_username');
    uni.removeStorageSync('remembered_password');
    uni.setStorageSync('remember_password', false);
  }
}
// 从本地存储加载密码
function loadPassword() {
  const remembered = uni.getStorageSync('remember_password');
  if (remembered) {
    rememberPassword.value = true;
    const savedUsername = uni.getStorageSync('remembered_username');
    const savedPassword = uni.getStorageSync('remembered_password');
    if (savedUsername) {
      loginForm.value.username = savedUsername;
    }
    if (savedPassword) {
      loginForm.value.password = savedPassword;
    }
  }
}
if (useWxLogin.value) {
  getWxCode().then(res => {
@@ -67,25 +102,36 @@
  })
}
// 获取图形验证码
function getCode() {
  getCodeImg().then(res => {
    captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled
    if (captchaEnabled.value) {
      codeUrl.value = 'data:image/gif;base64,' + res.img
      loginForm.value.uuid = res.uuid
    }
  })
};
function getUserLoginFacotryList() {
   if(loginForm.value.username){
      userLoginFacotryList({userName:loginForm.value.username}).then(res => {
         // 检查res.data是否为数组
         if (res.data && Array.isArray(res.data)) {
            // 重新组装数据格式:deptId变成id,deptName变成name
            factoryList.value = res.data.map(item => ({
               id: item.deptId,
               name: item.deptName
            }))
         } else {
            // 如果res.data不是数组,设置为空数组
            factoryList.value = []
         }
      }).catch(error => {
         modal.msgError('获取公司列表失败:', error)
         factoryList.value = []
      })
   }else {
      factoryList.value = []
   }
}
async function handleLogin() {
  if (loginForm.value.username === "") {
    modal.msgError("请输入您的账号")
  } else if (loginForm.value.password === "") {
    modal.msgError("请输入您的密码")
  } else if (loginForm.value.code === "" && captchaEnabled.value) {
    modal.msgError("请输入验证码")
  } else if (loginForm.value.factoryId === "") {
    modal.msgError("请选择公司")
  } else {
    modal.loading("登录中,请耐心等待...")
    pwdLogin()
@@ -93,14 +139,13 @@
};
// 密码登录
async function pwdLogin() {
  userStore.login(loginForm.value).then(() => {
  userStore.loginCheckFactory(loginForm.value).then(() => {
    modal.closeLoading()
    // 登录成功后保存密码
    savePassword();
    loginSuccess()
  }).catch(() => {
    if (captchaEnabled.value) {
      modal.closeLoading()
      getCode()
    }
      modal.closeLoading()
  })
};
@@ -112,23 +157,11 @@
    });
  })
}
// 隐私协议
function handlePrivacy() {
  let site = globalConfig.value.appInfo.agreements[0];
  uni.navigateTo({
    url: `/pages/common/webview/index?title=${site.title}&url=${site.url}`
  });
};
// 用户协议
function handleUserAgrement() {
  let site = globalConfig.value.appInfo.agreements[1]
  uni.navigateTo({
    url: `/pages/common/webview/index?title=${site.title}&url=${site.url}`
  });
};
getCode();
// 页面加载时检查是否有保存的密码
onMounted(() => {
   loadPassword();
   getUserLoginFacotryList()
});
</script>
<style lang="scss">
@@ -141,9 +174,10 @@
  .logo-content {
    width: 100%;
    font-size: 21px;
    text-align: center;
    padding-top: 15%;
      font-weight: 400;
      font-size: 30px;
      color: #333333;
      margin: 80px 0 0 30px;
    image {
      border-radius: 4px;
@@ -153,38 +187,60 @@
      margin-left: 10px;
    }
  }
   .u-checkbox {
      margin-left: 34px;
   }
  .login-form-content {
    text-align: center;
    margin: 20px auto;
    margin-top: 15%;
    width: 80%;
    margin: 58px auto;
      padding: 0 30px;
    .input-item {
      margin: 20px auto;
      background-color: #f5f6f7;
      height: 45px;
      border-radius: 20px;
      .input-item {
       margin: 30px auto;
       height: 45px;
      .icon {
        font-size: 38rpx;
        margin-left: 10px;
        color: #999;
      }
       .icon {
         font-size: 38rpx;
         margin-left: 10px;
         color: #999;
       }
      .input {
        width: 100%;
        font-size: 14px;
        line-height: 20px;
        text-align: left;
        padding-left: 15px;
      }
    }
       .input {
         width: 100%;
         font-size: 14px;
         line-height: 20px;
         text-align: left;
         padding-left: 15px;
       }
     }
      .select-container {
         flex: 1;
         border-bottom: 1px solid #e5e5e5;
         padding: 6px 9px;
         :deep(.up-select) {
            border: none;
            background: transparent;
            .up-select__label {
               font-size: 14px;
               color: #333;
            }
            .up-select__value {
               font-size: 14px;
               color: #333;
            }
         }
      }
    .login-btn {
      margin-top: 40px;
      height: 45px;
      margin-top: 60px;
      height: 50px;
         background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%);
         box-shadow: 0px 4px 10px 0px rgba(3,88,185,0.2);
         border-radius: 40px 40px 40px 40px;
    }
    .xieyi {