psj0001 vor 3 Wochen
Ursprung
Commit
83e53d82c9

BIN
src/assets/imgs/密码_黑.png


BIN
src/assets/imgs/用户名_黑.png


BIN
src/assets/imgs/验证码_黑.png


+ 1 - 1
src/router/index.js

@@ -20,7 +20,7 @@ export const router= createRouter({
 
    ]
   },
-  {path:'/login',name:'login',component:() => import('../views/login/Login.vue')},
+  {path:'/login',name:'login',component:() => import('../views/login/login.vue')},
 
  ]
 })

+ 24 - 0
src/service/index.js

@@ -28,6 +28,30 @@ requestInstance_Get.interceptors.response.use(function (res) {
 })
 
 
+export const requestInstance_Post = axios.create({
+	baseURL: import.meta.env.VITE_BASE_API,
+	timeout: 60000,
+	method: 'post',
+	responseType: "blob",
+	withCredentials:true,
+	headers:{
+		Systemtype:'031A00171DB84D81B4D3EF30B84EC265'
+	},
+
+})
+requestInstance_Post.interceptors.request.use((config) => {
+	// console.log(config)
+	return config
+}, (error) => {
+	return new Error(error)
+})
+requestInstance_Post.interceptors.response.use(function (res) {
+	return res.data
+}, function (error) {
+
+	throw new Error(error)
+})
+
 export const requestInstance = axios.create({
 	baseURL: import.meta.env.VITE_BASE_API,
 	timeout: 60000,

+ 52 - 1
src/service/login.js

@@ -1,6 +1,6 @@
 import {
  requestInstance, requestInstance_Get,
- requestInstance_login,
+ requestInstance_login, requestInstance_Post,
  requestInstance_PTJK,
  requestInstance_ZWGL,
  requestInstance_ZWLL
@@ -147,3 +147,54 @@ export function editZwLoginState(params){
   })
  }
 }
+
+
+export function randomImageCode_v1(color) {
+ return requestInstance_Post({
+  url: '/user/v1/randomImageCode',
+  data: {
+   color:color
+  },
+ })
+}
+export function verifyZymlUserInformation(username,password){
+ return requestInstance_login({
+  url:'/user/v1/verifyZymlUserInformation',
+  data:{
+   "username":username,
+   "password":password
+  }
+ })
+}
+
+export function sendPhoneVerificationCode(phone,verificationCode) {
+ return requestInstance_login({
+  url: '/user/v1/sendPhoneVerificationCode',
+  data: {
+   "telphone": phone,
+   "verificationCode": verificationCode
+  },
+ })
+}
+
+
+export function userBindPhone(userid, telphone, verificationCode) {
+ return requestInstance_login({
+  url: '/user/v1/zymlUserBindPhone',
+  data: {
+   "userId": userid,
+   "telphone": telphone,
+   "verificationCode": verificationCode
+  },
+ })
+}
+
+export function sendZymlVerificationCode(userid,verificationCode) {
+ return requestInstance_login({
+  url: '/user/v1/sendZymlVerificationCode',
+  data: {
+   "userId": userid,
+   "verificationCode": verificationCode
+  },
+ })
+}

+ 6 - 6
src/views/DataMiddleGroundHome/DataMiddleGroundHome.vue

@@ -47,12 +47,12 @@ const headArr = ref([
   {name:'政务信息共享交换系统',aPath:'https://datamidplat.zjw.sh.cegn.cn:2011/business-browsing/#/main/mainInfo',loginPage: 'https://datamidplat.zjw.sh.cegn.cn:2011/business-browsing/#/login',moduleId:'570',className:'left-k'},
   {name:'政务信息管理系统',aPath:'https://datamidplat.zjw.sh.cegn.cn:2011/business-manage/#/main/',loginPage: 'https://datamidplat.zjw.sh.cegn.cn:2011/business-manage/#/login',moduleId:'116',className: 'left-k left-k2'},
   {name:'数据治理监控系统',aPath:'https://datamidplat.zjw.sh.cegn.cn:2011/business-monitor/#/home',loginPage:'https://datamidplat.zjw.sh.cegn.cn:2011/business-monitor/#/login',moduleId:'51',className: 'right-k  right-k2'},
-  // {name:'应用系统',aPath:'http://10.90.7.241:9443/business-monitor/',className: 'right-k',children:
-  //     [
-  //       {name:'市住建委信用信息数据库系统',aPath:'https://datamidplat.zjw.sh.cegn.cn:2011/application-credit/#/main',loginPage: 'https://datamidplat.zjw.sh.cegn.cn:2011/application-credit/#/login',moduleId:'572'},
-  //       {name:'社情民意数据分析系统',aPath:'http://10.81.72.173:8088/login',loginPage:'http://10.81.72.173:8088/login',moduleId:'573'},
-  //     ]
-  // },
+  {name:'应用系统',aPath:'http://10.90.7.241:9443/business-monitor/',className: 'right-k',children:
+      [
+        {name:'市住建委信用信息数据库系统',aPath:'https://datamidplat.zjw.sh.cegn.cn:2011/application-credit/#/main',loginPage: 'https://datamidplat.zjw.sh.cegn.cn:2011/application-credit/#/login',moduleId:'572'},
+        {name:'社情民意数据分析系统',aPath:'http://10.81.72.173:8088/login',loginPage:'http://10.81.72.173:8088/login',moduleId:'573'},
+      ]
+  },
 ])
 function toLogin(){
   router.push('/login')

+ 545 - 0
src/views/login/LoginMessage.vue

@@ -0,0 +1,545 @@
+<template>
+  <div id="login-page">
+    <div class="title">
+      <div class="text font-ht" >
+        市住建委数据中台
+      </div>
+
+    </div>
+    <div class="login-content">
+      <div v-show="loginState=='1'||loginState=='2'">
+        <div class="welcome">欢迎登录</div>
+        <div class="form-item">
+          <el-input v-model="formInfo.username" placeholder="请输入用户名">
+            <template #prefix>
+              <img src="../../assets/imgs/用户名.png" alt="">
+            </template>
+          </el-input>
+        </div>
+        <div class="error" v-if="showObj.isUserNameEmptyShow">请输入用户名</div>
+        <div class="form-item" >
+          <el-input type="password" v-model="formInfo.psd" placeholder="请输入密码">
+            <template #prefix>
+              <img src="../../assets/imgs/密码.png" alt="">
+            </template>
+          </el-input>
+        </div>
+        <div class="error" v-if="showObj.isPsdErrorEmptyShow">请输入密码</div>
+        <div >
+          <div class="btn" @click="zymlUserInformationVerify">登录</div>
+        </div>
+      </div>
+      <div v-show="loginState=='3'">
+        <div class="welcome">短信验证</div>
+        <div class="form-item">
+          <el-input v-model="formInfo.codeUserInput_message" placeholder="请输入验证码">
+            <template #prefix>
+              <img src="../../assets/imgs/验证码.png" alt="">
+            </template>
+            <template #suffix>
+              <img style="width: 80px;height: 50px;" :src="formInfo.vCodeReal" alt="" id="validCode" @click="changeValidCode" class="valid-code" />
+              <!--            <canvas  id="validCode" @click="changeValidCode" class="valid-code"></canvas>-->
+            </template>
+          </el-input>
+        </div>
+        <div class="error"  v-if="!showObj.isValidCodeEmptyShow && showObj.isValidCodeErrorShow">验证码错误</div>
+        <div class="form-item">
+          <el-input v-model="formInfo.message" placeholder="请输入短信验证码">
+            <template #prefix>
+              <img src="../../assets/imgs/验证码.png" alt="">
+            </template>
+            <template #suffix>
+              <el-button :disabled="countdown > 0" @click="getSmsCode">{{ countdown > 0 ? `${countdown}秒后重新获取` : '获取验证码' }}</el-button>
+            </template>
+          </el-input>
+          <div class="message">
+            <span class="message_notice">短信将被发送到{{telphone}}手机号码上</span>
+          </div>
+        </div>
+        <div class="error" v-if="showObj.isValidCodeEmptyShow">请输入短信验证码</div>
+        <div >
+          <div class="btn" @click="login">登录</div>
+        </div>
+      </div>
+    </div>
+
+
+    <el-dialog
+        v-model="dialogVisible"
+        title="手机号绑定"
+        width="500"
+        align-center
+    >
+      <div class="dialog-content">
+        <div class="tip custom-block">
+          <!--          <p class="custom-block-title">通知</p>-->
+          <p class="custom-block-content">
+            由于安全需要,现需将身份认证升级为双因素认证,即在原有用户名密码基础上新增手机号短信验证。
+          </p>
+          <p class="custom-block-content">
+            现检测到该账号没有绑定过手机号,需进行手机号绑定,一个账号只能对应一个手机号。绑定之后每次登录都需进行手机号短信验证,请谨慎操作。
+          </p>
+        </div>
+        <div class="form-item">
+          <el-input v-model="formInfo.phone" placeholder="请输入手机号">
+            <template #prefix>
+              <img  src="../../assets/imgs/用户名_黑.png" alt="">
+            </template>
+          </el-input>
+        </div>
+
+        <div class="form-item">
+          <el-input v-model="formInfo.codeUserInput_phone" placeholder="请输入图形验证码">
+            <template #prefix>
+              <img src="../../assets/imgs/验证码_黑.png" alt="">
+            </template>
+            <template #suffix>
+              <img style="width: 80px;height: 50px;" :src="formInfo.vCodeReal" alt="" id="validCode" @click="changeValidCode('black')" class="valid-code" />
+            </template>
+          </el-input>
+        </div>
+        <div class="error"  v-if="!showObj.isValidCodeEmptyShow && showObj.isValidCodeErrorShow">验证码错误</div>
+
+        <div class="form-item">
+          <el-input v-model="formInfo.register_message" placeholder="请输入短信验证码">
+            <template #prefix>
+              <img src="../../assets/imgs/验证码_黑.png" alt="">
+            </template>
+            <template #suffix>
+              <el-button :disabled="register_countdown > 0" @click="getRegisterCode">{{ register_countdown > 0 ? `${register_countdown}秒后重新获取` : '获取验证码' }}</el-button>
+            </template>
+          </el-input>
+        </div>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="loginIn_phone">
+            绑定
+          </el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {encode} from "js-base64";
+import {onMounted, ref} from 'vue'
+import {getLoginImg, loginCim, loginIn,verifyZymlUserInformation,randomImageCode_v1,sendPhoneVerificationCode,userBindPhone,sendZymlVerificationCode} from "@/service/login";
+import {showConfirm, showMessage} from "@/unit/element-ui/tip";
+import {useRouter} from "vue-router";
+import {useLoginStore} from "@/pinia/login";
+import {ElLoading} from "element-plus";
+const router = useRouter();
+let url =ref(null);
+let loginPinia = useLoginStore();
+let loginState = ref('1');
+let countdown = ref(0);
+let register_countdown = ref(0);
+let userId = ref(null);
+let dialogVisible = ref(false);
+let telphone = ref('');
+let loading;
+
+
+function login(){
+  showObj.value.isUserNameEmptyShow = !Boolean(formInfo.value.username)
+  showObj.value.isPsdErrorEmptyShow = !Boolean(formInfo.value.psd)
+  showObj.value.isValidCodeEmptyShow = !Boolean(formInfo.value.message)
+  if (!showObj.value.isUserNameEmptyShow && !showObj.value.isPsdErrorEmptyShow && !showObj.value.isValidCodeEmptyShow){
+    loading = ElLoading.service({
+      lock: true,
+      text: 'Loading',
+      background: 'rgba(0, 0, 0, 0.7)',
+    })
+    loginIn(formInfo.value.username,encode(formInfo.value.psd),formInfo.value.message).then(res =>{
+      loading.close();
+      changeValidCode('black');
+      let data
+      try {
+        data = res.msg[0].Rows;
+      }
+      catch {
+        showMessage({
+          showClose: true,
+          message: '登录失败',
+          type: 'error'
+        });
+
+        return
+      }
+      if(data.length > 0 && data.length == 1){
+        let time2 = new Date(data[0]["GETTIME"]).getTime() - new Date(data[0]["LAST_TIME"]).getTime();
+        if (time2<=15*60*1000){
+          if (+data[0].LOGIN_COUNT>0){
+            if (+data[0].LOGIN_COUNT<5){
+              showMessage({
+                type:'error',
+                message:`密码错误${+data[0].LOGIN_COUNT }次,5次将锁定账号`
+              })
+
+            }else {
+              showMessage({
+                type:'error',
+                message:'账号已锁定,请15分钟后重试'
+              })
+            }
+            return;
+          }
+        }
+        let LOGIN_LOCK = data[0]["LOGIN_LOCK"];
+        if (LOGIN_LOCK == 1) {
+
+          var time = new Date(data[0]["GETTIME"]).getTime() - new Date(data[0]["LAST_TIME"]).getTime();
+          time = time / 1000;
+
+          if (time < 20) {
+            showConfirm(() => {
+              confirmLogin(data)
+            },'当前用户已登录!是否继续登录','系统提示',{
+              confirmButtonText: "确定",
+              cancelButtonText: "取消",
+              type: "warning"
+            })
+          }
+          else {
+            confirmLogin(data)
+          }
+        }else {
+          confirmLogin(data)
+        }
+      }else{
+        showMessage({
+          type:'error',
+          message:'无权登录'
+        })
+      }
+
+
+    })
+  }
+}
+function confirmLogin(data){
+  formInfo.value.psd = data[0].TOKEN;
+  localStorage.setItem('userInfoPsdOrUserNameMiddle',JSON.stringify({
+    ...formInfo.value
+  }))
+  loginPinia.$state.loginInfo = formInfo.value
+  loginMyCim();
+}
+function loginMyCim(){
+  loginCim({
+    username:formInfo.value.username,
+    password:formInfo.value.psd
+  }).then(res => {
+    router.push('/LoginedPage')
+    localStorage.setItem('canSeeSystemArr',JSON.stringify(res.msg[0].Rows))
+    loginPinia.$state.canSeeSystemArr =  res.msg[0].Rows
+  })
+}
+
+function changeValidCode(type){
+  randomImageCode_v1(type).then(res =>{
+    const blob = new Blob([res], { type: "image/png" });
+    // 创建URL对象
+    formInfo.value.vCodeReal = URL.createObjectURL(blob);
+  })
+}
+
+//verifyZymlUserInformation
+function zymlUserInformationVerify(){  //用户名密码校验
+  showObj.value.isUserNameEmptyShow = !Boolean(formInfo.value.username)
+  showObj.value.isPsdErrorEmptyShow = !Boolean(formInfo.value.psd)
+  if (!showObj.value.isUserNameEmptyShow && !showObj.value.isPsdErrorEmptyShow){
+    verifyZymlUserInformation(formInfo.value.username,encode(formInfo.value.psd))
+        .then(res => {
+          if(res.code == '200'){
+            if(res.data.state == '0'){
+              userId.value = res.data.userid;
+              if(res.data.isBindPhone == '0'){  //没有转注册手机号
+                dialogVisible.value = true;
+                changeValidCode('black');
+              }else if(res.data.isBindPhone == '1'){ //有转短信验证码
+                loginState.value = '3';
+                telphone.value = res.data.telphone;
+                changeValidCode();
+              }
+            }else{
+              showMessage({
+                type: 'error',
+                message: res.msg
+              })
+            }
+          }else{
+            showMessage({
+              type: 'error',
+              message: res.msg
+            })
+          }
+        })
+  }
+}
+
+function getRegisterCode() {
+  // 模拟发送短信验证码的请求
+  // 实际应用中,这里应该是向服务器发送请求,并处理响应
+  sendPhoneVerificationCode(formInfo.value.phone,formInfo.value.codeUserInput_phone)
+      .then(res =>{
+        if(res.code == '200'){
+          showMessage({
+            type: 'success',
+            message: res.msg
+          });
+          // 设置60秒倒计时
+          register_countdown.value = 60;
+          const registerIntervalId = setInterval(() => {
+            if (register_countdown.value > 0) {
+              register_countdown.value -= 1;
+            } else {
+              clearInterval(registerIntervalId);
+            }
+          }, 1000);
+        }else{
+          showMessage({
+            type: 'error',
+            message: res.msg
+          })
+        }
+      })
+  console.log('发送短信验证码到手机号');
+
+}
+
+function loginIn_phone(){
+  userBindPhone(userId.value,formInfo.value.phone,formInfo.value.register_message)
+      .then(res =>{
+        if(res.code == '200'){
+          dialogVisible = false
+          loginState.value = '3';
+          changeValidCode();
+        }else{
+          changeValidCode('black');
+          showMessage({
+            type: 'error',
+            message: res.msg
+          })
+        }
+      })
+}
+
+function getSmsCode() {
+  // 模拟发送短信验证码的请求
+  // 实际应用中,这里应该是向服务器发送请求,并处理响应
+  sendZymlVerificationCode(userId.value,formInfo.value.codeUserInput_message)
+      .then(res =>{
+        if(res.code == '200'){
+          showMessage({
+            type: 'success',
+            message: res.msg
+          });
+          // 设置60秒倒计时
+          countdown.value = 60;
+          const intervalId = setInterval(() => {
+            if (countdown.value > 0) {
+              countdown.value -= 1;
+            } else {
+              clearInterval(intervalId);
+            }
+          }, 1000);
+        }else{
+          changeValidCode();
+          showMessage({
+            type: 'error',
+            message: res.msg
+          })
+        }
+      })
+  console.log('发送短信验证码到手机号');
+
+}
+onMounted(() => {
+
+})
+let showObj= ref({
+  isUserNameEmptyShow:false,
+  isPsdErrorEmptyShow:false,
+  isValidCodeEmptyShow:false,
+  isValidCodeErrorShow:false,
+})
+let formInfo = ref({
+  psd:'',
+  username:'',
+  codeUserInput:'',
+  vCodeReal:'',  //图片验证码实际返回路径
+  codeUserInput_phone:'',   //手机号图片验证码
+  phone:'', //手机号
+  codeUserInput_message:'',  //短信图片验证码
+  message:'', //短信验证码
+  register_message:'', //注册短信验证码
+})
+</script>
+
+<style scoped lang="scss">
+#login-page{
+  .title{
+    position: absolute;
+    >.text{
+
+      font-size: 50px;
+      color: #EFF8FC;
+      line-height: 83px;
+      text-transform: uppercase;
+      letter-spacing: 10px;
+      //background-image: url("../../assets/imgs/img.png");
+      background: linear-gradient(0deg, #EFF8FC 0%, #E9F8FF 0%,#59C8FF 100%);
+      -webkit-background-clip: text;
+      animation: wave 30s linear infinite;
+      -webkit-text-fill-color: transparent;
+
+    }
+
+    top: 50px;
+    left: 50px;
+    width: 539px;
+    height: 83px;
+    background: url("../../assets/imgs/bk-big.png");
+  }
+  .error{
+    position: absolute;
+    margin-top: -30px;
+    color: red;
+  }
+  .message{
+    height: 40px;
+    width: 100%;
+    color: white;
+    display: flex;
+    align-items: flex-end;
+    justify-content: center;
+  }
+  .valid-code {
+    cursor: pointer;
+    height:50px;
+
+  }
+  .btn{
+    cursor: pointer;
+    color: #01030E;
+    font-size: 26px;
+    width: 270px;
+    height: 70px;
+    margin: 0 auto;
+    border-radius: 35px;
+    line-height: 70px;
+    text-align: center;
+    background-color: #fff;
+  }
+  .form-item{
+
+    margin-bottom: 40px;
+  }
+  :deep{
+    .el-input__wrapper{
+      .el-input__inner{
+        color: #fff;
+        height: 54px;
+        line-height: 54px;
+      }
+      background: rgba(0,0,0,0.25);
+      box-shadow: 0 0 0 1px var(--el-input-border-color,var(--el-border-color)) inset;
+      border-radius:0;
+    }
+  }
+  height: 100%;
+  width: 100%;
+  background: url("@/assets/imgs/middle-ground.jpg");
+  background-size: 100% 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  text-align: center;
+  .login-content{
+    .form-item{
+      img{
+        width: 32px;
+      }
+      .login_img{
+        width: 200px;
+        height: 40px;
+      }
+    }
+    .welcome{
+      line-height: 50px;
+      color: #fff;
+      font-size: 36px;
+      font-weight: bold;
+      margin-bottom: 40px;
+    }
+    box-sizing: border-box;
+    width: 580px;
+    padding: 50px;
+    background: rgba(0,0,0,0.3);
+
+  }
+  .dialog-content{
+    :deep{
+      .el-input__inner {
+        --el-input-inner-height: calc(var(--el-input-height, 3.299vh) - .206vh);
+        width: 100%;
+        flex-grow: 1;
+        -webkit-appearance: none;
+        color: var(--el-input-text-color, var(--el-text-color-regular));
+        font-size: inherit;
+        height: var(--el-input-inner-height);
+        line-height: var(--el-input-inner-height);
+        padding: 0;
+        outline: 0;
+        border: none;
+        background: 0 0;
+        box-sizing: border-box;
+      }
+
+      .el-input__wrapper {
+        display: inline-flex;
+        flex-grow: 1;
+        align-items: center;
+        justify-content: center;
+        padding: 1px 1.134vh;
+        background-color: var(--el-input-bg-color, var(--el-fill-color-blank));
+        background-image: none;
+        border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
+        cursor: text;
+        transition: var(--el-transition-box-shadow);
+        transform: translateZ(0);
+        box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color)) inset;
+      }
+
+      .el-input__wrapper{
+        .el-input__inner{
+          height: 54px;
+          line-height: 54px;
+        }
+        border-radius:0;
+      }
+      .el-input__wrapper.is-focus{
+        box-shadow: 0 0 0 1px var(--el-input-focus-border-color) inset;
+      }
+    }
+    .custom-block{
+      padding: 8px 16px;
+      background-color: rgba(64,158,255,0.1);
+      border-radius: 4px;
+      border-left: 5px solid var(--el-color-primary);
+      margin: 20px 0;
+
+      .custom-block-title {
+        margin-bottom: 20px;
+        font-weight: 700;
+      }
+      .custom-block-content{
+        text-align: left;
+      }
+    }
+  }
+}
+</style>