Преглед на файлове

✨ feat(auth-ui): 新增微信登录组件并重构项目结构

- 在 mini-enterprise-auth-ui 包中新增 WechatLogin 组件及其配置文件
- 实现完整的微信小程序登录流程,包含环境检测、用户授权、后端接口调用和错误处理
- 在 mini 项目中创建桥接文件,从 auth-ui 包导入微信登录组件
- 重构项目结构,将业务逻辑集中到 UI 包中,提高代码复用性
yourname преди 4 седмици
родител
ревизия
67ff57408d

+ 2 - 0
mini-ui-packages/mini-enterprise-auth-ui/src/index.ts

@@ -2,5 +2,7 @@ export * from './hooks'
 export * from './api'
 export { default as Login } from './pages/login/Login'
 export { default as LoginConfig } from './pages/login/Login.config'
+export { default as WechatLogin } from './pages/login/WechatLogin'
+export { default as WechatLoginConfig } from './pages/login/WechatLogin.config'
 export { default as Profile } from './pages/profile/Profile'
 export { default as ProfileConfig } from './pages/profile/Profile.config'

+ 5 - 0
mini-ui-packages/mini-enterprise-auth-ui/src/pages/login/WechatLogin.config.ts

@@ -0,0 +1,5 @@
+export default definePageConfig({
+  navigationBarTitleText: '微信登录',
+  navigationBarBackgroundColor: '#1890ff',
+  navigationBarTextStyle: 'white'
+})

+ 240 - 0
mini-ui-packages/mini-enterprise-auth-ui/src/pages/login/WechatLogin.tsx

@@ -0,0 +1,240 @@
+import { View, Text } from '@tarojs/components'
+import { useState, useEffect } from 'react'
+import Taro from '@tarojs/taro'
+import { cn } from '@d8d/mini-shared-ui-components/utils/cn'
+import Navbar from '@d8d/mini-shared-ui-components/navbar'
+import { isWeapp } from '@d8d/mini-shared-ui-components/utils/platform'
+import { Button } from '@d8d/mini-shared-ui-components/button'
+import { enterpriseAuthClient } from '../../api'
+
+export default function WechatLogin() {
+  const [loading, setLoading] = useState(false)
+  const [isWechatEnv, setIsWechatEnv] = useState(true)
+
+  // 设置导航栏标题并检查平台
+  useEffect(() => {
+    Taro.setNavigationBarTitle({
+      title: '微信登录'
+    })
+
+    // 检查是否为微信小程序环境
+    const wechatEnv = isWeapp()
+    setIsWechatEnv(wechatEnv)
+
+    // 如果不是微信小程序,显示提示并延迟跳转
+    if (!wechatEnv) {
+      Taro.showModal({
+        title: '提示',
+        content: '微信登录功能仅支持在微信小程序中使用',
+        showCancel: false,
+        confirmText: '返回',
+        success: () => {
+          setTimeout(() => {
+            Taro.navigateBack()
+          }, 500)
+        }
+      })
+    }
+  }, [])
+
+  const handleWechatLogin = async () => {
+    setLoading(true)
+
+    try {
+      Taro.showLoading({
+        title: '登录中...',
+        mask: true
+      })
+
+      // 1. 获取用户信息授权
+      const userProfile = await Taro.getUserProfile({
+        desc: '用于完善用户资料'
+      }).catch(err => {
+        if (err.errMsg.includes('deny') || err.errMsg.includes('cancel')) {
+          throw new Error('用户拒绝授权')
+        }
+        throw err
+      })
+
+      // 2. 获取登录code
+      const loginRes = await Taro.login()
+
+      if (!loginRes.code) {
+        throw new Error('获取登录凭证失败')
+      }
+
+      // 3. 使用RPC client调用后端小程序登录API
+      const response = await enterpriseAuthClient['mini-login'].$post({
+        json: {
+          code: loginRes.code,
+          userInfo: userProfile.userInfo
+        }
+      })
+
+      Taro.hideLoading()
+
+      if (response.status === 200) {
+        const { token, user, isNewUser } = await response.json()
+
+        // 4. 保存token和用户信息
+        Taro.setStorageSync('enterpriseUserInfo', user)
+        Taro.setStorageSync('enterprise_token', token) // 企业用户token存储
+
+        Taro.showToast({
+          title: isNewUser ? '注册成功' : '登录成功',
+          icon: 'success',
+          duration: 1500
+        })
+
+        // 跳转到首页
+        setTimeout(() => {
+          Taro.switchTab({ url: '/pages/yongren/dashboard/index' })
+        }, 1500)
+      } else {
+        const errorData = await response.json()
+        throw new Error(errorData.message || '登录失败')
+      }
+    } catch (error: any) {
+      Taro.hideLoading()
+
+      const errorMessage = error.message || '登录失败'
+
+      if (errorMessage.includes('用户拒绝授权')) {
+        Taro.showModal({
+          title: '提示',
+          content: '需要授权才能使用小程序的全部功能',
+          showCancel: false,
+          confirmText: '知道了'
+        })
+      } else if (errorMessage.includes('网络') || errorMessage.includes('Network')) {
+        Taro.showModal({
+          title: '网络错误',
+          content: '请检查网络连接后重试',
+          showCancel: false,
+          confirmText: '确定'
+        })
+      } else {
+        Taro.showToast({
+          title: errorMessage,
+          icon: 'none',
+          duration: 3000
+        })
+      }
+    } finally {
+      setLoading(false)
+    }
+  }
+
+  const goToAccountLogin = () => {
+    Taro.navigateBack()
+  }
+
+  return (
+    <View className="min-h-screen bg-gradient-to-br from-green-50 via-white to-blue-50">
+      <Navbar
+        title="微信登录"
+        backgroundColor="bg-transparent"
+        textColor="text-gray-900"
+        border={false}
+      />
+
+      {!isWechatEnv ? (
+        <View className="flex-1 flex items-center justify-center px-6">
+          <View className="flex flex-col items-center">
+            <View className="i-heroicons-exclamation-triangle-20-solid w-16 h-16 text-orange-500 mx-auto mb-4" />
+            <Text className="text-lg font-semibold text-gray-900 mb-2">当前环境不支持</Text>
+            <Text className="text-sm text-gray-600 mb-6">
+              微信登录功能仅支持在微信小程序中使用
+            </Text>
+            <Button
+              className="w-full max-w-xs"
+              size="lg"
+              variant="default"
+              onClick={goToAccountLogin}
+            >
+              <View className="i-heroicons-arrow-left-20-solid w-4 h-4 mr-2" />
+              返回账号登录
+            </Button>
+          </View>
+        </View>
+      ) : (
+        <View className="flex-1 px-6 py-12">
+        {/* Logo区域 */}
+        <View className="flex flex-col items-center mb-10">
+          <View className="w-20 h-20 mb-4 rounded-full bg-green-100 flex items-center justify-center">
+            <View className="i-heroicons-chat-bubble-left-right-20-solid w-12 h-12 text-green-500" />
+          </View>
+          <Text className="text-2xl font-bold text-gray-900 mb-2">微信一键登录</Text>
+          <Text className="text-gray-600 text-sm">便捷登录,无需输入账号密码</Text>
+        </View>
+
+        {/* 功能介绍 */}
+        <View className="bg-white rounded-2xl shadow-sm p-6 mb-8">
+          <Text className="text-lg font-semibold text-gray-900 mb-4">登录后您将享受</Text>
+
+          <View className="space-y-3">
+            <View className="flex items-center">
+              <View className="w-2 h-2 bg-green-500 rounded-full mr-3" />
+              <Text className="text-sm text-gray-700">数据云端同步</Text>
+            </View>
+            <View className="flex items-center">
+              <View className="w-2 h-2 bg-green-500 rounded-full mr-3" />
+              <Text className="text-sm text-gray-700">个性化推荐</Text>
+            </View>
+            <View className="flex items-center">
+              <View className="w-2 h-2 bg-green-500 rounded-full mr-3" />
+              <Text className="text-sm text-gray-700">多端数据共享</Text>
+            </View>
+            <View className="flex items-center">
+              <View className="w-2 h-2 bg-green-500 rounded-full mr-3" />
+              <Text className="text-sm text-gray-700">专属会员权益</Text>
+            </View>
+          </View>
+        </View>
+
+        {/* 微信登录按钮 */}
+        <View className="space-y-4">
+          <Button
+            className={cn(
+              "w-full",
+              "bg-green-500 text-white hover:bg-green-600",
+              "border-none"
+            )}
+            size="lg"
+            variant="default"
+            onClick={handleWechatLogin}
+            disabled={loading || !isWechatEnv}
+            loading={loading}
+          >
+            <View className="i-heroicons-chat-bubble-left-right-20-solid w-5 h-5 mr-2" />
+            {loading ? '登录中...' : '微信一键登录'}
+          </Button>
+
+          <Button
+            className="w-full"
+            size="lg"
+            variant="outline"
+            onClick={goToAccountLogin}
+          >
+            <View className="i-heroicons-arrow-left-20-solid w-4 h-4 mr-2" />
+            使用账号密码登录
+          </Button>
+        </View>
+
+        {/* 隐私声明 */}
+        <View className="mt-8 text-center">
+          <Text className="text-xs text-gray-500 leading-relaxed">
+            点击"微信一键登录"即表示您同意
+            <Text className="text-blue-500">《用户协议》</Text>
+            和
+            <Text className="text-blue-500">《隐私政策》</Text>
+          </Text>
+          <Text className="text-xs text-gray-400 mt-2">
+            我们将严格保护您的个人信息安全
+          </Text>
+        </View>
+      </View>
+      )}
+    </View>
+  )
+}

+ 2 - 0
mini/src/pages/login/wechat-login.config.ts

@@ -0,0 +1,2 @@
+// 桥接配置文件:从 @d8d/mini-enterprise-auth-ui 包导入WechatLogin配置
+export { WechatLoginConfig as default } from '@d8d/mini-enterprise-auth-ui'

+ 2 - 240
mini/src/pages/login/wechat-login.tsx

@@ -1,240 +1,2 @@
-import { View, Text } from '@tarojs/components'
-import { useState, useEffect } from 'react'
-import Taro from '@tarojs/taro'
-import { cn } from '@/utils/cn'
-import Navbar from '@/components/ui/navbar'
-import { isWeapp } from '@/utils/platform'
-import { Button } from '@/components/ui/button'
-import { enterpriseAuthClient } from '@/api'
-
-export default function WechatLogin() {
-  const [loading, setLoading] = useState(false)
-  const [isWechatEnv, setIsWechatEnv] = useState(true)
-
-  // 设置导航栏标题并检查平台
-  useEffect(() => {
-    Taro.setNavigationBarTitle({
-      title: '微信登录'
-    })
-    
-    // 检查是否为微信小程序环境
-    const wechatEnv = isWeapp()
-    setIsWechatEnv(wechatEnv)
-    
-    // 如果不是微信小程序,显示提示并延迟跳转
-    if (!wechatEnv) {
-      Taro.showModal({
-        title: '提示',
-        content: '微信登录功能仅支持在微信小程序中使用',
-        showCancel: false,
-        confirmText: '返回',
-        success: () => {
-          setTimeout(() => {
-            Taro.navigateBack()
-          }, 500)
-        }
-      })
-    }
-  }, [])
-
-  const handleWechatLogin = async () => {
-    setLoading(true)
-    
-    try {
-      Taro.showLoading({
-        title: '登录中...',
-        mask: true
-      })
-
-      // 1. 获取用户信息授权
-      const userProfile = await Taro.getUserProfile({
-        desc: '用于完善用户资料'
-      }).catch(err => {
-        if (err.errMsg.includes('deny') || err.errMsg.includes('cancel')) {
-          throw new Error('用户拒绝授权')
-        }
-        throw err
-      })
-
-      // 2. 获取登录code
-      const loginRes = await Taro.login()
-      
-      if (!loginRes.code) {
-        throw new Error('获取登录凭证失败')
-      }
-
-      // 3. 使用RPC client调用后端小程序登录API
-      const response = await enterpriseAuthClient['mini-login'].$post({
-        json: {
-          code: loginRes.code,
-          userInfo: userProfile.userInfo
-        }
-      })
-
-      Taro.hideLoading()
-
-      if (response.status === 200) {
-        const { token, user, isNewUser } = await response.json()
-        
-        // 4. 保存token和用户信息
-        Taro.setStorageSync('enterpriseUserInfo', user)
-        Taro.setStorageSync('enterprise_token', token) // 企业用户token存储
-        
-        Taro.showToast({
-          title: isNewUser ? '注册成功' : '登录成功',
-          icon: 'success',
-          duration: 1500
-        })
-        
-        // 跳转到首页
-        setTimeout(() => {
-          Taro.switchTab({ url: '/pages/yongren/dashboard/index' })
-        }, 1500)
-      } else {
-        const errorData = await response.json()
-        throw new Error(errorData.message || '登录失败')
-      }
-    } catch (error: any) {
-      Taro.hideLoading()
-      
-      const errorMessage = error.message || '登录失败'
-      
-      if (errorMessage.includes('用户拒绝授权')) {
-        Taro.showModal({
-          title: '提示',
-          content: '需要授权才能使用小程序的全部功能',
-          showCancel: false,
-          confirmText: '知道了'
-        })
-      } else if (errorMessage.includes('网络') || errorMessage.includes('Network')) {
-        Taro.showModal({
-          title: '网络错误',
-          content: '请检查网络连接后重试',
-          showCancel: false,
-          confirmText: '确定'
-        })
-      } else {
-        Taro.showToast({
-          title: errorMessage,
-          icon: 'none',
-          duration: 3000
-        })
-      }
-    } finally {
-      setLoading(false)
-    }
-  }
-
-  const goToAccountLogin = () => {
-    Taro.navigateBack()
-  }
-
-  return (
-    <View className="min-h-screen bg-gradient-to-br from-green-50 via-white to-blue-50">
-      <Navbar
-        title="微信登录"
-        backgroundColor="bg-transparent"
-        textColor="text-gray-900"
-        border={false}
-      />
-      
-      {!isWechatEnv ? (
-        <View className="flex-1 flex items-center justify-center px-6">
-          <View className="flex flex-col items-center">
-            <View className="i-heroicons-exclamation-triangle-20-solid w-16 h-16 text-orange-500 mx-auto mb-4" />
-            <Text className="text-lg font-semibold text-gray-900 mb-2">当前环境不支持</Text>
-            <Text className="text-sm text-gray-600 mb-6">
-              微信登录功能仅支持在微信小程序中使用
-            </Text>
-            <Button
-              className="w-full max-w-xs"
-              size="lg"
-              variant="default"
-              onClick={goToAccountLogin}
-            >
-              <View className="i-heroicons-arrow-left-20-solid w-4 h-4 mr-2" />
-              返回账号登录
-            </Button>
-          </View>
-        </View>
-      ) : (
-        <View className="flex-1 px-6 py-12">
-        {/* Logo区域 */}
-        <View className="flex flex-col items-center mb-10">
-          <View className="w-20 h-20 mb-4 rounded-full bg-green-100 flex items-center justify-center">
-            <View className="i-heroicons-chat-bubble-left-right-20-solid w-12 h-12 text-green-500" />
-          </View>
-          <Text className="text-2xl font-bold text-gray-900 mb-2">微信一键登录</Text>
-          <Text className="text-gray-600 text-sm">便捷登录,无需输入账号密码</Text>
-        </View>
-
-        {/* 功能介绍 */}
-        <View className="bg-white rounded-2xl shadow-sm p-6 mb-8">
-          <Text className="text-lg font-semibold text-gray-900 mb-4">登录后您将享受</Text>
-          
-          <View className="space-y-3">
-            <View className="flex items-center">
-              <View className="w-2 h-2 bg-green-500 rounded-full mr-3" />
-              <Text className="text-sm text-gray-700">数据云端同步</Text>
-            </View>
-            <View className="flex items-center">
-              <View className="w-2 h-2 bg-green-500 rounded-full mr-3" />
-              <Text className="text-sm text-gray-700">个性化推荐</Text>
-            </View>
-            <View className="flex items-center">
-              <View className="w-2 h-2 bg-green-500 rounded-full mr-3" />
-              <Text className="text-sm text-gray-700">多端数据共享</Text>
-            </View>
-            <View className="flex items-center">
-              <View className="w-2 h-2 bg-green-500 rounded-full mr-3" />
-              <Text className="text-sm text-gray-700">专属会员权益</Text>
-            </View>
-          </View>
-        </View>
-
-        {/* 微信登录按钮 */}
-        <View className="space-y-4">
-          <Button
-            className={cn(
-              "w-full",
-              "bg-green-500 text-white hover:bg-green-600",
-              "border-none"
-            )}
-            size="lg"
-            variant="default"
-            onClick={handleWechatLogin}
-            disabled={loading || !isWechatEnv}
-            loading={loading}
-          >
-            <View className="i-heroicons-chat-bubble-left-right-20-solid w-5 h-5 mr-2" />
-            {loading ? '登录中...' : '微信一键登录'}
-          </Button>
-
-          <Button
-            className="w-full"
-            size="lg"
-            variant="outline"
-            onClick={goToAccountLogin}
-          >
-            <View className="i-heroicons-arrow-left-20-solid w-4 h-4 mr-2" />
-            使用账号密码登录
-          </Button>
-        </View>
-
-        {/* 隐私声明 */}
-        <View className="mt-8 text-center">
-          <Text className="text-xs text-gray-500 leading-relaxed">
-            点击"微信一键登录"即表示您同意
-            <Text className="text-blue-500">《用户协议》</Text>
-            和
-            <Text className="text-blue-500">《隐私政策》</Text>
-          </Text>
-          <Text className="text-xs text-gray-400 mt-2">
-            我们将严格保护您的个人信息安全
-          </Text>
-        </View>
-      </View>
-      )}
-    </View>
-  )
-}
+// 桥接文件:从 @d8d/mini-enterprise-auth-ui 包导入WechatLogin页面
+export { WechatLogin as default } from '@d8d/mini-enterprise-auth-ui'