ZZJ
2021-12-16 dff9fb32c1bac52d378a6d196f670b92610c01d3
自适应2
5个文件已修改
2880 ■■■■ 已修改文件
src/pages/index/App.vue 625 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/index/components/formAccount.vue 266 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/index/components/formInfo.vue 523 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/login/App.vue 1154 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 312 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/index/App.vue
@@ -1,311 +1,316 @@
<template>
  <div class="init" v-if="!isWhite">
    <img class="img-test" onerror="console.log('网络故障')" />
    <div class="content">
      <div class="title">欢迎注册Smart AI 人工智能操作系统</div>
      <el-steps :active="active" finish-status="success" :align-center="true">
        <el-step title="创建账号"></el-step>
        <el-step title="配置网络"></el-step>
        <el-step title="注册信息"></el-step>
      </el-steps>
      <el-carousel
        ref="carousel"
        trigger="click"
        height="480px"
        :loop="false"
        :autoplay="false"
        :initial-index="active"
      >
        <el-carousel-item>
          <formAccount ref="form0"></formAccount>
        </el-carousel-item>
        <el-carousel-item>
          <formNet ref="form1"></formNet>
        </el-carousel-item>
        <el-carousel-item>
          <formInfo ref="form2"></formInfo>
        </el-carousel-item>
      </el-carousel>
      <div class="control">
        <div class="pre" @click="preForm">上一步</div>
        <div class="next" @click="nextForm" v-if="active == 0">下一步</div>
        <div class="next" @click="nextFormNot" v-if="active == 1">跳过</div>
        <div class="next" @click="nextForm" v-if="active == 1 && !isNet">
          下一步
        </div>
        <div class="next" @click="nextForm" v-if="active == 2">完成</div>
      </div>
    </div>
  </div>
  <div class="white" v-else></div>
</template>
<script>
import formAccount from "@/pages/index/components/formAccount";
import formNet from "@/pages/index/components/formNet";
import formInfo from "@/pages/index/components/formInfo";
import {
  getInitInfo,
  savePassword,
  initNetwork,
  saveRegInfo,
  getRegInfo,
  isOnNet,
} from "./api";
export default {
  mounted() {
    this.getInitInfo();
    let message = "网络正常";
    function onLine(callback) {
      var img = new Image();
      //临时判断网络是否通畅
      img.src = "http://apps.smartai.com/img/icon_logo.f78688b5.png";
      img.onload = function () {
        console.log("11111");
        if (callback) callback(true);
      };
      img.onerror = function () {
        console.log("22222");
        if (callback) callback(false);
      };
    }
    onLine((flag) => {
      let message = "";
      if (flag) {
        this.isNet = true;
        message = "已有网络";
      } else {
        //网络断网效果图出来后,将此地改为跳转路径到效果图上
        message = "未配置网络";
        this.$notify({
          message: message,
        });
      }
    });
  },
  data() {
    return {
      active: 0,
      formData: {},
      isWhite: true,
      isNet: false,
    };
  },
  components: {
    formAccount,
    formNet,
    formInfo,
  },
  methods: {
    preForm() {
      if (this.active == 0) {
        return;
      }
      this.active--;
      this.$refs["carousel"].prev();
    },
    async nextForm() {
      if (this.active == 2) {
        const data = this.$refs[`form${this.active}`].getFormData();
        await saveRegInfo(data);
        location.assign("/view/login/");
        return;
      }
      if (this.active == 0) {
        const data = this.$refs[`form${this.active}`].getFormData();
        if (!data) {
          return false;
        }
        const res1 = await savePassword(data);
        console.log(data);
        this.active++;
        this.$refs["carousel"].next();
      }
      if (this.active == 1) {
        const data = this.$refs[`form${this.active}`].getFormData();
        initNetwork(data);
        this.active++;
        this.$refs["carousel"].next();
      }
    },
    nextFormNot() {
      this.active++;
      this.$refs["carousel"].next();
    },
    async getInitInfo() {
      const res = await getInitInfo();
      if (res.data.initPwd && !res.data.initRegInfo) {
        const res1 = await getRegInfo();
        this.active = 1;
        console.log(res1);
        setTimeout(() => {
          this.$refs["carousel"].setActiveItem(1);
        }, 0);
      }
      /* if (res.data.initPwd && res.data.initRegInfo) {
        location.assign("/login");
        return;
      } */
      this.isWhite = false;
    },
  },
};
</script>
<style lang="scss" scoped>
.init {
  height: 100%;
  background-image: url("/images/init/背景图.png");
  color: #fff;
  user-select: none;
  .content {
    margin: 0 auto;
    width: 1000px;
    padding-top: 80px;
    .title {
      font-size: 28px;
      font-weight: 700;
      margin-bottom: 50px;
      letter-spacing: 5px;
    }
    .el-steps ::v-deep {
      margin-left: 22px;
      text-align: left;
      .el-step__icon {
        width: 48px;
        height: 48px;
      }
      .el-step__line {
        left: 210px;
        right: -110px;
        border: 0.5px solid #fff;
        border-bottom: none;
        border-top: none;
        opacity: 0.1;
        top: 22px;
      }
      .is-success .el-step__icon {
        background: none;
        border: 2px solid rgba(255, 255, 255, 0.3);
        .el-icon-check::before {
          color: #fff;
          font-size: 24px;
          font-weight: 700;
        }
      }
      .is-process .el-step__icon {
        background-color: rgba(255, 255, 255, 0.3);
        border: none;
        .el-step__icon-inner {
          color: #fff;
          font-size: 24px;
          font-weight: 700;
        }
      }
      .is-wait .el-step__icon {
        border: 2px solid rgba(255, 255, 255);
        opacity: 0.5;
        background: none;
        .el-step__icon-inner {
          color: #fff;
          font-size: 24px;
          font-weight: 700;
        }
      }
      .el-step__main {
        margin-top: 20px;
        .is-success,
        .is-process {
          font-size: 16px;
          color: #fff;
          font-weight: normal;
        }
        .is-wait {
          font-size: 16px;
          color: #fff;
          font-weight: normal;
          opacity: 0.5;
        }
      }
    }
    .formAccount {
      margin-top: 0.81rem;
      margin-left: 200px;
      width: 550px;
    }
    .formNet,
    .formInfo {
      margin-top: 0.47rem;
      margin-left: 200px;
      width: 550px;
    }
    .control {
      position: fixed;
      top: 80%;
      left: 0;
      right: 0;
      line-height: 40px;
      .pre {
        margin: 10px auto;
        cursor: pointer;
        width: 260px;
        height: 40px;
        border: 2px solid rgba(255, 255, 255, 0.3);
        border-radius: 20px;
        font-weight: bold;
        color: #ffffff;
      }
      .next {
        margin: 10px auto;
        cursor: pointer;
        width: 260px;
        height: 40px;
        background: rgba(255, 255, 255, 0.3);
        border-radius: 20px;
        font-weight: bold;
        color: #ffffff;
      }
    }
  }
  ::v-deep .el-carousel__indicators {
    display: none;
  }
  ::v-deep .el-carousel__container button {
    display: none;
  }
}
.white {
  height: 100%;
  background-color: #fff;
}
<template>
  <div class="init" v-if="!isWhite">
    <img class="img-test" onerror="console.log('网络故障')" />
    <div class="content">
      <div class="title">欢迎注册Smart AI 人工智能操作系统</div>
      <el-steps :active="active" finish-status="success" :align-center="true">
        <el-step title="创建账号"></el-step>
        <el-step title="配置网络"></el-step>
        <el-step title="注册信息"></el-step>
      </el-steps>
      <el-carousel
        ref="carousel"
        trigger="click"
        :loop="false"
        :autoplay="false"
        :initial-index="active"
      >
        <el-carousel-item>
          <formAccount ref="form0"></formAccount>
        </el-carousel-item>
        <el-carousel-item>
          <formNet ref="form1"></formNet>
        </el-carousel-item>
        <el-carousel-item>
          <formInfo ref="form2"></formInfo>
        </el-carousel-item>
      </el-carousel>
      <div class="control">
        <div class="pre" @click="preForm">上一步</div>
        <div class="next" @click="nextForm" v-if="active == 0">下一步</div>
        <div class="next" @click="nextFormNot" v-if="active == 1">跳过</div>
        <div class="next" @click="nextForm" v-if="active == 1 && !isNet">
          下一步
        </div>
        <div class="next" @click="nextForm" v-if="active == 2">完成</div>
      </div>
    </div>
  </div>
  <div class="white" v-else></div>
</template>
<script>
import formAccount from "@/pages/index/components/formAccount";
import formNet from "@/pages/index/components/formNet";
import formInfo from "@/pages/index/components/formInfo";
import {
  getInitInfo,
  savePassword,
  initNetwork,
  saveRegInfo,
  getRegInfo,
  isOnNet,
} from "./api";
export default {
  mounted() {
    this.getInitInfo();
    let message = "网络正常";
    function onLine(callback) {
      var img = new Image();
      //临时判断网络是否通畅
      img.src = "http://apps.smartai.com/img/icon_logo.f78688b5.png";
      img.onload = function () {
        console.log("11111");
        if (callback) callback(true);
      };
      img.onerror = function () {
        console.log("22222");
        if (callback) callback(false);
      };
    }
    onLine((flag) => {
      let message = "";
      if (flag) {
        this.isNet = true;
        message = "已有网络";
      } else {
        //网络断网效果图出来后,将此地改为跳转路径到效果图上
        message = "未配置网络";
        this.$notify({
          message: message,
        });
      }
    });
  },
  data() {
    return {
      active: 0,
      formData: {},
      isWhite: true,
      isNet: false,
    };
  },
  components: {
    formAccount,
    formNet,
    formInfo,
  },
  methods: {
    preForm() {
      if (this.active == 0) {
        return;
      }
      this.active--;
      this.$refs["carousel"].prev();
    },
    async nextForm() {
      if (this.active == 2) {
        const data = this.$refs[`form${this.active}`].getFormData();
        await saveRegInfo(data);
        location.assign("/view/login/");
        return;
      }
      if (this.active == 0) {
        const data = this.$refs[`form${this.active}`].getFormData();
        if (!data) {
          return false;
        }
        const res1 = await savePassword(data);
        console.log(data);
        this.active++;
        this.$refs["carousel"].next();
      }
      if (this.active == 1) {
        const data = this.$refs[`form${this.active}`].getFormData();
        initNetwork(data);
        this.active++;
        this.$refs["carousel"].next();
      }
    },
    nextFormNot() {
      this.active++;
      this.$refs["carousel"].next();
    },
    async getInitInfo() {
      const res = await getInitInfo();
      if (res.data.initPwd && !res.data.initRegInfo) {
        const res1 = await getRegInfo();
        this.active = 1;
        console.log(res1);
        setTimeout(() => {
          this.$refs["carousel"].setActiveItem(1);
        }, 0);
      }
      /* if (res.data.initPwd && res.data.initRegInfo) {
        location.assign("/login");
        return;
      } */
      this.isWhite = false;
    },
  },
};
</script>
<style lang="scss" scoped>
.init {
  background-image: url("/images/init/背景图.png");
  background-size: cover;
  background-attachment: fixed;
  color: #fff;
  user-select: none;
  height: 100%;
  min-width: 1000px;
  overflow: hidden;
  min-height: 760px;
  .content {
    margin: 0 auto;
    width: 1000px;
    padding-top: calc(6.4vh);
    .title {
      font-size: 28px;
      font-weight: 700;
      margin-bottom: 50px;
      letter-spacing: 5px;
    }
    .el-steps ::v-deep {
      margin-left: 22px;
      text-align: left;
      .el-step__icon {
        width: 48px;
        height: 48px;
      }
      .el-step__line {
        left: 210px;
        right: -110px;
        border: 0.5px solid #fff;
        border-bottom: none;
        border-top: none;
        opacity: 0.1;
        top: 22px;
      }
      .is-success .el-step__icon {
        background: none;
        border: 2px solid rgba(255, 255, 255, 0.3);
        .el-icon-check::before {
          color: #fff;
          font-size: 24px;
          font-weight: 700;
        }
      }
      .is-process .el-step__icon {
        background-color: rgba(255, 255, 255, 0.3);
        border: none;
        .el-step__icon-inner {
          color: #fff;
          font-size: 24px;
          font-weight: 700;
        }
      }
      .is-wait .el-step__icon {
        border: 2px solid rgba(255, 255, 255);
        opacity: 0.5;
        background: none;
        .el-step__icon-inner {
          color: #fff;
          font-size: 24px;
          font-weight: 700;
        }
      }
      .el-step__main {
        margin-top: 20px;
        .is-success,
        .is-process {
          font-size: 16px;
          color: #fff;
          font-weight: normal;
        }
        .is-wait {
          font-size: 16px;
          color: #fff;
          font-weight: normal;
          opacity: 0.5;
        }
      }
    }
    .formAccount {
      margin-left: 200px;
      width: 550px;
    }
    .formNet,
    .formInfo {
      margin-left: 200px;
      width: 550px;
    }
    .control {
      margin: 0 auto;
      line-height: 40px;
      margin-top: calc(3.2vh);
      .pre {
        margin: 10px auto;
        cursor: pointer;
        width: 260px;
        height: 40px;
        border: 2px solid rgba(255, 255, 255, 0.3);
        border-radius: 20px;
        font-weight: bold;
        color: #ffffff;
      }
      .next {
        margin: 10px auto;
        cursor: pointer;
        width: 260px;
        height: 40px;
        background: rgba(255, 255, 255, 0.3);
        border-radius: 20px;
        font-weight: bold;
        color: #ffffff;
      }
    }
  }
  ::v-deep .el-carousel__indicators {
    display: none;
  }
  ::v-deep .el-carousel__container button {
    display: none;
  }
  ::v-deep .el-carousel__container {
    margin-top: calc(5.74vh);
    height: 290px !important;
  }
}
.white {
  height: 100%;
  background-color: #fff;
}
</style>
src/pages/index/components/formAccount.vue
@@ -1,134 +1,134 @@
<template>
  <div class="formAccount">
    <el-form ref="form" :model="form" label-width="90px" :rules="rules">
      <el-form-item label="用户名" prop="username">
        <el-input
          v-model="form.username"
          placeholder="2-10位字符,不能以数字开头,不可包含汉字"
        ></el-input>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input
          v-model="form.password"
          placeholder="至少为6位字符"
          type="password"
        ></el-input>
      </el-form-item>
      <el-form-item label="确认密码" prop="repassword">
        <el-input
          v-model="form.repassword"
          placeholder="请确认密码"
          type="password"
        ></el-input>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
import { getRegInfo } from "../api";
export default {
  data() {
    const validateName = (rule, value, callback) => {
      var reg = /^[A-Za-z][A-Za-z0-9]{0,}$/;
      if (!reg.test(value)) {
        return callback(new Error("不能以数字开头,不可包含汉字"));
      } else callback();
    };
    const validateRePass = (rule, value, callback) => {
      if (this.form.password != value) {
        return callback(new Error("两次密码不一致"));
      } else callback();
    };
    return {
      form: {
        username: "",
        password: "",
        repassword: "",
      },
      rules: {
        name: [
          { required: true, message: "请输入用户名", trigger: "blur" },
          {
            min: 2,
            max: 10,
            message: "长度在 2 到 10 个字符",
            trigger: "blur",
          },
          { validator: validateName, trigger: "blur" },
        ],
        password: [
          { required: true, message: "请输入密码", trigger: "blur" },
          {
            min: 6,
            max: 24,
            message: "至少为6位字符",
            trigger: "blur",
          },
        ],
        repassword: [
          { required: true, message: "请确认密码", trigger: "blur" },
          { validator: validateRePass, trigger: "blur" },
        ],
      },
    };
  },
  methods: {
    getFormData() {
      const _this = this;
      let data = null;
      this.$refs["form"].validate((valid) => {
        if (valid) {
          data = _this.form;
        } else {
          return false;
        }
      });
      return data;
    },
    async getRegInfo() {
      const res = await getRegInfo();
      console.log(res);
    },
  },
};
</script>
<style lang="scss" scoped>
.formAccount {
  .el-form-item ::v-deep {
    label {
      font-size: 14px;
      color: #fff;
      text-align: left;
    }
    .el-form-item__content {
      margin-left: 110px !important;
    }
    input {
      background-color: rgba(0, 0, 0, 0.1);
      color: #fff;
      border: none;
      caret-color: #fff !important;
    }
    input:-webkit-autofill,
    textarea:-webkit-autofill,
    select:-webkit-autofill {
      -webkit-text-fill-color: #fff !important;
      -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
      background-color: transparent;
      background-image: none;
      transition: background-color 50000s ease-in-out 0s; //背景色透明  生效时长  过渡效果  启用时延迟的时间
    }
  }
}
<template>
  <div class="formAccount">
    <el-form ref="form" :model="form" label-width="90px" :rules="rules">
      <el-form-item label="用户名" prop="username">
        <el-input
          v-model="form.username"
          placeholder="2-10位字符,不能以数字开头,不可包含汉字"
        ></el-input>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input
          v-model="form.password"
          placeholder="至少为6位字符"
          type="password"
        ></el-input>
      </el-form-item>
      <el-form-item label="确认密码" prop="repassword">
        <el-input
          v-model="form.repassword"
          placeholder="请确认密码"
          type="password"
        ></el-input>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
import { getRegInfo } from "../api";
export default {
  data() {
    const validateName = (rule, value, callback) => {
      var reg = /^[A-Za-z][A-Za-z0-9]{0,}$/;
      if (!reg.test(value)) {
        return callback(new Error("不能以数字开头,不可包含汉字"));
      } else callback();
    };
    const validateRePass = (rule, value, callback) => {
      if (this.form.password != value) {
        return callback(new Error("两次密码不一致"));
      } else callback();
    };
    return {
      form: {
        username: "",
        password: "",
        repassword: "",
      },
      rules: {
        username: [
          { required: true, message: "请输入用户名", trigger: "blur" },
          {
            min: 2,
            max: 10,
            message: "长度在 2 到 10 个字符",
            trigger: "blur",
          },
          { validator: validateName, trigger: "blur" },
        ],
        password: [
          { required: true, message: "请输入密码", trigger: "blur" },
          {
            min: 6,
            max: 24,
            message: "至少为6位字符",
            trigger: "blur",
          },
        ],
        repassword: [
          { required: true, message: "请确认密码", trigger: "blur" },
          { validator: validateRePass, trigger: "blur" },
        ],
      },
    };
  },
  methods: {
    getFormData() {
      const _this = this;
      let data = null;
      this.$refs["form"].validate((valid) => {
        if (valid) {
          data = _this.form;
        } else {
          return false;
        }
      });
      return data;
    },
    async getRegInfo() {
      const res = await getRegInfo();
      console.log(res);
    },
  },
};
</script>
<style lang="scss" scoped>
.formAccount {
  .el-form-item ::v-deep {
    label {
      font-size: 14px;
      color: #fff;
      text-align: left;
    }
    .el-form-item__content {
      margin-left: 110px !important;
    }
    input {
      background-color: rgba(0, 0, 0, 0.1);
      color: #fff;
      border: none;
      caret-color: #fff !important;
    }
    input:-webkit-autofill,
    textarea:-webkit-autofill,
    select:-webkit-autofill {
      -webkit-text-fill-color: #fff !important;
      -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
      background-color: transparent;
      background-image: none;
      transition: background-color 50000s ease-in-out 0s; //背景色透明  生效时长  过渡效果  启用时延迟的时间
    }
  }
}
</style>
src/pages/index/components/formInfo.vue
@@ -1,259 +1,266 @@
<template>
  <div class="formInfo">
    <el-form ref="form" :model="form" label-width="90px" :rules="rules">
      <el-form-item label="类型" prop="type">
        <el-radio v-model="form.userType" label="personal">个人</el-radio>
        <el-radio v-model="form.userType" label="company">公司</el-radio>
      </el-form-item>
      <el-form-item
        label="公司名称"
        prop="name1"
        v-if="form.userType == 'company'"
      >
        <el-input v-model="form.name1" placeholder="请输入公司名称"></el-input>
      </el-form-item>
      <el-form-item
        label="联系人姓名"
        prop="name2"
        v-if="form.userType == 'company'"
      >
        <el-input
          v-model="form.name2"
          placeholder="请输入联系人姓名"
        ></el-input>
      </el-form-item>
      <el-form-item label="姓名" prop="name" v-else>
        <el-input v-model="form.name" placeholder="请输入姓名"></el-input>
      </el-form-item>
      <el-form-item label="所在地" prop="addr">
        <el-cascader
          :props="props"
          popper-class="location"
          separator=" "
          @change="handleChange"
          v-model="form.addr"
        ></el-cascader>
      </el-form-item>
      <el-form-item label="邮箱" prop="email">
        <el-input v-model="form.email" placeholder="请输入邮箱"></el-input>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
import { getList } from "../api";
export default {
  created() {},
  data() {
    return {
      form: {
        userType: "personal",
        name: "",
        name1: "",
        name2: "",
        email: "",
        addr: "",
        provinceId: "",
        cityId: "",
        labelList: "",
      },
      rules: {
        name1: [{ required: true, message: "请输入公司名称", trigger: "blur" }],
        name2: [
          { required: true, message: "请输入联系人姓名", trigger: "blur" },
        ],
        name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
        addr: [{ required: true, message: "请选择所在地", trigger: "blur" }],
        email: [{ required: true, message: "请输入邮箱", trigger: "blur" }],
      },
      provinceOptions: [],
      props: {
        lazy: true, // 开启动态加载
        lazyLoad: async (node, resolve) => {
          // 设置加载数据源方法 默认执行一次
          // node 为当前点击的节点
          // resolve 为数据加载完成的回调(必须调用)
          /* node此时属性为:
                  当前叶子  level:0
                  loaded:true
                  loading:false
                  是否是根  root:ture
              */
          console.log(node);
          if (node.level == 0) {
            const res = await getList();
            this.provinceOptions = res.data.map((item) => {
              return {
                value: item.id,
                label: item.name, // 选项名
                leaf: false, // 是否为末尾
              };
            });
            resolve(this.provinceOptions);
            console.log(node.level);
          }
          if (node.level == 1) {
            console.log("-------------");
            this.provinceId = node.value;
            const res2 = await getList({
              parentId: node.value,
            });
            const arr = res2.data.map((item) => {
              return {
                value: item.id,
                label: item.name, // 选项名
                leaf: true, // 是否为末尾
              };
            });
            resolve(arr);
          } else {
            console.log(node);
          }
        },
      },
      value: [],
    };
  },
  methods: {
    getFormData() {
      const _this = this;
      let data = null;
      this.$refs["form"].validate((valid) => {
        if (valid) {
          console.log(_this.form.userType);
          if (_this.form.userType == "personal") {
            data = {
              userType: _this.form.userType,
              name: _this.form.name,
              email: _this.form.email,
              addr: _this.form.labelList,
              provinceId: _this.form.provinceId,
              cityId: _this.form.cityId,
            };
          } else {
            data = {
              userType: _this.form.userType,
              name: _this.form.name1 + " " + _this.form.name2,
              email: _this.form.email,
              addr: _this.form.labelList,
              provinceId: _this.form.provinceId,
              cityId: _this.form.cityId,
            };
          }
        } else {
          return false;
        }
      });
      return data;
    },
    handleChange(val) {
      this.form.provinceId = val[0] + "";
      this.form.cityId = val[1] + "";
      setTimeout(() => {
        this.form.labelList =
          document.querySelectorAll(".el-cascader input")[0].value;
      }, 200);
    },
  },
};
</script>
<style lang="scss" scoped>
.formInfo {
  .el-form-item ::v-deep {
    label {
      font-size: 14px;
      color: #fff;
      text-align: left;
    }
    .el-radio {
      .el-radio__inner {
        background: none;
        border-color: rgba(255, 255, 255, 0.3) !important;
        &::after {
          width: 6px;
          height: 6px;
        }
      }
      .el-radio__label {
        color: #fff !important;
      }
    }
    .el-form-item__content {
      margin-left: 110px !important;
      text-align: left;
    }
    input {
      background-color: rgba(0, 0, 0, 0.1);
      color: #fff;
      border: none;
      caret-color: #fff !important;
    }
    input:-webkit-autofill,
    textarea:-webkit-autofill,
    select:-webkit-autofill {
      -webkit-text-fill-color: #fff !important;
      -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
      background-color: transparent;
      background-image: none;
      transition: background-color 50000s ease-in-out 0s; //背景色透明  生效时长  过渡效果  启用时延迟的时间
    }
    .el-cascader {
      width: 100%;
    }
  }
}
</style>
<style lang="scss">
.el-popper.el-cascader__dropdown.location {
  background-color: rgb(77, 72, 111);
  border: none;
  margin: 0 0;
  * {
    color: #fff;
    border-color: rgba(255, 255, 2555, 0.1);
  }
  .el-cascader-node:hover,
  .in-active-path,
  .is-active,
  .el-cascader-node {
    background-color: rgb(101, 93, 126) !important;
  }
  .popper__arrow::after,
  .popper__arrow {
    display: none;
  }
  .el-cascader-node__label {
    text-align: left;
  }
  .el-cascader-menu__wrap {
    width: 226px;
    height: 175px;
  }
}
<template>
  <div class="formInfo">
    <el-form ref="form" :model="form" label-width="90px" :rules="rules">
      <el-form-item label="类型" prop="type">
        <el-radio v-model="form.userType" label="personal">个人</el-radio>
        <el-radio v-model="form.userType" label="company">公司</el-radio>
      </el-form-item>
      <el-form-item
        label="公司名称"
        prop="name1"
        v-if="form.userType == 'company'"
      >
        <el-input v-model="form.name1" placeholder="请输入公司名称"></el-input>
      </el-form-item>
      <el-form-item
        label="联系人姓名"
        prop="name2"
        v-if="form.userType == 'company'"
      >
        <el-input
          v-model="form.name2"
          placeholder="请输入联系人姓名"
        ></el-input>
      </el-form-item>
      <el-form-item label="姓名" prop="name" v-else>
        <el-input v-model="form.name" placeholder="请输入姓名"></el-input>
      </el-form-item>
      <el-form-item label="所在地" prop="addr">
        <el-cascader
          :props="props"
          popper-class="location"
          separator=" "
          @change="handleChange"
          v-model="form.addr"
        ></el-cascader>
      </el-form-item>
      <el-form-item label="邮箱" prop="email">
        <el-input v-model="form.email" placeholder="请输入邮箱"></el-input>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
import { getList } from "../api";
export default {
  created() {},
  data() {
    return {
      form: {
        userType: "personal",
        name: "",
        name1: "",
        name2: "",
        email: "",
        addr: "",
        provinceId: "",
        cityId: "",
        labelList: "",
      },
      rules: {
        name1: [{ required: true, message: "请输入公司名称", trigger: "blur" }],
        name2: [
          { required: true, message: "请输入联系人姓名", trigger: "blur" },
        ],
        name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
        addr: [{ required: true, message: "请选择所在地", trigger: "blur" }],
        email: [
          { required: true, message: "请输入邮箱", trigger: "blur" },
          {
            type: "email",
            message: "邮箱格式有误",
            trigger: "blur",
          },
        ],
      },
      provinceOptions: [],
      props: {
        lazy: true, // 开启动态加载
        lazyLoad: async (node, resolve) => {
          // 设置加载数据源方法 默认执行一次
          // node 为当前点击的节点
          // resolve 为数据加载完成的回调(必须调用)
          /* node此时属性为:
                  当前叶子  level:0
                  loaded:true
                  loading:false
                  是否是根  root:ture
              */
          console.log(node);
          if (node.level == 0) {
            const res = await getList();
            this.provinceOptions = res.data.map((item) => {
              return {
                value: item.id,
                label: item.name, // 选项名
                leaf: false, // 是否为末尾
              };
            });
            resolve(this.provinceOptions);
            console.log(node.level);
          }
          if (node.level == 1) {
            console.log("-------------");
            this.provinceId = node.value;
            const res2 = await getList({
              parentId: node.value,
            });
            const arr = res2.data.map((item) => {
              return {
                value: item.id,
                label: item.name, // 选项名
                leaf: true, // 是否为末尾
              };
            });
            resolve(arr);
          } else {
            console.log(node);
          }
        },
      },
      value: [],
    };
  },
  methods: {
    getFormData() {
      const _this = this;
      let data = null;
      this.$refs["form"].validate((valid) => {
        if (valid) {
          console.log(_this.form.userType);
          if (_this.form.userType == "personal") {
            data = {
              userType: _this.form.userType,
              name: _this.form.name,
              email: _this.form.email,
              addr: _this.form.labelList,
              provinceId: _this.form.provinceId,
              cityId: _this.form.cityId,
            };
          } else {
            data = {
              userType: _this.form.userType,
              name: _this.form.name1 + " " + _this.form.name2,
              email: _this.form.email,
              addr: _this.form.labelList,
              provinceId: _this.form.provinceId,
              cityId: _this.form.cityId,
            };
          }
        } else {
          return false;
        }
      });
      return data;
    },
    handleChange(val) {
      this.form.provinceId = val[0] + "";
      this.form.cityId = val[1] + "";
      setTimeout(() => {
        this.form.labelList =
          document.querySelectorAll(".el-cascader input")[0].value;
      }, 200);
    },
  },
};
</script>
<style lang="scss" scoped>
.formInfo {
  .el-form-item ::v-deep {
    label {
      font-size: 14px;
      color: #fff;
      text-align: left;
    }
    .el-radio {
      .el-radio__inner {
        background: none;
        border-color: rgba(255, 255, 255, 0.3) !important;
        &::after {
          width: 6px;
          height: 6px;
        }
      }
      .el-radio__label {
        color: #fff !important;
      }
    }
    .el-form-item__content {
      margin-left: 110px !important;
      text-align: left;
    }
    input {
      background-color: rgba(0, 0, 0, 0.1);
      color: #fff;
      border: none;
      caret-color: #fff !important;
    }
    input:-webkit-autofill,
    textarea:-webkit-autofill,
    select:-webkit-autofill {
      -webkit-text-fill-color: #fff !important;
      -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
      background-color: transparent;
      background-image: none;
      transition: background-color 50000s ease-in-out 0s; //背景色透明  生效时长  过渡效果  启用时延迟的时间
    }
    .el-cascader {
      width: 100%;
    }
  }
}
</style>
<style lang="scss">
.el-popper.el-cascader__dropdown.location {
  background-color: rgb(77, 72, 111);
  border: none;
  margin: 0 0;
  * {
    color: #fff;
    border-color: rgba(255, 255, 2555, 0.1);
  }
  .el-cascader-node:hover,
  .in-active-path,
  .is-active,
  .el-cascader-node {
    background-color: rgb(101, 93, 126) !important;
  }
  .popper__arrow::after,
  .popper__arrow {
    display: none;
  }
  .el-cascader-node__label {
    text-align: left;
  }
  .el-cascader-menu__wrap {
    width: 226px;
    height: 175px;
  }
}
</style>
src/pages/login/App.vue
@@ -1,577 +1,577 @@
<template>
  <!-- <div class v-loading="vLoading" :style="`width: ${currentWidth}px;height:${currentHeight}px`">
    <div class="web-site">
      <a href="http://www.smartai.com" target="_blank">www.smartai.com</a>
    </div>
    <lang-select class="lang-select"/>
    <licence />
    <div class="right-bg" style>
      <particle-network />
    </div>
    <div class="left-bg">
      <div class="login-logo">
        <img src="/images/login-logo.png" alt width="105px" height="105px" />
      </div>
      <div class="login-com">
        <span>{{ $t('login.company') }}</span>
      </div>
      <div class="login-form">
        <el-form
          :model="user"
          status-icon
          :rules="nullRule"
          :validate-on-rule-change="false"
          ref="ruleForm"
          class="demo-ruleForm"
        >
          <el-form-item prop="loginName">
            <el-input v-model="user.loginName" style="width:280px" :placeholder="$t('placeholder.enterUsername')">
              <i slot="prefix" class="iconfont iconyonghu1"></i>
            </el-input>
          </el-form-item>
          <el-form-item prop="password">
            <el-input
              show-password
              @keyup.enter.native="systemLogin()"
              v-model="user.password"
              autocomplete="off"
              style="width:280px"
              :placeholder="$t('placeholder.enterPassword')"
            >
              <i slot="prefix" class="iconfont iconmima"></i>
            </el-input>
          </el-form-item>
          <el-form-item>
            <el-button ref="submit" type="warning" @click="systemLogin()" style="width:280px">{{ $t('button.login') }}</el-button>
          </el-form-item>
        </el-form>
      </div>
      <p class="gradient-text gradient-text-one">
        ——
        <b>SmartAI</b> {{ $t('login.aios') }} ——
      </p>
      <p
        class="gradient-text gradient-text-one"
        style="letter-spacing: 1.8px;font-size:15px;"
      >V1.0.0</p>
    </div>
  </div> -->
  <div class="login">
    <div class="title">
      <div class="en">{{ data.title_firstLine }}</div>
      <div class="ch">{{ data.title_secondLine }}</div>
    </div>
    <div class="left_footer">
      <img class="logo" src="/apps/loginData/LOGO.png" alt="" />
      <div class="web">{{ data.website }}</div>
    </div>
    <div
      class="login-form"
      :style="{ background: backgroundColor }"
      :class="{ empty: !user.loginName && !user.password }"
    >
      <img class="logo" src="/apps/loginData/leftImg.png" alt="" />
      <el-form
        :model="user"
        status-icon
        :rules="nullRule"
        :validate-on-rule-change="false"
        ref="ruleForm"
        class="demo-ruleForm"
      >
        <el-form-item prop="loginName">
          <el-input
            v-model="user.loginName"
            :placeholder="$t('placeholder.enterUsername')"
          >
            <i slot="prefix" class="iconfont icon">&#xe7e5;</i>
          </el-input>
        </el-form-item>
        <el-form-item prop="password">
          <el-input
            show-password
            @keyup.enter.native="systemLogin()"
            v-model="user.password"
            autocomplete="off"
            :placeholder="$t('placeholder.enterPassword')"
          >
            <i slot="prefix" class="iconfont icon">&#xe7e4;</i>
          </el-input>
        </el-form-item>
        <el-form-item>
          <el-button ref="submit" type="warning" @click="systemLogin()">{{
            $t("button.login")
          }}</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>
<script>
import { tologin, getLoginUserData, getServerName } from "./api.ts";
import ParticleNetwork from "./ParticleNetwork";
import Licence from "@/components/licence";
import LangSelect from "@/components/langSelect";
import { getMenuListData } from "@/api/utils";
import loginData from "../../../public/apps/loginData/login.json";
export default {
  name: "login-pgae",
  metaInfo: {
    title: "登录页",
  },
  components: {
    //  ParticleNetwork,
    // Licence,
    //  LangSelect
  },
  computed: {
    rules() {
      return {
        loginName: [
          {
            required: true,
            message: this.$t("placeholder.enterUsername"),
            trigger: "change",
          },
        ],
        password: [
          {
            required: true,
            message: this.$t("placeholder.enterPassword"),
            trigger: "change",
          },
        ],
      };
    },
  },
  data: () => ({
    data: {},
    serverTitle: "",
    user: {
      loginName: "",
      password: "",
      rememberMe: false,
    },
    nullRule: {},
    loading: "",
    vLoading: false,
    currentHeight: 1057,
    currentWidth: 1920,
    backgroundColor: "",
    backgroundList: [
      "#2A2344",
      "#342344",
      "#000000",
      "#233044",
      "#0B252E",
      "#150051",
      "#110040",
    ],
  }),
  created() {
    this.getServerName();
    this.getScreenHeight();
    this.data = loginData;
    this.backgroundColor =
      this.backgroundList[
        Math.floor(Math.random() * this.backgroundList.length)
      ];
  },
  mounted() {
    // 自动登录接口
    this.loginRobot();
  },
  watch: {},
  beforeDestroy() {
    window.onresize = null;
  },
  methods: {
    loginRobot() {
      // 解析路由参数,并缓存
      let user = this.getQueryVariable("username");
      let passwd = this.getQueryVariable("password");
      if (user.length && passwd.length) {
        sessionStorage.setItem(
          "autoLogin",
          JSON.stringify({ username: user, passwd: passwd })
        );
        this.user.loginName = user;
        this.user.password = passwd;
        this.systemLogin();
        return;
      }
      // 登陆超时后的重新登陆
      let sessionInfo = sessionStorage.getItem("autoLogin");
      if (sessionInfo) {
        let authority = JSON.parse(sessionInfo);
        this.user.loginName = authority.username;
        this.user.password = authority.passwd;
        this.systemLogin();
      }
    },
    systemLogin() {
      this.nullRule = this.rules;
      this.$nextTick(() => {
        this.$refs["ruleForm"].validate((valid) => {
          if (valid) {
            this.loading = this.$loading({
              lock: true,
              text: "Loading",
              spinner: "el-icon-loading",
              background: "rgba(0, 0, 0, 0.7)",
            });
            this.testLogin();
          } else {
            this.nullRule = {};
          }
        });
        this.nullRule = {};
      });
    },
    async testLogin() {
      // location.assign("/view/desktop/")
      tologin({ username: this.user.loginName, password: this.user.password })
        .then((json) => {
          const loginedInfo = {
            access_token: json.token_type + " " + json.access_token,
            refresh_token: json.refresh_token,
          };
          sessionStorage.setItem("expires_in", json.expires_in);
          sessionStorage.setItem("loginedInfo", JSON.stringify(loginedInfo));
          this.loading.close();
          this.getLoginUserData();
        })
        .catch((err) => {
          this.loading.close();
          this.$notify({
            title: "提示",
            type: "error",
            message: err.msg,
          });
          this.$refs.pwd.focus();
        });
    },
    async getLoginUserData() {
      let res = await getLoginUserData();
      if (res.success) {
        sessionStorage.setItem("userInfo", JSON.stringify(res.data));
        this.$notify.success("登录成功!");
        // 获取权限
        await this.getMenuList();
        location.assign("/view/desktop/");
        return res.data;
      } else {
        this.$notify.error("登录失败!");
      }
    },
    getScreenHeight() {
      this.currentHeight = document.documentElement.clientHeight;
      this.currentWidth = document.documentElement.clientWidth;
      window.onresize = () => {
        this.currentHeight = document.documentElement.clientHeight;
        this.currentWidth = document.documentElement.clientWidth;
        this.$forceUpdate();
      };
    },
    async getServerName() {
      let res = await getServerName();
      if (res && res.success) {
        this.serverTitle = res.data.serverName;
        window.document.title = res.data.serverName
          ? res.data.serverName
          : "SmartAI";
        sessionStorage.setItem("title", res.data.serverName);
      }
    },
    async getMenuList() {
      let results = await getMenuListData({});
      if (results && results.success) {
        /* 存储权限 */
        let buttonAuthoritys = results.data;
        if (results && results.length && this.$route.query.is_login) {
          this.$router.replace(results[0].url);
        }
        sessionStorage.setItem(
          "buttonAuthoritys",
          "," + buttonAuthoritys + ","
        );
        sessionStorage.setItem("menuInfo", JSON.stringify(results));
      } else {
        this.$toast({
          type: "error",
          message: "菜单获取失败",
        });
      }
    },
    getQueryVariable(variable) {
      var query = window.location.search.substring(1);
      var vars = query.split("&");
      for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable) {
          return pair[1];
        }
      }
      return false;
    },
  },
};
</script>
<style lang="scss">
html,
body,
.login {
  height: 100%;
  min-width: 1200px;
  min-height: 680px;
  position: relative;
  background-image: url("/apps/loginData/background.png");
  .title {
    position: absolute;
    top: 40%;
    left: 15.6%;
    color: #fff;
    text-align: center;
    .en {
      font-size: 120px;
    }
    .ch {
      font-size: 48px;
      letter-spacing: 9px;
    }
  }
  .left_footer {
    position: absolute;
    display: flex;
    justify-content: start;
    align-items: center;
    left: 18.6%;
    bottom: 40px;
    .logo {
      width: 136px;
      margin-right: 30px;
    }
    .web {
      font-size: 24px;
      font-weight: 700;
      color: rgba(255, 255, 255, 0.7);
    }
  }
  .login-form {
    position: absolute;
    width: 40%;
    height: 92.5%;
    right: 3.75%;
    top: 3.75%;
    padding: 0 90px;
    box-sizing: border-box;
    background: #2a2344;
    opacity: 0.95;
    box-shadow: -4px 0px 10px rgba(0, 0, 0, 0.25);
    border-radius: 56px;
    overflow: hidden;
    .logo {
      width: 100%;
      margin-top: 13%;
      margin-bottom: 20px;
    }
    .el-form {
      width: 100%;
    }
    .el-form-item {
      background: rgba(0, 0, 0, 0);
    }
    .el-form-item:nth-child(2) {
      margin-top: 10%;
      margin-bottom: 13%;
    }
    .el-button {
      width: 100%;
      height: 60px;
      background: #4e94ff;
      border-radius: 30px;
      border: none;
    }
    .el-input {
      width: 100%;
      background: rgba(0, 0, 0, 0);
    }
    input {
      width: 100%;
      height: 56px;
      background: rgba(255, 255, 255, 0.1) !important;
      border: 1px solid #4e94ff;
      box-sizing: border-box;
      border-radius: 28px;
      color: #fff;
      caret-color: #fff; //光标颜色
      padding-left: 100px;
      padding-right: 50px;
      font-weight: 700;
    }
    input:-webkit-autofill,
    textarea:-webkit-autofill,
    select:-webkit-autofill {
      -webkit-text-fill-color: #ededed !important;
      -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
      background-color: transparent;
      background-image: none;
      transition: background-color 50000s ease-in-out 0s; //背景色透明  生效时长  过渡效果  启用时延迟的时间
    }
    .el-form-item__error {
      top: 110%;
      left: 80px;
    }
    .icon {
      font-size: 32px;
      color: rgb(80, 151, 255);
    }
    .el-input__prefix {
      padding: 0 20px;
      height: 40px;
      left: 5px;
      top: 8px;
      border-right: 1px solid #4e94ff;
    }
    .el-input__suffix {
      right: 20px;
    }
    .el-icon-circle-close {
      display: none;
    }
  }
  .login-form.empty {
    input {
      border-color: #999;
      color: #bbb;
    }
    .el-button {
      background-color: #999;
      color: #fff;
    }
    .icon {
      color: #fff;
    }
    .el-input__prefix {
      border-color: #d4d6d9;
    }
  }
}
// .right-bg {
//   position: fixed;
//   top: 0;
//   left: 0;
//   background-image: url("/images/login-net.png");
//   width: 100%;
//   height: 100%;
//   min-width: 1000px;
//   z-index: -10;
//   zoom: 1;
//   background-color: #fff;
//   background-repeat: no-repeat;
//   background-size: cover;
//   -webkit-background-size: cover;
//   -o-background-size: cover;
//   background-position: center 0;
// }
// .web-site {
//   position: absolute;
//   top: 55px;
//   left: 41px;
//   font-family: PingFangSC-Medium;
//   font-size: 20px;
//   color: #6170e1;
//   letter-spacing: 6.15px;
// }
// .lang-select {
//   float: right;
//   color: white !important;
//   font-size: 14px;
//   margin: 13px;
//   cursor: pointer;
// }
// .left-bg {
//   position: absolute;
//   top: 29%;
//   right: 18%;
//   width: 390px;
//   height: 426px;
//   background: rgba(146, 208, 255, 0.23);
//   border-radius: 4px;
//   text-align: center;
//   .login-logo {
//     margin-top: -53px;
//   }
//   .login-com {
//     font-family: PingFangSC-Medium;
//     font-size: 22px;
//     color: #ffffff;
//     letter-spacing: 0.44px;
//     margin: 15px;
//   }
//   .login-form {
//     margin: 40px 10px;
//   }
//   .gradient-text {
//     line-height: 36px;
//     font-size: 17px;
//     font-family: -webkit-pictograph;
//     font-weight: bolder;
//     position: relative;
//     b {
//       font-size: 20px;
//     }
//   }
//   .gradient-text-one {
//     background-image: linear-gradient(to right, #51feff 5%, #ff8725 100%);
//     -webkit-background-clip: text;
//     -webkit-text-fill-color: transparent;
//   }
//   .el-input__prefix {
//     left: 8px;
//   }
//   .el-form-item__error {
//     left: 54px;
//   }
// }
</style>
<template>
  <!-- <div class v-loading="vLoading" :style="`width: ${currentWidth}px;height:${currentHeight}px`">
    <div class="web-site">
      <a href="http://www.smartai.com" target="_blank">www.smartai.com</a>
    </div>
    <lang-select class="lang-select"/>
    <licence />
    <div class="right-bg" style>
      <particle-network />
    </div>
    <div class="left-bg">
      <div class="login-logo">
        <img src="/images/login-logo.png" alt width="105px" height="105px" />
      </div>
      <div class="login-com">
        <span>{{ $t('login.company') }}</span>
      </div>
      <div class="login-form">
        <el-form
          :model="user"
          status-icon
          :rules="nullRule"
          :validate-on-rule-change="false"
          ref="ruleForm"
          class="demo-ruleForm"
        >
          <el-form-item prop="loginName">
            <el-input v-model="user.loginName" style="width:280px" :placeholder="$t('placeholder.enterUsername')">
              <i slot="prefix" class="iconfont iconyonghu1"></i>
            </el-input>
          </el-form-item>
          <el-form-item prop="password">
            <el-input
              show-password
              @keyup.enter.native="systemLogin()"
              v-model="user.password"
              autocomplete="off"
              style="width:280px"
              :placeholder="$t('placeholder.enterPassword')"
            >
              <i slot="prefix" class="iconfont iconmima"></i>
            </el-input>
          </el-form-item>
          <el-form-item>
            <el-button ref="submit" type="warning" @click="systemLogin()" style="width:280px">{{ $t('button.login') }}</el-button>
          </el-form-item>
        </el-form>
      </div>
      <p class="gradient-text gradient-text-one">
        ——
        <b>SmartAI</b> {{ $t('login.aios') }} ——
      </p>
      <p
        class="gradient-text gradient-text-one"
        style="letter-spacing: 1.8px;font-size:15px;"
      >V1.0.0</p>
    </div>
  </div> -->
  <div class="login">
    <div class="title">
      <div class="en">{{ data.title_firstLine }}</div>
      <div class="ch">{{ data.title_secondLine }}</div>
    </div>
    <div class="left_footer">
      <img class="logo" src="/apps/loginData/LOGO.png" alt="" />
      <div class="web">{{ data.website }}</div>
    </div>
    <div
      class="login-form"
      :style="{ background: backgroundColor }"
      :class="{ empty: !user.loginName || !user.password }"
    >
      <img class="logo" src="/apps/loginData/leftImg.png" alt="" />
      <el-form
        :model="user"
        status-icon
        :rules="nullRule"
        :validate-on-rule-change="false"
        ref="ruleForm"
        class="demo-ruleForm"
      >
        <el-form-item prop="loginName">
          <el-input
            v-model="user.loginName"
            :placeholder="$t('placeholder.enterUsername')"
          >
            <i slot="prefix" class="iconfont icon">&#xe7e5;</i>
          </el-input>
        </el-form-item>
        <el-form-item prop="password">
          <el-input
            show-password
            @keyup.enter.native="systemLogin()"
            v-model="user.password"
            autocomplete="off"
            :placeholder="$t('placeholder.enterPassword')"
          >
            <i slot="prefix" class="iconfont icon">&#xe7e4;</i>
          </el-input>
        </el-form-item>
        <el-form-item>
          <el-button ref="submit" type="warning" @click="systemLogin()">{{
            $t("button.login")
          }}</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>
<script>
import { tologin, getLoginUserData, getServerName } from "./api.ts";
import ParticleNetwork from "./ParticleNetwork";
import Licence from "@/components/licence";
import LangSelect from "@/components/langSelect";
import { getMenuListData } from "@/api/utils";
import loginData from "../../../public/apps/loginData/login.json";
export default {
  name: "login-pgae",
  metaInfo: {
    title: "登录页",
  },
  components: {
    //  ParticleNetwork,
    // Licence,
    //  LangSelect
  },
  computed: {
    rules() {
      return {
        loginName: [
          {
            required: true,
            message: this.$t("placeholder.enterUsername"),
            trigger: "change",
          },
        ],
        password: [
          {
            required: true,
            message: this.$t("placeholder.enterPassword"),
            trigger: "change",
          },
        ],
      };
    },
  },
  data: () => ({
    data: {},
    serverTitle: "",
    user: {
      loginName: "",
      password: "",
      rememberMe: false,
    },
    nullRule: {},
    loading: "",
    vLoading: false,
    currentHeight: 1057,
    currentWidth: 1920,
    backgroundColor: "",
    backgroundList: [
      "#2A2344",
      "#342344",
      "#000000",
      "#233044",
      "#0B252E",
      "#150051",
      "#110040",
    ],
  }),
  created() {
    this.getServerName();
    this.getScreenHeight();
    this.data = loginData;
    this.backgroundColor =
      this.backgroundList[
        Math.floor(Math.random() * this.backgroundList.length)
      ];
  },
  mounted() {
    // 自动登录接口
    this.loginRobot();
  },
  watch: {},
  beforeDestroy() {
    window.onresize = null;
  },
  methods: {
    loginRobot() {
      // 解析路由参数,并缓存
      let user = this.getQueryVariable("username");
      let passwd = this.getQueryVariable("password");
      if (user.length && passwd.length) {
        sessionStorage.setItem(
          "autoLogin",
          JSON.stringify({ username: user, passwd: passwd })
        );
        this.user.loginName = user;
        this.user.password = passwd;
        this.systemLogin();
        return;
      }
      // 登陆超时后的重新登陆
      let sessionInfo = sessionStorage.getItem("autoLogin");
      if (sessionInfo) {
        let authority = JSON.parse(sessionInfo);
        this.user.loginName = authority.username;
        this.user.password = authority.passwd;
        this.systemLogin();
      }
    },
    systemLogin() {
      this.nullRule = this.rules;
      this.$nextTick(() => {
        this.$refs["ruleForm"].validate((valid) => {
          if (valid) {
            this.loading = this.$loading({
              lock: true,
              text: "Loading",
              spinner: "el-icon-loading",
              background: "rgba(0, 0, 0, 0.7)",
            });
            this.testLogin();
          } else {
            this.nullRule = {};
          }
        });
        this.nullRule = {};
      });
    },
    async testLogin() {
      // location.assign("/view/desktop/")
      tologin({ username: this.user.loginName, password: this.user.password })
        .then((json) => {
          const loginedInfo = {
            access_token: json.token_type + " " + json.access_token,
            refresh_token: json.refresh_token,
          };
          sessionStorage.setItem("expires_in", json.expires_in);
          sessionStorage.setItem("loginedInfo", JSON.stringify(loginedInfo));
          this.loading.close();
          this.getLoginUserData();
        })
        .catch((err) => {
          this.loading.close();
          this.$notify({
            title: "提示",
            type: "error",
            message: err.msg,
          });
          this.$refs.pwd.focus();
        });
    },
    async getLoginUserData() {
      let res = await getLoginUserData();
      if (res.success) {
        sessionStorage.setItem("userInfo", JSON.stringify(res.data));
        this.$notify.success("登录成功!");
        // 获取权限
        await this.getMenuList();
        location.assign("/view/desktop/");
        return res.data;
      } else {
        this.$notify.error("登录失败!");
      }
    },
    getScreenHeight() {
      this.currentHeight = document.documentElement.clientHeight;
      this.currentWidth = document.documentElement.clientWidth;
      window.onresize = () => {
        this.currentHeight = document.documentElement.clientHeight;
        this.currentWidth = document.documentElement.clientWidth;
        this.$forceUpdate();
      };
    },
    async getServerName() {
      let res = await getServerName();
      if (res && res.success) {
        this.serverTitle = res.data.serverName;
        window.document.title = res.data.serverName
          ? res.data.serverName
          : "SmartAI";
        sessionStorage.setItem("title", res.data.serverName);
      }
    },
    async getMenuList() {
      let results = await getMenuListData({});
      if (results && results.success) {
        /* 存储权限 */
        let buttonAuthoritys = results.data;
        if (results && results.length && this.$route.query.is_login) {
          this.$router.replace(results[0].url);
        }
        sessionStorage.setItem(
          "buttonAuthoritys",
          "," + buttonAuthoritys + ","
        );
        sessionStorage.setItem("menuInfo", JSON.stringify(results));
      } else {
        this.$toast({
          type: "error",
          message: "菜单获取失败",
        });
      }
    },
    getQueryVariable(variable) {
      var query = window.location.search.substring(1);
      var vars = query.split("&");
      for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable) {
          return pair[1];
        }
      }
      return false;
    },
  },
};
</script>
<style lang="scss">
html,
body,
.login {
  height: 100%;
  min-width: 1200px;
  min-height: 680px;
  position: relative;
  background-image: url("/apps/loginData/background.png");
  .title {
    position: absolute;
    top: 40%;
    left: 15.6%;
    color: #fff;
    text-align: center;
    .en {
      font-size: 120px;
    }
    .ch {
      font-size: 48px;
      letter-spacing: 9px;
    }
  }
  .left_footer {
    position: absolute;
    display: flex;
    justify-content: start;
    align-items: center;
    left: 18.6%;
    bottom: 40px;
    .logo {
      width: 136px;
      margin-right: 30px;
    }
    .web {
      font-size: 24px;
      font-weight: 700;
      color: rgba(255, 255, 255, 0.7);
    }
  }
  .login-form {
    position: absolute;
    width: 40%;
    height: 92.5%;
    right: 3.75%;
    top: 3.75%;
    padding: 0 90px;
    box-sizing: border-box;
    background: #2a2344;
    opacity: 0.95;
    box-shadow: -4px 0px 10px rgba(0, 0, 0, 0.25);
    border-radius: 56px;
    overflow: hidden;
    .logo {
      width: 100%;
      margin-top: 13%;
      margin-bottom: 20px;
    }
    .el-form {
      width: 100%;
    }
    .el-form-item {
      background: rgba(0, 0, 0, 0);
    }
    .el-form-item:nth-child(2) {
      margin-top: 10%;
      margin-bottom: 13%;
    }
    .el-button {
      width: 100%;
      height: 60px;
      background: #4e94ff;
      border-radius: 30px;
      border: none;
    }
    .el-input {
      width: 100%;
      background: rgba(0, 0, 0, 0);
    }
    input {
      width: 100%;
      height: 56px;
      background: rgba(255, 255, 255, 0.1) !important;
      border: 1px solid #4e94ff;
      box-sizing: border-box;
      border-radius: 28px;
      color: #fff;
      caret-color: #fff; //光标颜色
      padding-left: 100px;
      padding-right: 50px;
      font-weight: 700;
    }
    input:-webkit-autofill,
    textarea:-webkit-autofill,
    select:-webkit-autofill {
      -webkit-text-fill-color: #ededed !important;
      -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
      background-color: transparent;
      background-image: none;
      transition: background-color 50000s ease-in-out 0s; //背景色透明  生效时长  过渡效果  启用时延迟的时间
    }
    .el-form-item__error {
      top: 110%;
      left: 80px;
    }
    .icon {
      font-size: 32px;
      color: rgb(80, 151, 255);
    }
    .el-input__prefix {
      padding: 0 20px;
      height: 40px;
      left: 5px;
      top: 8px;
      border-right: 1px solid #4e94ff;
    }
    .el-input__suffix {
      right: 20px;
    }
    .el-icon-circle-close {
      display: none;
    }
  }
  .login-form.empty {
    input {
      border-color: #999;
      color: #bbb;
    }
    .el-button {
      background-color: #999;
      color: #fff;
    }
    .icon {
      color: #fff;
    }
    .el-input__prefix {
      border-color: #d4d6d9;
    }
  }
}
// .right-bg {
//   position: fixed;
//   top: 0;
//   left: 0;
//   background-image: url("/images/login-net.png");
//   width: 100%;
//   height: 100%;
//   min-width: 1000px;
//   z-index: -10;
//   zoom: 1;
//   background-color: #fff;
//   background-repeat: no-repeat;
//   background-size: cover;
//   -webkit-background-size: cover;
//   -o-background-size: cover;
//   background-position: center 0;
// }
// .web-site {
//   position: absolute;
//   top: 55px;
//   left: 41px;
//   font-family: PingFangSC-Medium;
//   font-size: 20px;
//   color: #6170e1;
//   letter-spacing: 6.15px;
// }
// .lang-select {
//   float: right;
//   color: white !important;
//   font-size: 14px;
//   margin: 13px;
//   cursor: pointer;
// }
// .left-bg {
//   position: absolute;
//   top: 29%;
//   right: 18%;
//   width: 390px;
//   height: 426px;
//   background: rgba(146, 208, 255, 0.23);
//   border-radius: 4px;
//   text-align: center;
//   .login-logo {
//     margin-top: -53px;
//   }
//   .login-com {
//     font-family: PingFangSC-Medium;
//     font-size: 22px;
//     color: #ffffff;
//     letter-spacing: 0.44px;
//     margin: 15px;
//   }
//   .login-form {
//     margin: 40px 10px;
//   }
//   .gradient-text {
//     line-height: 36px;
//     font-size: 17px;
//     font-family: -webkit-pictograph;
//     font-weight: bolder;
//     position: relative;
//     b {
//       font-size: 20px;
//     }
//   }
//   .gradient-text-one {
//     background-image: linear-gradient(to right, #51feff 5%, #ff8725 100%);
//     -webkit-background-clip: text;
//     -webkit-text-fill-color: transparent;
//   }
//   .el-input__prefix {
//     left: 8px;
//   }
//   .el-form-item__error {
//     left: 54px;
//   }
// }
</style>
vue.config.js
@@ -1,156 +1,156 @@
"use strict";
const glob = require("glob");
const pages = {};
const IS_VENDOR = /[\\/]node_modules[\\/]/;
const pageVendor = {};
const pkg = require("./package.json");
const timestamp = new Date().getTime();
const queryStr = `?v=${pkg.version}&t=${timestamp}`;
glob.sync("./src/pages/**/main.ts").forEach((path) => {
  const chunk = path.split("./src/pages/")[1].split("/main.ts")[0];
  const chunk_vendor = `${chunk}-vendors`;
  const chunk_common = `${chunk}-common`;
  pages[chunk] = {
    entry: path,
    template: "public/index.html",
    title: chunk == "desktop/index" ? "SmartAI" : chunk,
    chunks: [chunk_vendor, "chunk-common", chunk],
  };
  if (chunk != "index") {
    pages[chunk].filename = "view/" + chunk + ".html";
  }
  pageVendor[chunk_vendor] = {
    name: chunk_vendor,
    priority: -11,
    chunks: (c) => c.name === chunk,
    test: /\.js$/,
    enforce: true,
  };
  // pageVendor[chunk_common] = {
  //   name: chunk_common,
  //   priority: -20,
  //   chunks: 'initial',
  //   minChunks: 2,
  //   reuseExistingChunk: true,
  //   enforce: true
  // }
});
const serverUrl = "http://192.168.20.189:7009"; // 羊五//
// const serverUrl = "http://192.168.8.10:7009";
const serverUrl2 = "http://192.168.8.10:9000";
// const serverUrl = "http://192.168.20.10:7009";
// const serverUrl2 = "http://192.168.20.10:9000";
// const cir = require("circular-dependency-plugin");
module.exports = {
  pages,
  chainWebpack: (config) => {
    config.plugins.delete("named-chunks");
    if (process.env.NODE_ENV === "production") {
      config.output.filename("js/[name].js" + queryStr).end();
      config.output.chunkFilename("js/[name].js" + queryStr).end();
      // 修改生产配置
      config.plugin("extract-css").tap(() => [
        {
          filename: `css/[name].css${queryStr}`,
          chunkFilename: `css/[name].css${queryStr}`,
        },
      ]);
    }
    config.optimization.splitChunks({
      cacheGroups: pageVendor,
    });
    // config.module.rule('fonts').use('url-loader').loader('file-loader').options({ name: 'fonts/[name].[ext]', publicPath: '../' })
    //config.module.rule('fonts').use('url-loader').loader('file-loader').options({ name: 'fonts/[name].[ext]', outputPath: '../' })
  },
  productionSourceMap: false,
  filenameHashing: false,
  pwa: {
    iconPaths: {
      favicon32: "favicon.ico",
      favicon16: "favicon.ico",
    },
  },
  devServer: {
    proxy: {
      "/track": {
        target: serverUrl,
        // ws: true,
        changeOrigin: true,
      },
      "/ws": {
        target: serverUrl,
        // ws: true,
        changeOrigin: true,
      },
      "/data/api-v/app/findAllApp": {
        // target: '/',
        target: "http://localhost:8080/",
        changeOrigin: true,
        pathRewrite: {
          "^/data/api-v/app/findAllApp": "apps.json",
        },
      },
      "/api-c": {
        target: serverUrl,
        changeOrigin: true,
      },
      "/api-v": {
        target: serverUrl,
        changeOrigin: true,
      },
      "/api-f": {
        target: serverUrl,
        // secure: false,
        changeOrigin: true,
      },
      "/api-p": {
        target: serverUrl,
        // secure: false,
        changeOrigin: true,
      },
      "/api-u": {
        target: serverUrl,
        changeOrigin: true,
      },
      "/httpImage": {
        target: serverUrl,
        changeOrigin: true, //开启代理
      },
      "/files": {
        target: serverUrl,
        changeOrigin: true, //开启代理
      },
      "/iotdata": {
        target: serverUrl2,
        changeOrigin: true, //开启代理,
      },
    },
  },
  // configureWebpack: {
  //   plugins: [
  //     new cir({
  //       exclude: /a\.js|node_modules/,
  //       include: /dir/,
  //       failOnError: true,
  //       allowAsyncCycles: false,
  //       cwd: process.cwd(),
  //     }),
  //   ],
  // },
  /* css:{
    loaderOptions:{
      scss:{
        prependData:`@import"@/assets/css/globalVariable.scss"`
      }
    }
  } */
};
"use strict";
const glob = require("glob");
const pages = {};
const IS_VENDOR = /[\\/]node_modules[\\/]/;
const pageVendor = {};
const pkg = require("./package.json");
const timestamp = new Date().getTime();
const queryStr = `?v=${pkg.version}&t=${timestamp}`;
glob.sync("./src/pages/**/main.ts").forEach((path) => {
  const chunk = path.split("./src/pages/")[1].split("/main.ts")[0];
  const chunk_vendor = `${chunk}-vendors`;
  const chunk_common = `${chunk}-common`;
  pages[chunk] = {
    entry: path,
    template: "public/index.html",
    title: chunk == "desktop/index" ? "SmartAI" : chunk,
    chunks: [chunk_vendor, "chunk-common", chunk],
  };
  if (chunk != "index") {
    pages[chunk].filename = "view/" + chunk + ".html";
  }
  pageVendor[chunk_vendor] = {
    name: chunk_vendor,
    priority: -11,
    chunks: (c) => c.name === chunk,
    test: /\.js$/,
    enforce: true,
  };
  // pageVendor[chunk_common] = {
  //   name: chunk_common,
  //   priority: -20,
  //   chunks: 'initial',
  //   minChunks: 2,
  //   reuseExistingChunk: true,
  //   enforce: true
  // }
});
const serverUrl = "http://192.168.20.189:7009"; // 羊五//
// const serverUrl = "http://192.168.8.10:7009";
const serverUrl2 = "http://192.168.8.10:9000";
// const serverUrl = "http://192.168.20.10:7009";
// const serverUrl2 = "http://192.168.20.10:9000";
// const cir = require("circular-dependency-plugin");
module.exports = {
  pages,
  chainWebpack: (config) => {
    config.plugins.delete("named-chunks");
    if (process.env.NODE_ENV === "production") {
      config.output.filename("js/[name].js" + queryStr).end();
      config.output.chunkFilename("js/[name].js" + queryStr).end();
      // 修改生产配置
      config.plugin("extract-css").tap(() => [
        {
          filename: `css/[name].css${queryStr}`,
          chunkFilename: `css/[name].css${queryStr}`,
        },
      ]);
    }
    config.optimization.splitChunks({
      cacheGroups: pageVendor,
    });
    // config.module.rule('fonts').use('url-loader').loader('file-loader').options({ name: 'fonts/[name].[ext]', publicPath: '../' })
    //config.module.rule('fonts').use('url-loader').loader('file-loader').options({ name: 'fonts/[name].[ext]', outputPath: '../' })
  },
  productionSourceMap: false,
  filenameHashing: false,
  pwa: {
    iconPaths: {
      favicon32: "favicon.ico",
      favicon16: "favicon.ico",
    },
  },
  devServer: {
    proxy: {
      "/track": {
        target: serverUrl,
        // ws: true,
        changeOrigin: true,
      },
      "/ws": {
        target: serverUrl,
        // ws: true,
        changeOrigin: true,
      },
      "/data/api-v/app/findAllApp": {
        // target: '/',
        target: "http://localhost:8080/",
        changeOrigin: true,
        pathRewrite: {
          "^/data/api-v/app/findAllApp": "apps.json",
        },
      },
      "/api-c": {
        target: serverUrl,
        changeOrigin: true,
      },
      "/api-v": {
        target: serverUrl,
        changeOrigin: true,
      },
      "/api-f": {
        target: serverUrl,
        // secure: false,
        changeOrigin: true,
      },
      "/api-p": {
        target: serverUrl,
        // secure: false,
        changeOrigin: true,
      },
      "/api-u": {
        target: serverUrl,
        changeOrigin: true,
      },
      "/httpImage": {
        target: serverUrl,
        changeOrigin: true, //开启代理
      },
      "/files": {
        target: serverUrl,
        changeOrigin: true, //开启代理
      },
      "/iotdata": {
        target: serverUrl2,
        changeOrigin: true, //开启代理,
      },
    },
  },
  // configureWebpack: {
  //   plugins: [
  //     new cir({
  //       exclude: /a\.js|node_modules/,
  //       include: /dir/,
  //       failOnError: true,
  //       allowAsyncCycles: false,
  //       cwd: process.cwd(),
  //     }),
  //   ],
  // },
  /* css:{
    loaderOptions:{
      scss:{
        prependData:`@import"@/assets/css/globalVariable.scss"`
      }
    }
  } */
};