zx 1 hafta önce
ebeveyn
işleme
0f3a0fb545
2 değiştirilmiş dosya ile 362 ekleme ve 233 silme
  1. 88 2
      src/api/qw/user.js
  2. 274 231
      src/views/qw/user/index.vue

+ 88 - 2
src/api/qw/user.js

@@ -149,8 +149,23 @@ export function exportUser(query) {
     params: query
   })
 }
-
-
+/**
+ * 登录企业微信(发起登录)
+ */
+export function getQwIpad(data) {
+  return request({
+    url: '/qw/user/getQwIpad',
+    method: 'post',
+    data: data
+  })
+}
+export function delQwIpad(data) {
+  return request({
+    url: '/qw/user/delQwIpad',
+    method: 'post',
+    data: data
+  })
+}
 /**
  * 登录企业微信(发起登录)
  */
@@ -161,6 +176,55 @@ export function loginQwCode(data) {
     data: data
   })
 }
+/**
+ * 登录企业微信(发起登录)
+ */
+export function loginQwIpad(data) {
+  return request({
+    url: '/qw/user/loginQwIpad',
+    method: 'post',
+    data: data
+  })
+}
+
+/**
+ * 获取登录状态
+ */
+export function qrCodeStatus(data) {
+  return request({
+    url: '/qw/user/qrCodeStatus',
+    method: 'post',
+    data: data
+  })
+}
+export function qrCodeVerify(data) {
+  return request({
+    url: '/qw/user/qrCodeVerify',
+    method: 'post',
+    data: data
+  })
+}
+export function outLoginQwIpad(data) {
+  return request({
+    url: '/qw/user/outLoginQwIpad',
+    method: 'post',
+    data: data
+  })
+}
+export function twoCode(data) {
+  return request({
+    url: '/qw/user/twoCode',
+    method: 'post',
+    data: data
+  })
+}
+export function twoCodeStatus(data) {
+  return request({
+    url: '/qw/user/twoCodeStatus',
+    method: 'post',
+    data: data
+  })
+}
 /**
  * 取redis里的登录二维码
  */
@@ -234,6 +298,15 @@ export function handleInputAuthAppKey(data) {
   })
 }
 
+// 分配异地主机
+export function handleAllocateRemoteHost(data) {
+  return request({
+    url: '/qw/user/allocateRemoteHost',
+    method: 'post',
+    data
+  });
+}
+
 /**
 * 企业微信员工账号 绑定 云主机
 */
@@ -263,3 +336,16 @@ export function selectCloudAP(data) {
     data: data
   })
 }
+
+/**
+ * 模糊查询企微用户列表
+ * @param params 参数
+ * @returns {*}
+ */
+export function getQwUserListLikeName(params) {
+  return request({
+    url: '/qw/user/getQwUserListLikeName',
+    method: 'get',
+    params: params
+  })
+}

+ 274 - 231
src/views/qw/user/index.vue

@@ -1,4 +1,5 @@
 <template>
+
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
       <el-form-item label="企微主体" prop="corpId">
@@ -67,7 +68,12 @@
       <el-table-column label="企微账号" align="center" prop="qwUserId" />
       <el-table-column label="企微昵称" align="center" prop="qwUserName" />
       <el-table-column label="员工称呼" align="center" prop="welcomeText" />
-<!--      <el-table-column label="所属部门" align="center" prop="departmentName" />-->
+      <el-table-column label="所属部门" align="center" prop="isDel">
+        <template slot-scope="scope">
+          <el-tag v-if="scope.row.isDel == 0" type="success">正常</el-tag>
+          <el-tag v-else type="error">离职</el-tag>
+        </template>
+      </el-table-column>
       <el-table-column label="联系我二维码" align="center" prop="contactWay" >
         <template slot-scope="scope">
           <el-image
@@ -80,12 +86,12 @@
       </el-table-column>
       <el-table-column label="绑定的AI客服" align="center" prop="fastGptRoleName" />
       <el-table-column label="授权码" align="center" prop="appKey" />
-<!--      <el-table-column label="企微状态" align="center" prop="loginStatus">-->
-<!--        <template slot-scope="scope">-->
-<!--          <el-tag v-if="scope.row.loginStatus == 1 && scope.row.toolStatus==1" type="success">在线</el-tag>-->
-<!--          <el-tag v-else type="danger">离线</el-tag>-->
-<!--        </template>-->
-<!--      </el-table-column>-->
+     <el-table-column label="ai状态" align="center" prop="loginStatus">
+        <template slot-scope="scope">
+          <el-tag v-if="scope.row.ipadStatus == 1" type="success">在线</el-tag>
+          <el-tag v-else type="danger">离线</el-tag>
+        </template>
+      </el-table-column>
 <!--      <el-table-column label="插件状态" align="center" prop="toolStatus">-->
 <!--        <template slot-scope="scope">-->
 <!--          <el-tag v-if="scope.row.toolStatus == 1" type="success">在线</el-tag>-->
@@ -114,29 +120,60 @@
             修改员工称呼
           </el-button>
 
-<!--          <el-button-->
-<!--            v-if="scope.row.toolStatus==1"-->
-<!--            size="mini"-->
-<!--            type="text"-->
-<!--            icon="el-icon-sunny"-->
-<!--            plain-->
-<!--            @click="handleLoginQwCode(scope.row)"-->
-<!--            v-hasPermi="['qw:user:login']"-->
-<!--          >-->
-<!--            登录企微-->
-<!--          </el-button>-->
-<!--          <el-button-->
-<!--            v-if="scope.row.appKey!=null && scope.row.toolStatus === 1 && scope.row.loginStatus === 1"-->
-<!--            size="mini"-->
-<!--            type="text"-->
-<!--            icon="el-icon-moon"-->
-<!--            plain-->
-<!--            @click="handleLoginOutQwStatus(scope.row)"-->
-<!--            v-hasPermi="['qw:user:login']"-->
-<!--          >-->
-<!--            退出企微-->
-<!--          </el-button>-->
-
+          <el-button
+            v-if="scope.row.serverStatus==1&&scope.row.ipadStatus!=1"
+            size="mini"
+            type="text"
+            icon="el-icon-sunny"
+            plain
+            @click="handleLoginQwCode(scope.row)"
+            v-hasPermi="['qw:user:login']"
+          >
+            登录企微
+          </el-button>
+         <el-button
+			v-if="scope.row.serverStatus==1&&scope.row.ipadStatus==1"
+            size="mini"
+            type="text"
+            icon="el-icon-moon"
+            plain
+            @click="handleLoginOutQwStatus(scope.row)"
+            v-hasPermi="['qw:user:login']"
+          >
+            退出企微
+          </el-button>
+		<el-button
+			v-if="scope.row.ipadStatus==1"
+		   size="mini"
+		   type="text"
+		   icon="el-icon-moon"
+		   plain
+		   @click="handleTwoCode(scope.row)"
+		   v-hasPermi="['qw:user:login']">
+		   二次验证
+		 </el-button>
+		 <el-button
+		 	v-if="scope.row.serverStatus!=1"
+		    size="mini"
+		    type="text"
+		    icon="el-icon-moon"
+		    plain
+		    @click="handleGetQwIpad(scope.row)"
+		    v-hasPermi="['qw:user:login']"
+		  >
+		    获取Ai主机
+		  </el-button>
+		  <el-button
+		  	v-if="scope.row.serverStatus==1 && scope.row.ipadStatus!=1"
+		     size="mini"
+		     type="text"
+		     icon="el-icon-moon"
+		     plain
+		     @click="handleDelQwIpad(scope.row)"
+		     v-hasPermi="['qw:user:login']"
+		   >
+		     解绑Ai主机
+		   </el-button>
         </template>
       </el-table-column>
       <el-table-column label="主机" align="center" class-name="small-padding fixed-width" width="110px" fixed="right">
@@ -163,17 +200,17 @@
           >
             绑定主机
           </el-button>
-          <el-button
-            v-if="scope.row.loginCodeUrl!=null"
-            size="mini"
-            type="text"
-            icon="el-icon-video-camera-solid"
-            plain
-            @click="handleCloudAP(scope.row.loginCodeUrl)"
-            v-hasPermi="['qw:user:cloudAP']"
-          >
-            获取主机帐密
-          </el-button>
+<!--          <el-button-->
+<!--            v-if="scope.row.loginCodeUrl!=null"-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-video-camera-solid"-->
+<!--            plain-->
+<!--            @click="handleCloudAP(scope.row.loginCodeUrl)"-->
+<!--            v-hasPermi="['qw:user:cloudAP']"-->
+<!--          >-->
+<!--            获取主机帐密-->
+<!--          </el-button>-->
           <el-button
             v-if="scope.row.loginCodeUrl!=null"
             size="mini"
@@ -275,36 +312,63 @@
     </el-dialog>
     <!--二维码   -->
     <el-dialog
-      :title="qwLogin.title"
-      :visible.sync="qwLogin.open"
+      title="企微二次认证"
+      :visible.sync="qwLoginTwo.open"
       width="600px"
       append-to-body
       custom-class="qr-login-dialog"
     >
       <div class="qr-login-container">
-        <!-- 包裹 el-image 的 div,控制加载状态 -->
-        <div class="image-wrapper" v-loading="imageLoading" element-loading-text="加载中..." element-loading-spinner="el-icon-loading">
-          <!-- 如果图片未加载或加载失败,显示一个占位图 -->
+        <div class="image-wrapper" v-loading="imageLoading" >
           <el-image
-            :src="'data:image/png;base64,' + qwLogin.codeUrl"
+            :src="'data:image/png;base64,' +qwLoginTwo.codeUrl"
             style="display: block; margin: 0 auto; width: 300px; height: 300px;"
-            @click="handleQrCodeClick"
           />
         </div>
-        <p class="qr-login-instructions">使用企业微信扫码授权登录</p>
-        <el-input
-          v-model="qwLogin.code"
-          placeholder="请输入六位验证码 按回车"
-          clearable
-          size="small"
-          type="text"
-          maxlength="6"
-          class="verification-code-input"
-          @input="validateCode"
-          @keyup.native.enter="handleLoginQwCodeMsg"
-        />
-      </div>
+        <p class="qr-login-instructions">二次验证二维码</p>
+		</div>
+		<div slot="footer" class="dialog-footer" >
+		  <el-button type="primary" @click="qwLoginTwo.open=false">确 定</el-button>
+		</div>
     </el-dialog>
+
+	<el-dialog
+	  :title="qwLogin.title"
+	  :visible.sync="qwLogin.open"
+	  width="600px"
+	  append-to-body
+	  custom-class="qr-login-dialog"
+	>
+	  <div class="qr-login-container">
+	    <div class="image-wrapper" v-loading="imageLoading" >
+	      <el-image
+	        :src="'data:image/png;base64,' +qwLogin.codeUrl"
+	        style="display: block; margin: 0 auto; width: 300px; height: 300px;"
+	      />
+	    </div>
+	    <p class="qr-login-instructions">使用企业微信扫码授权登录</p>
+	  </div>
+	</el-dialog>
+
+	<el-dialog
+	  title="输入企微验证码"
+	  :visible.sync="qwCode.open"
+	  width="600px"
+	  append-to-body>
+	 <el-form  :model="qwCode"  label-width="80px" @submit.native.prevent="handleSubmit">
+	     <el-form-item label="验证码" prop="companyName">
+	       <el-input v-model="qwCode.code" placeholder="输入企微6位验证码" />
+	     </el-form-item>
+	</el-form>
+
+	<div slot="footer" class="dialog-footer">
+	  <el-button type="primary" @click="submitCodeForm">确 定</el-button>
+
+	</div>
+	</el-dialog>
+
+
+
     <!-- 大图预览对话框 -->
     <el-dialog
       :visible.sync="dialogVisible"
@@ -333,12 +397,21 @@ import {
   relieveFastGptRoleById,
   staffListUser,
   loginQwCode,
+  loginQwIpad,
   modifyLoginQwStatus,
   loginQwCodeMsg,
   getQwCodeUrl,
+  twoCode,
+  twoCodeStatus,
+  qrCodeStatus,
+  getQwIpad,
+  delQwIpad,
   logoutQwLogout,
+  qrCodeVerify,
+  outLoginQwIpad,
   loginQwCodeUrl,
   getLoginQwStatus,
+  handleAllocateRemoteHost,
   qwBindCloudHost, qwUnbindCloudHost, handleAuthAppKey, handleInputAuthAppKey, selectCloudAP
 } from '@/api/qw/user'
 import fastGptRole from "@/views/fastGpt/fastGptRole/fastGptRole";
@@ -399,7 +472,18 @@ export default {
         code:null,
         appKey:null,
       },
-
+	 qwLoginTwo:{
+        title:"",
+        open:false,
+        codeUrl:null,
+        code:null,
+        appKey:null,
+     },
+	qwCode:{
+        title:"",
+        open:false,
+        code:null,
+      },
       cloudAPOpen:{
         open:false,
         admin:null,
@@ -414,9 +498,9 @@ export default {
         id:null,
         welcomeText:null,
       },
-      qrCodeInterval:null,
+      twoCodeInterval:null,
       loginQwInterval:null,
-      loginOutQwInterval:null,
+
       imageLoading: true, // 控制加载状态
       // 查询参数
       queryParams: {
@@ -426,6 +510,7 @@ export default {
         corpId: null,
         qwUserName: null,
       },
+	  qwUserId:null,
       companyUserList:[],
       // 表单参数
       form: {
@@ -463,41 +548,18 @@ export default {
     'qwLogin.open'(newVal) {
       if (!newVal) {
         // 如果弹窗关闭,清除定时器
-        this.beforeDestroy();
+        clearInterval(this.loginQwInterval);
 
       }
     },
   },
   methods: {
-    // handleChangeIP(row){
-    //   this.updateIp.open = true
-    //   this.updateIpForm.id = row.id
-    //   this.updateIpForm.newIp = null;
-    // },
-    // submitUpdateIpForm(){
-    //   if (this.updateIpForm.newIp==null){
-    //     this.$message.warning("请填写IP")
-    //     return
-    //   }
-    //   const data = {
-    //     id : this.updateIpForm.id,
-    //     loginCodeUrl : this.updateIpForm.newIp
-    //   }
-    //
-    //   updateUser(data).then(response => {
-    //     this.msgSuccess("绑定成功");
-    //     this.updateIp.open = false;
-    //     this.getList();
-    //   });
-    // },
-    /** 查询企微用户列表 */
     getList() {
       this.loading = true;
       staffListUser(this.queryParams).then(response => {
         this.userList = response.rows;
         this.total = response.total;
         this.loading = false;
-
       });
 
     },
@@ -523,172 +585,153 @@ export default {
     },
     //登录
     handleLoginQwCode(val){
-
-      // v-if="scope.row.appKey!=null && scope.row.toolStatus === 1 && scope.row.loginStatus === 0"
       if (val.appKey==null || val.appKey===''){
         return this.$message.warning("没有授权码,无法登录企业微信,请授权");
       }
+      loginQwIpad({qwUserId:val.id}).then(res => {
+		this.qwUserId=val.id;
+        this.qwLogin.code=null;
+        this.imageLoading=false;
+		console.log(res)
+		if(res.msg=="success"){
+			this.qwLogin.codeUrl=res.qrCode64
+			this.qwLogin.open=true;
+			this.loginQwPolling();
+		}else{
+			this.$message.success(res.msg);
+			this.getList()
+		}
 
-      if (val.toolStatus===0 || val.toolStatus==null ){
-        return this.$message.warning("插件离线了,无法登录企业微信,请联系管理员~");
-      }
-
-      if (val.loginStatus===1 && val.toolStatus===1){
-        return this.$message.success("已经登录了,无需重复登录");
-      }
-
-      loginQwCode({appKey:val.appKey}).then(res => {
-        this.qwLogin.appKey=val.appKey;
-        this.qwLogin.open=true;
-        this.imageLoading=true;
+      })
+    },
 
-        //定时器 获取登录状态(有自动登录的)
-        this.loginQwPolling();
+	handleTwoCode(val){
 
-        // 调用后台接口获取新的二维码URL
-        loginQwCodeUrl({ appKey: this.qwLogin.appKey }).then(res => {
-          getQwCodeUrl({appKey:this.qwLogin.appKey}).then(res=>{
-            this.qwLogin.codeUrl=res.base64 // 更新二维码URL
-          }).catch(()=>{
-            this.resetQwLogin();
-          }).finally(()=>{
-            this.imageLoading=false;
-          })
+		twoCode({ qwUserId: val.id }).then(res => {
+		console.log(res)
+		this.qwLoginTwo.open=true;
+		this.qwLoginTwo.codeUrl=res.qrCode
 
         });
 
-        // setTimeout(()=>{
-        //
-        //     getQwCodeUrl({appKey:val.appKey}).then(res=>{
-        //       this.qwLogin.codeUrl=res.base64
-        //     }).catch(()=>{
-        //       this.resetQwLogin();
-        //     }).finally(()=>{
-        //       this.imageLoading=false;
-        //     })
-        //
-        // },3000)
-
-        // 启动定时器,每隔45秒更新一次二维码
-        this.startQrCodePolling();
-
-      })
-    },
-
-    // 每隔45秒请求一次二维码
-    startQrCodePolling() {
-      this.qrCodeInterval = setInterval(() => {
-        this.refreshQrCode();
-      }, 45000);  // 45秒更新一次
-    },
 
+	},
+	twoCodePolling() {
+	  this.twoCodeInterval = setInterval(() => {
+	    twoCodeStatus({ qwUserId: this.qwUserId }).then(res => {
+			console.log(res)
+
+	      if (res.msg==104001) {
+			this.$message.success('登录成功');
+			this.clearDl()
+	        clearInterval(this.loginQwInterval);
+	      }else if(res.msg==100004){
+			  this.clearDl()
+		  }
+	    });
+	  }, 3000);
+	},
     loginQwPolling() {
-      let elapsedTime = 0;  // 记录已执行的时间(单位:秒)
-
       this.loginQwInterval = setInterval(() => {
-        // 每次轮询后增加已执行的时间
-        elapsedTime += 5;  // 因为每 3 秒执行一次
-
-        // 请求登录状态
-        getLoginQwStatus({ appKey: this.qwLogin.appKey }).then(res => {
-          if (res.status==1) {
-            this.$message.success('登录成功');
-            clearInterval(this.loginQwInterval);  // 登录成功,停止轮询
-            this.resetQwLogin();
-          }
-          // 判断是否超过最大轮询时间(60秒)
-          if (elapsedTime >= 90) {
-            clearInterval(this.loginQwInterval);  // 超过90秒停止轮询
-            this.$message.warning('登录超时,请稍后再试!')
-            this.resetQwLogin();
-          }
+        qrCodeStatus({ qwUserId: this.qwUserId }).then(res => {
+			console.log(res)
+			if (res.msg==22) {
+				this.$message.success('账号企业不一致请重新扫码登录');
+				this.clearDl();
+			}
+          if (res.msg==104001) {
+			this.$message.success('登录成功');
+			this.clearDl()
+
+          }else if(res.msg==100004){
+			  this.qwCode.open=true;
+			  clearInterval(this.loginQwInterval);
+		  }
         });
-      }, 3000);  // 每 3 秒更新一次
-    },
-
-    // 退出时清除定时器
-    beforeDestroy() {
-      if (this.qrCodeInterval) {
-        clearInterval(this.qrCodeInterval);  // 清除定时器
-      }
-      if (this.loginQwInterval) {
-        clearInterval(this.loginQwInterval);  // 清除定时器
-      }
-      if (this.loginOutQwInterval){
-        clearInterval(this.loginOutQwInterval);  // 清除定时器
-      }
-      this.resetQwLogin();
-    },
-
-    // 刷新二维码
-    refreshQrCode() {
-      // 调用后台接口获取新的二维码URL
-      loginQwCodeUrl({ appKey: this.qwLogin.appKey }).then(res => {
-        getQwCodeUrl({appKey:this.qwLogin.appKey}).then(res=>{
-          this.qwLogin.codeUrl=res.base64 // 更新二维码URL
-        }).catch(()=>{
-          this.resetQwLogin();
-        }).finally(()=>{
-          this.imageLoading=false;
-        })
-
-      });
+      }, 3000);
     },
+	submitCodeForm(){
+
+		qrCodeVerify({ code: this.qwCode.code,qwUserId: this.qwUserId }).then(res => {
+			console.log(res)
+
+			this.$message.success('验证成功账号信息确认中。。。。');
+			this.qwCode.open=false;
+			 this.loginQwInterval = setTimeout(() => {
+			     qrCodeStatus({ qwUserId: this.qwUserId }).then(res => {
+			         console.log(res);
+			         if (res.msg == 23) {
+			             this.$message.error('账号不一致请重新扫码登录');
+			             this.clearDl();
+			         }
+					 if (res.msg == 22) {
+					     this.$message.error('账号企业不一致请重新扫码登录');
+					     this.clearDl();
+					 }
+			         if (res.msg == 104001) {
+			             this.$message.success('登录成功');
+			             this.clearDl();
+			         }
+			     });
+			 }, 4000);
+		});
+	},
+
+	clearDl(){
+		this.qwCode.open=false;
+		this.qwLogin.open=false;
+		clearInterval(this.loginQwInterval);
+		this.getList()
+	},
 
-    handleQrCodeClick(){
-      this.imageLoading=true;
-      // 调用后台接口获取新的二维码URL
-      loginQwCodeUrl({ appKey: this.qwLogin.appKey }).then(res => {
-
-        setTimeout(()=>{
-          getQwCodeUrl({appKey:this.qwLogin.appKey}).then(res=>{
-
-            //确保万一再调用一下刷新二维码
-            this.qwLogin.codeUrl=res.base64 // 更新二维码URL
-
-          }).catch(()=>{
-            this.resetQwLogin();
-          }).finally(()=>{
-            this.imageLoading=false;
-          })
-
-        },3000)
 
 
-      });
-    },
     //退出
     handleLoginOutQwStatus(val){
-      this.loading=true;
-      logoutQwLogout({appKey:val.appKey,loginStatus:0}).then(res => {
-
-        let elapsedTime = 0;  // 记录已执行的时间(单位:秒)
-
-        this.loginOutQwInterval = setInterval(() => {
-          // 每次轮询后增加已执行的时间
-          elapsedTime += 3;  // 因为每 3 秒执行一次
-
-          // 请求登录状态
-          getLoginQwStatus({ appKey: val.appKey }).then(res => {
-            if (res.status==0) {
-              this.$message.success('退出成功');
-              clearInterval(this.loginOutQwInterval);  // 登录成功,停止轮询
-              this.resetQwLogin();
-            }
-
-            // 判断是否超过最大轮询时间(60秒)
-            if (elapsedTime >= 90) {
-              clearInterval(this.loginOutQwInterval);  // 超过90秒停止轮询
-              this.$message.warning('退出超时,请多等待后刷新页面!')
-              this.resetQwLogin();
-
-            }
-          });
-        }, 3000);  // 每 3 秒更新一次
+      outLoginQwIpad({qwUserId: val.id}).then(res => {
 
+        this.$message.success("退出登录成功");
+		this.getList()
       })
+
     },
 
+
+	handleGetQwIpad(val){
+    getQwIpad({ qwUserId: val.id }).then(res => {
+      this.$message.success("获取主机成功");
+      this.getList();
+    }).catch(error => {
+      console.log(error);
+      if (error.code  === 501) {
+        this.$confirm(
+          '当前区域没有多余的名额,将为你分配异地名额,会导致企业微信需要扫脸重新登录,并且半个小时后需要进行验证',
+          '提示',
+          {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning',
+            dangerouslyUseHTMLString: true
+          }
+        ).then(() => {
+          return handleAllocateRemoteHost({ qwUserId: val.id });
+        }).then(res => {
+          this.$message.success('异地主机分配成功');
+          this.getList();
+        }).catch(() => {
+          this.$message.info('已取消异地主机分配');
+        });
+      } else {
+        this.$message.error('获取主机失败');
+      }
+    });
+	},
+	handleDelQwIpad(val){
+	  delQwIpad({qwUserId: val.id}).then(res => {
+	    this.$message.success("解绑主机成功");
+		this.getList()
+	  })
+	},
     //传验证码
     handleLoginQwCodeMsg(){
       loginQwCodeMsg({appKey: this.qwLogin.appKey,code:this.qwLogin.code}).then(res => {