Bladeren bron

Merge branch 'xinyan'

xinyan 6 maanden geleden
bovenliggende
commit
632aa58217

+ 6 - 0
package-lock.json

@@ -19,6 +19,7 @@
 				"@vitejs/plugin-vue-jsx": "^3.0.0",
 				"@wangeditor/editor": "^5.1.23",
 				"@wangeditor/editor-for-vue": "^5.1.12",
+				"@wecom/jssdk": "^2.2.4",
 				"autoprefixer": "^10.4.14",
 				"axios": "^1.2.1",
 				"countup.js": "^2.3.2",
@@ -4258,6 +4259,11 @@
 				"snabbdom": "^3.1.0"
 			}
 		},
+		"node_modules/@wecom/jssdk": {
+			"version": "2.2.4",
+			"resolved": "https://registry.npmmirror.com/@wecom/jssdk/-/jssdk-2.2.4.tgz",
+			"integrity": "sha512-AmR3mLAr2PfiXCtks9cAlwGhtQ2lJGJYpmy4uEkji8TXPeZQPeXwwUHMsCgCZlU81Hjtg3+3N+oM/4CuPAVNNA=="
+		},
 		"node_modules/abort-controller": {
 			"version": "3.0.0",
 			"resolved": "https://registry.npmmirror.com/abort-controller/-/abort-controller-3.0.0.tgz",

+ 1 - 0
package.json

@@ -20,6 +20,7 @@
 		"@vitejs/plugin-vue-jsx": "^3.0.0",
 		"@wangeditor/editor": "^5.1.23",
 		"@wangeditor/editor-for-vue": "^5.1.12",
+		"@wecom/jssdk": "^2.2.4",
 		"autoprefixer": "^10.4.14",
 		"axios": "^1.2.1",
 		"countup.js": "^2.3.2",

+ 5 - 0
src/utils/emitter.ts

@@ -0,0 +1,5 @@
+import mitt from 'mitt'
+
+const emitter = mitt()
+
+export default emitter

+ 8 - 0
src/views/system/login/api.ts

@@ -19,3 +19,11 @@ export function getUserInfo() {
         method: 'get',
     });
 }
+
+export function WeComLogin(query: any) {
+    return request({
+        url: '/api/system/wechat/login/',
+        method: 'get',
+        params: query,
+    });
+}

+ 18 - 0
src/views/system/login/component/account.vue

@@ -67,6 +67,7 @@ import { SystemConfigStore } from '/@/stores/systemConfig';
 import { BtnPermissionStore } from '/@/plugin/permission/store.permission';
 import { Md5 } from 'ts-md5';
 import { errorMessage } from '/@/utils/message';
+import emitter from '/@/utils/mitt';
 
 export default defineComponent({
 	name: 'loginAccount',
@@ -166,6 +167,23 @@ export default defineComponent({
 			useUserInfo().setUserInfos();
 		};
 
+    emitter.on('scan-wecomLogin', (userInfo: any) => {
+      if (userInfo.loginInfo.code == 2000) {
+        Session.set('token', userInfo.loginInfo.data.access)
+        Cookies.set('username', userInfo.loginInfo.data.name)
+        if (!themeConfig.value.isRequestRoutes) {
+          // 前端控制路由,2、请注意执行顺序
+          // console.log('成功获取token,开始初始化前端路由')
+          initFrontEndControlRoutes()
+          loginSuccess()
+        } else {
+          initBackEndControlRoutes()
+          loginSuccess()
+        }
+        emitter.off('scan-wecomLogin')
+      }
+    })
+
 
 		// 登录成功后的跳转
 		const loginSuccess = () => {

+ 89 - 50
src/views/system/login/component/scan.vue

@@ -1,59 +1,98 @@
-<template>
-	<div class="login-scan-container">
-		<div ref="qrcodeRef"></div>
-		<div class="font12 mt20 login-msg">{{ $t('message.scan.text') }}</div>
-	</div>
-</template>
+<script lang="ts" setup>
+import { onMounted } from 'vue';
+import * as ww from '@wecom/jssdk';
+import { WeComLogin } from '../api';
+import emitter from '/@/utils/emitter';
 
-<script lang="ts">
-import { ref, defineComponent, onMounted } from 'vue';
-import QRCode from 'qrcodejs2-fixes';
-
-export default defineComponent({
-	name: 'loginScan',
-	setup() {
-		const qrcodeRef = ref<HTMLElement | null>(null);
-		// 初始化生成二维码
-		const initQrcode = () => {
-			(qrcodeRef.value as HTMLElement).innerHTML = '';
-			new QRCode(qrcodeRef.value, {
-				text: `https://jq.qq.com/?_wv=1027&k=hUu2GeU1`,
-				width: 260,
-				height: 260,
-				colorDark: '#000000',
-				colorLight: '#ffffff',
-			});
-		};
-		// 页面加载时
-		onMounted(() => {
-			initQrcode();
-		});
-		return { qrcodeRef };
-	},
+const props = defineProps({
+  isScan: {
+    type: Boolean,
+    default: false,
+  },
+});
+
+// 初始化企业微信扫码登录
+function initWeComQRCode() {
+  ww.createWWLoginPanel({
+    el: '#wx_qrcode',
+    params: {
+      login_type: 'CorpApp',
+      appid: 'ww467ec1685e8262e6', // 企业微信企业 ID
+      agentid: '1000074', // 应用 AgentID
+      redirect_uri: 'http://operate.zosi.com.cn/web/', //正式环境网址
+      state: 'Wechat',
+      scope: 'snsapi_privateinfo',
+      redirect_type: 'callback',
+    },
+    onCheckWeComLogin({ isWeComLogin }) {
+      // console.log(isWeComLogin)
+    },
+    onLoginSuccess({ code }) {
+      handleWeComLogin({ code: code, state: 'Wechat' });
+    },
+    onLoginFail(err) {
+      // console.log(err)
+    },
+  });
+}
+
+async function handleWeComLogin(query: any) {
+  // console.log('扫码成功')
+  try {
+    const res = await WeComLogin(query);
+    if (res) {
+      emitter.emit('scan-wecomLogin', { loginInfo: res });
+      // console.log('发送跳转')
+    }
+  } catch (error) {
+    console.log('error:', error);
+  }
+}
+
+onMounted(() => {
+  if (props.isScan) {
+    initWeComQRCode();
+  }
 });
 </script>
 
-<style scoped lang="scss">
+<template>
+  <div class="login-scan-container">
+    <div id="wx_qrcode"></div>
+    <!--<div class="font12 mt20 login-msg">{{ $t('message.scan.text') }}</div>-->
+  </div>
+</template>
+
+
+<style lang="scss" scoped>
 .login-scan-animation {
-	opacity: 0;
-	animation-name: error-num;
-	animation-duration: 0.5s;
-	animation-fill-mode: forwards;
+  opacity: 0;
+  animation-name: error-num;
+  animation-duration: 0.5s;
+  animation-fill-mode: forwards;
 }
+
 .login-scan-container {
-	padding: 20px;
-	display: flex;
-	flex-direction: column;
-	text-align: center;
-	@extend .login-scan-animation;
-	animation-delay: 0.1s;
-	:deep(img) {
-		margin: auto;
-	}
-	.login-msg {
-		color: var(--el-text-color-placeholder);
-		@extend .login-scan-animation;
-		animation-delay: 0.2s;
-	}
+  //padding: 20px;
+  display: flex;
+  align-items: center;
+  flex-direction: column;
+  text-align: center;
+  @extend .login-scan-animation;
+  animation-delay: 0.1s;
+
+  :deep(img) {
+    margin: auto;
+  }
+
+  .login-msg {
+    color: var(--el-text-color-placeholder);
+    @extend .login-scan-animation;
+    animation-delay: 0.2s;
+  }
+}
+
+:deep(#wx_qrcode iframe) {
+  height: 365px;
 }
 </style>

+ 71 - 67
src/views/system/login/index.vue

@@ -1,70 +1,3 @@
-<template>
-	<div class="login-container flex z-10">
-		<div class="login-left">
-			<div class="login-left-logo">
-				<img :src="siteLogo" />
-				<div class="login-left-logo-text">
-					<span>{{ getSystemConfig['login.site_title'] || getThemeConfig.globalViceTitle }}</span>
-					<span class="login-left-logo-text-msg">{{
-						getSystemConfig['login.site_name'] || getThemeConfig.globalViceTitleMsg }}</span>
-				</div>
-			</div>
-			<div class="login-left-img">
-				<img :src="loginMain" />
-			</div>
-			<img :src="loginBg" class="login-left-waves" />
-		</div>
-		<div class="login-right flex z-10">
-			<div class="login-right-warp flex-margin">
-				<span class="login-right-warp-one"></span>
-				<span class="login-right-warp-two"></span>
-				<div class="login-right-warp-mian">
-					<div class="login-right-warp-main-title">{{ getSystemConfig['login.site_title'] ||
-						getThemeConfig.globalTitle }} 欢迎您!</div>
-					<div class="login-right-warp-main-form">
-						<div v-if="!state.isScan">
-							<el-tabs v-model="state.tabsActiveName">
-								<el-tab-pane :label="$t('message.label.one1')" name="account">
-									<Account />
-								</el-tab-pane>
-								<!-- TODO 手机号码登录未接入,展示隐藏 -->
-								<!-- <el-tab-pane :label="$t('message.label.two2')" name="mobile">
-									<Mobile />
-								</el-tab-pane> -->
-							</el-tabs>
-						</div>
-						<Scan v-if="state.isScan" />
-						<div class="login-content-main-sacn" @click="state.isScan = !state.isScan">
-							<i class="iconfont" :class="state.isScan ? 'icon-diannao1' : 'icon-barcode-qr'"></i>
-							<div class="login-content-main-sacn-delta"></div>
-						</div>
-					</div>
-				</div>
-			</div>
-		</div>
-
-		<div class="login-authorization z-10">
-			<p>Copyright © {{ getSystemConfig['login.copyright'] || '2021-2024 django-vue-admin.com' }} 版权所有</p>
-			<p class="la-other">
-				<a href="https://beian.miit.gov.cn" target="_blank">{{ getSystemConfig['login.keep_record'] ||
-					'晋ICP备18005113号-3' }}</a>
-				|
-				<a :href="getSystemConfig['login.help_url'] ? getSystemConfig['login.help_url'] : 'https://django-vue-admin.com'"
-					target="_blank">帮助</a>
-				|
-				<a
-					:href="getSystemConfig['login.privacy_url'] ? getBaseURL(getSystemConfig['login.privacy_url']) : '#'">隐私</a>
-				|
-				<a
-					:href="getSystemConfig['login.clause_url'] ? getBaseURL(getSystemConfig['login.clause_url']) : '#'">条款</a>
-			</p>
-		</div>
-	</div>
-	<div v-if="siteBg">
-		<img :src="siteBg" class="fixed inset-0 z-1 w-full h-full" />
-	</div>
-</template>
-
 <script setup lang="ts" name="loginIndex">
 import { defineAsyncComponent, onMounted, reactive, computed } from 'vue';
 import { storeToRefs } from 'pinia';
@@ -113,12 +46,83 @@ const siteBg = computed(() => {
 	}
 });
 
+function showScan() {
+  state.isScan = !state.isScan;
+}
+
 // 页面加载时
 onMounted(() => {
 	NextLoading.done();
 });
 </script>
 
+<template>
+  <div class="login-container flex z-10">
+    <div class="login-left">
+      <div class="login-left-logo">
+        <img :src="siteLogo" />
+        <div class="login-left-logo-text">
+          <span>{{ getSystemConfig['login.site_title'] || getThemeConfig.globalViceTitle }}</span>
+          <span class="login-left-logo-text-msg">{{
+              getSystemConfig['login.site_name'] || getThemeConfig.globalViceTitleMsg }}</span>
+        </div>
+      </div>
+      <div class="login-left-img">
+        <img :src="loginMain" />
+      </div>
+      <img :src="loginBg" class="login-left-waves" />
+    </div>
+    <div class="login-right flex z-10">
+      <div class="login-right-warp flex-margin">
+        <span class="login-right-warp-one"></span>
+        <span class="login-right-warp-two"></span>
+        <div class="login-right-warp-mian">
+          <div class="login-right-warp-main-title">{{ getSystemConfig['login.site_title'] ||
+          getThemeConfig.globalTitle }} 欢迎您!</div>
+          <div class="login-right-warp-main-form">
+            <div v-if="!state.isScan">
+              <el-tabs v-model="state.tabsActiveName">
+                <el-tab-pane :label="$t('message.label.one1')" name="account">
+                  <Account />
+                </el-tab-pane>
+                <!-- TODO 手机号码登录未接入,展示隐藏 -->
+                <!-- <el-tab-pane :label="$t('message.label.two2')" name="mobile">
+                  <Mobile />
+                </el-tab-pane> -->
+              </el-tabs>
+            </div>
+            <Scan v-if="state.isScan" :isScan="state.isScan" />
+            <div class="login-content-main-sacn" @click="showScan">
+              <i :class="state.isScan ? 'icon-diannao1' : 'icon-barcode-qr'" class="iconfont"></i>
+              <div class="login-content-main-sacn-delta"></div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="login-authorization z-10">
+      <p>Copyright © {{ getSystemConfig['login.copyright'] || '2021-2024 django-vue-admin.com' }} 版权所有</p>
+      <p class="la-other">
+        <a href="https://beian.miit.gov.cn" target="_blank">{{ getSystemConfig['login.keep_record'] ||
+        '晋ICP备18005113号-3' }}</a>
+        |
+        <a :href="getSystemConfig['login.help_url'] ? getSystemConfig['login.help_url'] : 'https://django-vue-admin.com'"
+           target="_blank">帮助</a>
+        |
+        <a
+            :href="getSystemConfig['login.privacy_url'] ? getBaseURL(getSystemConfig['login.privacy_url']) : '#'">隐私</a>
+        |
+        <a
+            :href="getSystemConfig['login.clause_url'] ? getBaseURL(getSystemConfig['login.clause_url']) : '#'">条款</a>
+      </p>
+    </div>
+  </div>
+  <div v-if="siteBg">
+    <img :src="siteBg" class="fixed inset-0 z-1 w-full h-full" />
+  </div>
+</template>
+
 <style scoped lang="scss">
 .login-container {
 	height: 100%;