zhangwencui
4 天以前 67461f55748c32d885db965bdff6c2cc63eb327b
src/pages/login.vue
@@ -1,208 +1,302 @@
<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">
      <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">
        <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">登录</button>
      <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 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 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 loginForm = ref({
  username: "admin",
  password: "admin123",
  code: "",
  uuid: ''
});
  import { modal } from "@/plugins";
if (useWxLogin.value) {
  getWxCode().then(res => {
    console.log(res);
    wxLogin('miniapp',res).then(res => {
      if(res.token != null){
        setToken(res.token);
        loginSuccess()
      }
  const showToast = message => {
    uni.showToast({
      title: message,
      icon: "none",
    });
  })
}
  };
  import { userLoginFacotryList, updateClientId } 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";
  import View from "@/pages/procurementManagement/procurementLedger/view.vue";
  const userStore = useUserStore();
  const useWxLogin = ref(false); // 是否使用微信登录
  const rememberPassword = ref(false); // 记住密码
  const loginForm = ref({
    userName: "",
    password: "",
    currentFatoryName: "",
  });
  const factoryList = ref([]); // 公司列表
// 获取图形验证码
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 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);
    }
  })
};
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 {
    modal.loading("登录中,请耐心等待...")
    pwdLogin()
  }
};
// 密码登录
async function pwdLogin() {
  userStore.login(loginForm.value).then(() => {
    modal.closeLoading()
    loginSuccess()
  }).catch(() => {
    if (captchaEnabled.value) {
      modal.closeLoading()
      getCode()
  // 从本地存储加载密码
  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;
      }
    }
  })
};
  }
function loginSuccess(result) {
  // 设置用户信息
  userStore.getInfo().then(res => {
    uni.switchTab({
      url: '/pages/index'
  if (useWxLogin.value) {
    getWxCode().then(res => {
      console.log(res);
      wxLogin("miniapp", res).then(res => {
        if (res.token != null) {
          setToken(res.token);
          loginSuccess();
        }
      });
    });
  })
}
  }
// 隐私协议
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}`
  });
};
  function getUserLoginFacotryList() {
    if (loginForm.value.userName) {
      userLoginFacotryList({ userName: loginForm.value.userName })
        .then(res => {
          console.log("res", 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 => {
          showToast("获取公司列表失败:", error);
          factoryList.value = [];
        });
    } else {
      factoryList.value = [];
    }
  }
getCode();
  async function handleLogin() {
    if (loginForm.value.userName === "") {
      showToast("请输入您的账号");
    } else if (loginForm.value.password === "") {
      showToast("请输入您的密码");
    } else {
      showToast("登录中,请耐心等待...");
      pwdLogin();
    }
  }
  // 密码登录
  async function pwdLogin() {
    userStore
      .loginCheckFactory(loginForm.value)
      .then(() => {
        modal.closeLoading();
        // 登录成功后保存密码
        savePassword();
        loginSuccess();
      })
      .catch(() => {
        modal.closeLoading();
      });
  }
  function loginSuccess(result) {
    // 设置用户信息
    userStore.getInfo().then(res => {
      // 登录成功后,将客户端推送标识发送到服务器
      sendClientIdToServer();
      uni.switchTab({
        url: "/pages/index",
      });
    });
  }
  // 将客户端推送标识发送到服务器
  function sendClientIdToServer() {
    // 获取本地存储的客户端标识
    const clientId = uni.getStorageSync("clientid");
    if (clientId) {
      console.log("登录成功,准备发送客户端标识到服务器:", clientId);
      // 这里调用后端接口发送客户端标识
      updateClientId({ cid: clientId })
        .then(res => {
          console.log("服务器响应:", res);
          if (res.code === 200) {
            console.log("客户端标识已成功发送到服务器");
          } else {
            console.log("服务器返回错误:", res.msg);
          }
        })
        .catch(error => {
          console.log("发送客户端标识到服务器失败:", error);
        });
      // 示例:api.updateClientId({ clientId: clientId });
      // 由于没有具体的接口,这里只打印日志
      console.log("客户端标识已发送到服务器");
    } else {
      console.log("未获取到客户端推送标识");
    }
  }
  // 页面加载时检查是否有保存的密码
  onMounted(() => {
    loadPassword();
    getUserLoginFacotryList();
  });
</script>
<style lang="scss">
page {
  background-color: #ffffff;
}
  page {
    background-color: #ffffff;
  }
.normal-login-container {
  width: 100%;
  .logo-content {
  .normal-login-container {
    width: 100%;
    font-size: 21px;
    text-align: center;
    padding-top: 15%;
    height: 100vh;
    image {
      border-radius: 4px;
    }
    .logo-content {
      width: 90%;
      font-weight: 400;
      font-size: 30px;
      color: #333333;
      margin: 80px 0 0 30px;
    .title {
      margin-left: 10px;
    }
  }
      image {
        border-radius: 4px;
      }
  .login-form-content {
    text-align: center;
    margin: 20px auto;
    margin-top: 15%;
    width: 80%;
    .input-item {
      margin: 20px auto;
      background-color: #f5f6f7;
      height: 45px;
      border-radius: 20px;
      .icon {
        font-size: 38rpx;
      .title {
        margin-left: 10px;
        color: #999;
      }
    }
    .u-checkbox {
      margin-left: 34px;
    }
    .login-form-content {
      text-align: center;
      margin: 58px auto;
      padding: 0 30px;
      .input-item {
        margin: 30px auto;
        height: 45px;
        .icon {
          font-size: 38rpx;
          margin-left: 10px;
          color: #999;
        }
        .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;
          }
        }
      }
      .input {
        width: 100%;
        font-size: 14px;
        line-height: 20px;
        text-align: left;
        padding-left: 15px;
      .login-btn {
        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 {
        color: #333;
        margin-top: 20px;
      }
    .login-btn {
      margin-top: 40px;
      height: 45px;
    }
    .xieyi {
      color: #333;
      margin-top: 20px;
    }
    .login-code {
      height: 38px;
      float: right;
      .login-code-img {
      .login-code {
        height: 38px;
        position: absolute;
        margin-left: 10px;
        width: 200rpx;
        float: right;
        .login-code-img {
          height: 38px;
          position: absolute;
          margin-left: 10px;
          width: 200rpx;
        }
      }
    }
  }
}
</style>