zhangwei
2025-08-20 115769e9ad3ddc64e21ad7285450c4c563c745ed
src/views/login/index.vue
@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup lang="tsx">
import Motion from "./utils/motion";
import { useRouter } from "vue-router";
import { message } from "@/utils/message";
@@ -7,15 +7,25 @@
  reactive,
  computed,
  ref,
  Ref,
  h,
  onMounted,
  defineAsyncComponent,
  onUnmounted,
  watch
} from "vue";
import { debounce } from "@pureadmin/utils";
import { debounce, storageLocal } from "@pureadmin/utils";
import { useNav } from "@/layout/hooks/useNav";
import { useEventListener } from "@vueuse/core";
import type { FormInstance } from "element-plus";
import {
  ElForm,
  ElFormItem,
  ElRadioGroup,
  ElRadio,
  ElRow,
  ElTag
} from "element-plus";
import { useLayout } from "@/layout/hooks/useLayout";
import { useUserStoreHook } from "@/store/modules/user";
import { initRouter, getTopMenu } from "@/router/utils";
@@ -25,12 +35,7 @@
import { useRoute } from "vue-router";
const route = useRoute();
// import dayIcon from "@/assets/svg/day.svg?component";
// import darkIcon from "@/assets/svg/dark.svg?component";
import Lock from "~icons/ri/lock-fill";
import User from "~icons/ri/user-3-fill";
import { captcha, phoneNumberCode, exRole } from "@/api/register/index.ts";
import { captcha, phoneNumberCode, exRole } from "@/api/register/index";
defineOptions({
  name: "Login"
@@ -50,15 +55,18 @@
// 获取验证码
const getCaptcha = async () => {
  // if (!state.captchaEnabled) return;
  state.ruleForm.code = "";
  const res = await captcha();
  console.log(res);
  state.captchaImage = "data:text/html;base64," + res.result?.img;
  state.expirySeconds = res.result?.expirySeconds;
  state.ruleForm.codeId = res.result?.id;
};
import {
  addDialog,
  closeDialog,
  updateDialog,
  closeAllDialog
} from "@/components/ReDialog";
const state = reactive({
  isShowPassword: false,
  ruleForm: {
@@ -66,9 +74,8 @@
    nickName: "",
    phone: "",
    phoneVCode: "",
    // tenantId: props.tenantInfo.id,
    code: "",
    codeId: 0,
    codeId: "",
    email: "",
    exRoleCode: ""
  },
@@ -111,49 +118,22 @@
  expirySeconds: 60, // 验证码过期时间
  phoneSeconds: 0, // 手机验证码倒计时
  roleList: [],
  myEnterpriseList: [],
  nowRole: {}
});
let secondCode = "";
let secondId: Ref<string | number | boolean> = ref("");
// 验证码过期计时器
let timer: any = null;
let phonetimer: any = null;
// 页面初始化
onMounted(async () => {
  // 若URL带有Token参数(第三方登录)
  // if (accessToken) await saveTokenAndInitRoutes(accessToken);
  // watch(
  //   () => themeConfig.value.isLoaded,
  //   isLoaded => {
  //     if (isLoaded) {
  // 获取登录配置
  // state.hideTenantForLogin = themeConfig.value.hideTenantForLogin ?? true;
  // state.secondVerEnabled = themeConfig.value.secondVer ?? true;
  // state.captchaEnabled = themeConfig.value.captcha ?? true;
  // 获取验证码
  getCaptcha();
  exRole().then(res => {
    state.roleList = res.result;
    const role = route.query;
    if (role.code) {
      state.nowRole = role;
    } else {
      state.nowRole = state.roleList[0];
    }
    state.ruleForm.exRoleCode = state.nowRole?.code;
  });
  // 注册验证码过期计时器
  // if (state.captchaEnabled) {
  timer = setInterval(() => {
    if (state.expirySeconds > 0) state.expirySeconds -= 1;
  }, 1000);
  // }
  // }
  // },
  // { immediate: true }
  // );
});
// 页面卸载
onUnmounted(() => {
@@ -163,37 +143,166 @@
  clearInterval(phonetimer);
  phonetimer = null;
});
const openDialog = () => {
  addDialog({
    width: "30%",
    title: "选择登录公司",
    contentRenderer: () =>
      h(
        ElForm,
        {
          ref: ruleFormRef,
          model: state.ruleForm,
          rules: loginRules,
          size: "large"
        },
        [
          h(Motion, { delay: 150 }, [
            h(
              ElFormItem,
              {
                prop: "exRoleCode",
                label: ""
              },
              [
                // 单选框组 - 纵向排列
                h(
                  ElRadioGroup,
                  {
                    modelValue: secondId.value,
                    "onUpdate:modelValue": val => {
                      secondId.value = val;
                    }
                  },
                  [
                    // 循环渲染单选框 - 根据每项的isManager显示标签
                    state.myEnterpriseList.map(item =>
                      h(
                        "el-row",
                        {
                          style: {
                            width: "100%"
                          }
                        },
                        [
                          h(
                            "el-col",
                            {
                              span: 24
                            },
                            [
                              h(
                                ElRadio,
                                {
                                  key: item.customerUserID,
                                  value: item.customerUserID
                                },
                                [
                                  // 单选框文本
                                  item.enterpriseName,
                                  // 根据当前项的isManager显示标签(放在文本后面)
                                  item.isManger
                                    ? h(
                                        ElTag,
                                        {
                                          type: "primary",
                                          size: "small",
                                          style: {
                                            marginLeft: "8px",
                                            alignSelf: "center"
                                          }
                                        },
                                        "管理员"
                                      )
                                    : null
                                ]
                              )
                            ]
                          )
                        ]
                      )
                    )
                  ]
                )
              ]
            )
          ])
        ]
      ),
    // jsx 语法 (注意在.vue文件启用jsx语法,需要在script开启lang="tsx")
    closeCallBack: ({ options, args }) => {
      if (args?.command === "cancel") {
        // 您点击了取消按钮
      } else if (args?.command === "sure") {
        let obj = {
          phone: state.ruleForm.phone,
          code: secondCode,
          id: secondId.value
        };
        useUserStoreHook()
          .loginByUsername(obj)
          .then(res => {
            if (res?.code == 200) {
              message("登录成功!", { type: "success" });
              router.replace({
                path: "/Index"
              });
            } else {
              message(res?.message, { type: "warning" });
            }
          });
      } else {
      }
    }
  });
};
// 点击登录
const onLogin = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  await formEl.validate(valid => {
    if (valid) {
      let obj = {
        phone: state.ruleForm.phone,
        code: state.ruleForm.phoneVCode,
        exRuleCode: state.ruleForm.exRoleCode
      };
      loading.value = true;
      useUserStoreHook()
        .loginByUsername({
          phone: state.ruleForm.phone,
          code: state.ruleForm.phoneVCode,
          exRuleCode: state.ruleForm.exRoleCode
        })
        .loginByUsername(obj)
        .then(res => {
          if (res.code == 200) {
            // 获取后端路由
            return initRouter().then(() => {
              disabled.value = true;
              router
                .replace("index")
                .then(() => {
                  message("登录成功", { type: "success" });
                })
                .finally(() => (disabled.value = false));
              let obj = res.result;
              if (obj.theLastLogo) {
                router
                  .replace({
                    path: "/Index"
                  })
                  .then(() => {
                    message("登录成功", { type: "success" });
                  })
                  .finally(() => (disabled.value = false));
              } else {
                state.myEnterpriseList = obj.customerExs;
                secondCode = obj.code;
                openDialog();
              }
            });
          } else {
            message(res?.message || "登录失败", { type: "error" });
          }
        })
        .finally(() => (loading.value = false));
        .finally(() => {
          loading.value = false;
          disabled.value = false;
        });
    }
  });
};
// 发送手机验证码
const sendValidationCode = async () => {
  if (!state.ruleForm.phone) {
    return message("请先输入手机号", { type: "warning" });
@@ -231,26 +340,12 @@
    <div class="wave">
      <img width="400px" :src="logo1" class="logo1" />
    </div>
    <!-- <img :src="bg" class="wave" /> -->
    <div class="flex-c absolute right-5 top-3">
      <!-- 主题 -->
      <el-switch
        v-model="dataTheme"
        inline-prompt
        :active-icon="dayIcon"
        :inactive-icon="darkIcon"
        @change="dataThemeChange"
      />
    </div>
    <div class="login-container">
      <div class="img">
        <!-- <component :is="toRaw(illustration)" /> -->
      </div>
      <div class="img" />
      <div class="login-box">
        <div class="login-form">
          <!-- <avatar class="avatar" /> -->
          <Motion>
            <h2 class="logintitle">{{ state.nowRole.name }}登录</h2>
            <h2 class="logintitle">登录</h2>
          </Motion>
          <el-form
@@ -259,18 +354,6 @@
            :rules="loginRules"
            size="large"
          >
            <!-- <Motion :delay="150">
              <el-form-item prop="exRoleCode">
                <el-radio-group v-model="state.ruleForm.exRoleCode">
                  <el-radio
                    v-for="item in state.roleList"
                    :key="item.id"
                    :value="item.code"
                    >{{ item.name }}</el-radio
                  >
                </el-radio-group>
              </el-form-item>
            </Motion> -->
            <Motion :delay="100">
              <el-form-item
                :rules="[
@@ -323,16 +406,6 @@
                  </div>
                </el-col>
              </el-form-item>
              <!-- <el-form-item prop="password">
                <el-input
                  v-model="ruleForm.password"
                  clearable
                  show-password
                  placeholder="密码"
                  :prefix-icon="useRenderIcon(Lock)"
                />
              </el-form-item> -->
            </Motion>
            <Motion :delay="150">
              <el-form-item prop="phoneVCode">
@@ -346,7 +419,7 @@
                      <span
                        id="suffix-span-2"
                        ref="spanRef"
                        @click="sendValidationCode(state.ruleForm.phone)"
                        @click="sendValidationCode"
                      >
                        获取验证码
                      </span>