From cfe0b79fbea0fb1d7a5a796e71ada7d3b7812046 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期一, 15 十二月 2025 22:31:33 +0800
Subject: [PATCH] feat: 企业微信发送微信小程序cetd

---
 app/pages/login.vue |  496 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 446 insertions(+), 50 deletions(-)

diff --git a/app/pages/login.vue b/app/pages/login.vue
index 7f0e8c8..e30db61 100644
--- a/app/pages/login.vue
+++ b/app/pages/login.vue
@@ -1,9 +1,9 @@
 <template>
-  <view class="normal-login-container">
+  <scroll-view class="normal-login-container" scroll-y="true">
     <view class="logo-content align-center justify-center flex">
       <image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix">
       </image>
-      <text class="title">鑻ヤ緷绉诲姩绔櫥褰�</text>
+      <text class="title">姘戣埅璋冨害绯荤粺</text>
     </view>
     <view class="login-form-content">
       <view class="input-item flex align-center">
@@ -14,32 +14,57 @@
         <view class="iconfont icon-password icon"></view>
         <input v-model="loginForm.password" type="password" class="input" placeholder="璇疯緭鍏ュ瘑鐮�" maxlength="20" />
       </view>
-      <view class="input-item flex align-center" style="width: 60%;margin: 0px;" v-if="captchaEnabled">
+      <view class="input-item flex align-center captcha-container" v-if="captchaEnabled">
         <view class="iconfont icon-code icon"></view>
         <input v-model="loginForm.code" type="number" class="input" placeholder="璇疯緭鍏ラ獙璇佺爜" maxlength="4" />
         <view class="login-code"> 
-          <image :src="codeUrl" @click="getCode" class="login-code-img"></image>
+          <image :src="codeUrl" @click="getCode" class="login-code-img" mode="aspectFit"></image>
         </view>
       </view>
+      <view class="agreement-checkbox">
+        <checkbox-group @change="onAgreementChange">
+          <label class="checkbox-label">
+            <checkbox :checked="agreedToPolicy" value="agreed" color="#007AFF" class="round-checkbox" style="margin-top: 0;" />
+            <text class="agreement-text">
+              <text class="text-grey1">鍚屾剰</text>
+              <text @click.stop="handleUserAgrement" class="text-blue agreement-link">銆婄敤鎴峰崗璁��</text>
+              <text class="text-grey1">鍜�</text>
+              <text @click.stop="handlePrivacy" class="text-blue agreement-link">銆婇殣绉佹斂绛栥��</text>
+            </text>
+          </label>
+        </checkbox-group>
+      </view>
+      
       <view class="action-btn">
         <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">鐧诲綍</button>
-      </view>
-      <view class="reg text-center" v-if="register">
-        <text class="text-grey1">娌℃湁璐﹀彿锛�</text>
-        <text @click="handleUserRegister" class="text-blue">绔嬪嵆娉ㄥ唽</text>
-      </view>
-      <view class="xieyi text-center">
-        <text class="text-grey1">鐧诲綍鍗充唬琛ㄥ悓鎰�</text>
-        <text @click="handleUserAgrement" class="text-blue">銆婄敤鎴峰崗璁��</text>
-        <text @click="handlePrivacy" class="text-blue">銆婇殣绉佸崗璁��</text>
+        <!-- 寰俊涓�閿櫥褰曟寜閽�(浠呭湪寰俊灏忕▼搴忕幆澧冩樉绀�) -->
+        <!-- #ifdef MP-WEIXIN -->
+        <button 
+          v-if="isWechat && wechatOpenId" 
+          @click="loginByOpenId" 
+          class="wechat-login-btn cu-btn block bg-green lg round"
+          style="margin-top: 20rpx;">
+          <text class="cuIcon-wechat" style="margin-right: 10rpx;"></text>
+        鎵嬫満鍙风爜蹇嵎鐧诲綍
+        </button>
+        <button 
+          v-else-if="isWechat"
+          open-type="getPhoneNumber" 
+          @getphonenumber="onGetPhoneNumber"
+          class="wechat-login-btn cu-btn block bg-green lg round"
+          style="margin-top: 20rpx;">
+          <text class="cuIcon-wechat" style="margin-right: 10rpx;"></text>
+          鎵嬫満鍙风爜蹇嵎鐧诲綍
+        </button>
+        <!-- #endif -->
       </view>
     </view>
-     
-  </view>
+  </scroll-view>
 </template>
 
 <script>
-  import { getCodeImg } from '@/api/login'
+  import { getCodeImg, loginByOpenId, loginByWechatPhone } from '@/api/login'
+  import { isWxWorkEnvironment,redirectToQyLogin } from '@/utils/wechat'
 
   export default {
     data() {
@@ -48,17 +73,38 @@
         captchaEnabled: true,
         // 鐢ㄦ埛娉ㄥ唽寮�鍏�
         register: false,
+        // 闅愮鏀跨瓥鍚屾剰鐘舵��(榛樿鏈�変腑,闇�瑕佺敤鎴蜂富鍔ㄥ嬀閫�)
+        agreedToPolicy: false,
         globalConfig: getApp().globalData.config,
         loginForm: {
-          username: "admin",
-          password: "admin123",
+          username: "",
+          password: "",
           code: "",
           uuid: ''
-        }
+        },
+        // 寰俊涓�閿櫥褰曠浉鍏�
+        isWechat: false, // 鏄惁涓哄井淇″皬绋嬪簭鐜
+        wechatOpenId: '', // 寰俊OpenID
+        wechatUnionId: '', // 寰俊UnionID
+        // 椤甸潰鍙傛暟
+        pageOptions: {}
       }
+    },
+    onLoad(options) {
+      // 淇濆瓨椤甸潰鍙傛暟
+      this.pageOptions = options || {}
+      isWxWorkEnvironment().then(res=>{
+        if(res){
+          // console.log("浼佷笟寰俊鐜 login.vue....")
+          redirectToQyLogin(options,this.$tab);
+        }
+      });
+      
     },
     created() {
       this.getCode()
+      this.checkWechatEnv()
+      this.tryAutoLogin()
     },
     methods: {
       // 鐢ㄦ埛娉ㄥ唽
@@ -67,13 +113,15 @@
       },
       // 闅愮鍗忚
       handlePrivacy() {
-        let site = this.globalConfig.appInfo.agreements[0]
-        this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)
+        this.$tab.navigateTo('/pages/mine/privacy-policy/index')
       },
       // 鐢ㄦ埛鍗忚
       handleUserAgrement() {
-        let site = this.globalConfig.appInfo.agreements[1]
-        this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)
+        this.$tab.navigateTo('/pages/mine/user-agreement/index')
+      },
+      // 鍗忚鍚屾剰鐘舵�佸彉鏇�
+      onAgreementChange(e) {
+        this.agreedToPolicy = e.detail.value.length > 0
       },
       // 鑾峰彇鍥惧舰楠岃瘉鐮�
       getCode() {
@@ -87,6 +135,10 @@
       },
       // 鐧诲綍鏂规硶
       async handleLogin() {
+        if (!this.agreedToPolicy) {
+          this.$modal.msgError("璇峰厛闃呰骞跺悓鎰忕敤鎴峰崗璁拰闅愮鏀跨瓥")
+          return
+        }
         if (this.loginForm.username === "") {
           this.$modal.msgError("璇疯緭鍏ユ偍鐨勮处鍙�")
         } else if (this.loginForm.password === "") {
@@ -113,8 +165,202 @@
       loginSuccess(result) {
         // 璁剧疆鐢ㄦ埛淇℃伅
         this.$store.dispatch('GetInfo').then(res => {
-          this.$tab.reLaunch('/pages/index')
+          // 瑙﹀彂鐧诲綍鎴愬姛浜嬩欢锛屽惎鍔ㄦ秷鎭疆璇�
+          uni.$emit('user-login')
+          // 澶勭悊鑷姩璺宠浆閫昏緫
+          this.redirectAfterLogin()
         })
+      },
+      
+      // ==================== 寰俊涓�閿櫥褰曠浉鍏虫柟娉� ====================
+      
+      // 妫�鏌ユ槸鍚﹀湪寰俊灏忕▼搴忕幆澧�
+      checkWechatEnv() {
+        // #ifdef MP-WEIXIN
+        this.isWechat = true
+        console.log('褰撳墠鐜:寰俊灏忕▼搴�')
+        // #endif
+        
+        // #ifndef MP-WEIXIN
+        this.isWechat = false
+        console.log('褰撳墠鐜:闈炲井淇″皬绋嬪簭')
+        // #endif
+      
+
+      },
+      
+      // 灏濊瘯鑷姩鐧诲綍(妫�鏌ユ湰鍦版槸鍚︽湁淇濆瓨鐨凮penID)
+      tryAutoLogin() {
+        if (!this.isWechat) {
+          return
+        }
+        
+        // 浠庢湰鍦板瓨鍌ㄤ腑鑾峰彇OpenID鍜孶nionID
+        const savedOpenId = uni.getStorageSync('wechat_openid')
+        const savedUnionId = uni.getStorageSync('wechat_unionid')
+        const autoLogin=true;
+        
+        if (savedOpenId && autoLogin) {
+          console.log('妫�娴嬪埌宸蹭繚瀛樼殑OpenID锛屽皾璇曡嚜鍔ㄧ櫥褰�')
+          this.wechatOpenId = savedOpenId
+          this.wechatUnionId = savedUnionId // 鍙兘涓簄ull
+          this.loginByOpenId()
+        }
+      },
+      
+      // 澶勭悊鑾峰彇鎵嬫満鍙风殑鍥炶皟
+      onGetPhoneNumber(e) {
+        console.log('鑾峰彇鎵嬫満鍙峰洖璋�:', e)
+        
+        if (!this.agreedToPolicy) {
+          this.$modal.msgError("璇峰厛闃呰骞跺悓鎰忕敤鎴峰崗璁拰闅愮鏀跨瓥")
+          return
+        }
+        
+        if (e.detail.errMsg === 'getPhoneNumber:ok') {
+          // 鐢ㄦ埛鍚屾剰鎺堟潈
+          const { code } = e.detail
+          
+          this.$modal.loading("姝e湪鑾峰彇鎵嬫満鍙�...")
+          
+          // 鍏堣幏鍙栧井淇$櫥褰昪ode
+          uni.login({
+            provider: 'weixin',
+            success: (loginRes) => {
+              console.log('寰俊鐧诲綍code:', loginRes.code)
+              console.log('鎵嬫満鍙穋ode:', code)
+              
+              // 璋冪敤鍚庣鎺ュ彛,浼犲叆loginCode鍜宲honeCode
+              loginByWechatPhone(loginRes.code, code).then(response => {
+                this.$modal.closeLoading()
+                
+                if (response.code === 200) {
+                  // 鐧诲綍鎴愬姛,淇濆瓨OpenID鍜孶nionID
+                  const openId = response.openId
+                  const unionId = response.unionId
+                  
+                  uni.setStorageSync('wechat_openid', openId)
+                  this.wechatOpenId = openId
+                  
+                  if (unionId) {
+                    uni.setStorageSync('wechat_unionid', unionId)
+                    this.wechatUnionId = unionId
+                  }
+                  
+                  // 淇濆瓨token鍒版湰鍦板瓨鍌ㄥ拰Vuex
+                  const token = response.token
+                  this.$store.commit('SET_TOKEN', token)
+                  // 蹇呴』璋冪敤setToken淇濆瓨鍒版湰鍦板瓨鍌�
+                  const { setToken } = require('@/utils/auth')
+                  setToken(token)
+                  
+                  // 鑾峰彇鐢ㄦ埛淇℃伅骞跺鐞嗚嚜鍔ㄨ烦杞�昏緫
+                  this.$store.dispatch('GetInfo').then(() => {
+                    this.redirectAfterLogin()
+                  });
+                } else {
+                  this.$modal.msgError(response.msg || '鐧诲綍澶辫触')
+                }
+              }).catch(error => {
+                this.$modal.closeLoading()
+                console.error('鐧诲綍澶辫触:', error)
+                this.$modal.msgError('鐧诲綍澶辫触,璇烽噸璇�')
+              })
+            },
+            fail: (err) => {
+              this.$modal.closeLoading()
+              console.error('鑾峰彇寰俊鐧诲綍code澶辫触:', err)
+              this.$modal.msgError('鑾峰彇寰俊淇℃伅澶辫触')
+            }
+          })
+        } else {
+          // 鐢ㄦ埛鎷掔粷鎺堟潈
+          this.$modal.msgError('闇�瑕佹偍鐨勬墜鏈哄彿鎵嶈兘鐧诲綍')
+        }
+      },
+      
+      // 閫氳繃OpenID鍜孶nionID鐧诲綍
+      loginByOpenId() {
+        this.$modal.loading("姝e湪鐧诲綍...")
+        
+        // 鍚屾椂浼犲叆openId鍜寀nionId杩涜鍙岄噸楠岃瘉
+        loginByOpenId(this.wechatOpenId, this.wechatUnionId).then(response => {
+          this.$modal.closeLoading()
+          
+          if (response.code === 200) {
+            // 鐧诲綍鎴愬姛,淇濆瓨token鍒版湰鍦板瓨鍌ㄥ拰Vuex
+            const token = response.token
+            this.$store.commit('SET_TOKEN', token)
+            // 蹇呴』璋冪敤setToken淇濆瓨鍒版湰鍦板瓨鍌�
+            const { setToken } = require('@/utils/auth')
+            setToken(token)
+            
+            // 鑾峰彇鐢ㄦ埛淇℃伅骞跺鐞嗚嚜鍔ㄨ烦杞�昏緫
+            this.$store.dispatch('GetInfo').then(() => {
+              this.redirectAfterLogin()
+            });
+          } else {
+            // OpenID鏈粦瀹氭垨楠岃瘉澶辫触锛岄渶瑕佽幏鍙栨墜鏈哄彿缁戝畾
+            console.log('璇penID灏氭湭缁戝畾鎴栭獙璇佸け璐ワ紝闇�瑕佽幏鍙栨墜鏈哄彿')
+            this.$modal.closeLoading()
+            this.$modal.msgError(response.msg || '璇ュ井淇¤处鍙峰皻鏈粦瀹氾紝璇风偣鍑诲井淇′竴閿櫥褰曟寜閽幏鍙栨墜鏈哄彿鎺堟潈')
+          }
+        }).catch(error => {
+          this.$modal.closeLoading()
+          console.error('鐧诲綍澶辫触:', error)
+          this.$modal.msgError('鐧诲綍澶辫触锛岃閲嶈瘯')
+        })
+      },
+      
+      /**
+       * 鑾峰彇URL鍙傛暟
+       */
+      getUrlParam(name) {
+        // #ifdef H5
+        const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
+        const r = window.location.search.substr(1).match(reg);
+        if (r != null) return decodeURIComponent(r[2]);
+        // #endif
+
+        // #ifdef MP-WEIXIN
+        // 鍦ㄥ皬绋嬪簭涓紝鍙傛暟閫氳繃onLoad鐨刼ptions浼犻��
+        if (this.pageOptions && this.pageOptions[name]) {
+          return decodeURIComponent(this.pageOptions[name]);
+        }
+        // #endif
+
+        return null;
+      },
+      
+      /**
+       * 鐧诲綍鎴愬姛鍚庣殑璺宠浆澶勭悊
+       */
+      redirectAfterLogin() {
+        try {
+          // 妫�鏌ユ槸鍚︽湁redirect鍙傛暟鎸囧畾璺宠浆椤甸潰
+          let redirectUrl = this.getUrlParam("redirect");
+          
+          // 濡傛灉娌℃湁redirect鍙傛暟锛屾鏌ユ槸鍚︽湁淇濆瓨鐨勭洰鏍囬〉闈�
+          if (!redirectUrl) {
+            const { getTargetUrl } = require('@/utils/auth')
+            redirectUrl = getTargetUrl()
+          }
+          
+          if (redirectUrl) {
+            // 瑙g爜redirect鍙傛暟
+            redirectUrl = decodeURIComponent(redirectUrl);
+            console.log("鑷姩璺宠浆鍒版寚瀹氶〉闈�:", redirectUrl);
+            this.$tab.reLaunch(redirectUrl);
+          } else {
+            // 榛樿璺宠浆鍒伴椤�
+            console.log("璺宠浆鍒伴椤�");
+            this.$tab.reLaunch('/pages/index');
+          }
+        } catch (e) {
+          console.error("璺宠浆澶辫触锛屼娇鐢ㄩ粯璁よ烦杞�:", e);
+          // 鍑虹幇寮傚父鏃讹紝榛樿璺宠浆鍒伴椤�
+          this.$tab.reLaunch('/pages/index');
+        }
       }
     }
   }
@@ -127,6 +373,24 @@
 
   .normal-login-container {
     width: 100%;
+    min-height: 100vh;
+    // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘
+    ::-webkit-scrollbar {
+      display: none;
+      width: 0 !important;
+      height: 0 !important;
+      background: transparent;
+    }
+    
+    // Firefox婊氬姩鏉¢殣钘�
+    * {
+      scrollbar-width: none; /* Firefox */
+    }
+    
+    // IE/Edge婊氬姩鏉¢殣钘�
+    * {
+      -ms-overflow-style: none; /* IE 10+ */
+    }
 
     .logo-content {
       width: 100%;
@@ -158,45 +422,177 @@
         .icon {
           font-size: 38rpx;
           margin-left: 10px;
-          color: #999;
         }
 
         .input {
+          margin-left: 20rpx;
           width: 100%;
-          font-size: 14px;
-          line-height: 20px;
-          text-align: left;
-          padding-left: 15px;
+          height: 45px;
+          background: none;
+        }
+      }
+
+      .captcha-container {
+        width: 100%;
+        margin: 20px auto;
+        background-color: #f5f6f7;
+        height: 45px;
+        border-radius: 20px;
+        padding-right: 10rpx;
+        box-sizing: border-box;
+
+        .icon {
+          font-size: 38rpx;
+          margin-left: 10px;
         }
 
+        .input {
+          margin-left: 20rpx;
+          width: 60%;
+          height: 45px;
+          background: none;
+        }
+
+        .login-code {
+          width: 30%;
+          height: 45px;
+          margin-left: 10rpx;
+          border-left: 1px solid #e0e0e0;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+
+          .login-code-img {
+            max-width: 100%;
+            max-height: 45px;
+            object-fit: contain;
+            cursor: pointer;
+          }
+        }
       }
 
-      .login-btn {
-        margin-top: 40px;
-        height: 45px;
+      .action-btn {
+        margin: 40rpx 0;
+
+        .login-btn {
+          height: 90rpx;
+          font-size: 32rpx;
+        }
+        
+        .wechat-login-btn {
+          height: 90rpx;
+          font-size: 32rpx;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+        }
       }
-      
+
       .reg {
-        margin-top: 15px;
+        margin: 20rpx 0;
+
+        .text-grey1 {
+          color: #888;
+        }
+
+        .text-blue {
+          margin: 0 10rpx;
+          color: #007AFF;
+        }
       }
       
-      .xieyi {
-        color: #333;
-        margin-top: 20px;
-      }
-      
-      .login-code {
-        height: 38px;
-        float: right;
-      
-        .login-code-img {
-          height: 38px;
-          position: absolute;
-          margin-left: 10px;
-          width: 200rpx;
+      .agreement-checkbox {
+        margin: 50rpx 0 30rpx 0;
+        padding: 20rpx;
+        display: flex;
+        justify-content: flex-start;
+        align-items: left;
+        
+        checkbox-group {
+          display: flex;
+          align-items: center;
+        }
+        
+        .checkbox-label {
+          display: flex;
+          align-items: center;
+          justify-content: flex-start;
+          
+          checkbox {
+            margin-right: 15rpx;
+            transform: scale(1.2);
+            flex-shrink: 0;
+            vertical-align: middle;
+          }
+          
+          // 鍦嗗舰澶嶉�夋鏍峰紡
+          .round-checkbox {
+            border-radius: 50% !important;
+          }
+          
+          // 閽堝寰俊灏忕▼搴忕殑鍦嗗舰鏍峰紡
+          ::v-deep .uni-checkbox-input,
+          ::v-deep .wx-checkbox-input {
+            border-radius: 50% !important;
+          }
+          
+          // 閽堝H5鐨勫渾褰㈡牱寮�
+          ::v-deep input[type="checkbox"] {
+            border-radius: 50% !important;
+            -webkit-appearance: none;
+            appearance: none;
+            width: 36rpx;
+            height: 36rpx;
+            border: 2rpx solid #d1d1d1;
+            background-color: #fff;
+            position: relative;
+            
+            &:checked {
+              background-color: #007AFF;
+              border-color: #007AFF;
+              
+              &::after {
+                content: '';
+                position: absolute;
+                top: 50%;
+                left: 50%;
+                transform: translate(-50%, -50%);
+                width: 12rpx;
+                height: 12rpx;
+                background-color: #fff;
+                border-radius: 50%;
+              }
+            }
+          }
+          
+          .agreement-text {
+            display: inline-flex;
+            align-items: center;
+            flex-wrap: wrap;
+            line-height: 1.5;
+            font-size: 26rpx;
+            text-align: left;
+            justify-content: flex-start;
+            
+            .text-grey1 {
+              color: #666;
+              font-size: 26rpx;
+              line-height: 1.5;
+            }
+            
+            .text-blue {
+              color: #007AFF;
+              font-size: 26rpx;
+              padding: 8rpx 10rpx;
+              margin: 0 5rpx;
+              display: inline-block;
+              position: relative;
+              z-index: 10;
+              line-height: 1.5;
+            }
+          }
         }
       }
     }
   }
-
-</style>
+</style>
\ No newline at end of file

--
Gitblit v1.9.1