# SNS Login SDK

统一身份登录 SDK - 基于自定义协议调用桌面应用程序进行身份认证

## 功能特性

- 🔐 统一身份认证
- 🖥️ 桌面应用程序集成
- 📱 自定义协议支持
- ⏱️ 智能轮询机制
- 🔄 自动重试机制
- 💪 TypeScript 支持

## 安装

```bash
npm install sns-login-sdk
```

或者使用 yarn:

```bash
yarn add sns-login-sdk
```

## 使用方法

### 基础用法

```javascript
import SnsLoginSDK, { createSnsLogin } from 'sns-login-sdk';

// 方式1: 直接使用类
const snsLogin = new SnsLoginSDK({
  options: {
    baseUrl: 'http://your-api-server.com',
    type: 1, // 1-区域，2-业务
  },
  callbacks: {
    onLoading: (loading) => {
      console.log('Loading状态:', loading);
    },
    onSuccess: (token) => {
      console.log('登录成功，Token:', token);
      // 处理登录成功逻辑
    },
    onError: (error) => {
      console.error('登录失败:', error);
    },
    onMessage: (message, type) => {
      console.log(`消息[${type}]:`, message);
    },
  },
});

// 开始登录
snsLogin.login();
```

```javascript
// 方式2: 使用工厂函数
const snsLogin = createSnsLogin({
  options: {
    baseURL: 'http://your-api-server.com',
  },
  callbacks: {
    onSuccess: (token) => {
      console.log('登录成功:', token);
    },
  },
});

snsLogin.login();
```

### Vue.js 集成示例

```vue
<template>
  <div>
    <button @click="handleLogin" :disabled="loading">
      {{ loading ? '登录中...' : '统一身份登录' }}
    </button>
    <div v-if="message">{{ message }}</div>
  </div>
</template>

<script>
import { createSnsLogin } from 'sns-login-sdk';

export default {
  data() {
    return {
      loading: false,
      message: '',
      snsLogin: null,
    };
  },
  created() {
    this.snsLogin = createSnsLogin({
      options: {
        baseURL: process.env.VUE_APP_API_BASE_URL,
      },
      callbacks: {
        onLoading: (loading) => {
          this.loading = loading;
        },
        onSuccess: (token) => {
          this.message = '登录成功！';
          // 处理token，如存储到localStorage或发送到后端
          localStorage.setItem('authToken', token);
          this.$router.push('/dashboard');
        },
        onError: (error) => {
          this.message = `登录失败: ${error.message}`;
        },
        onMessage: (message, type) => {
          this.message = message;
        },
      },
    });
  },
  methods: {
    handleLogin() {
      this.snsLogin.login();
    },
  },
  beforeDestroy() {
    // 清理资源
    if (this.snsLogin) {
      this.snsLogin.destroy();
    }
  },
};
</script>
```

### React 集成示例

```jsx
import React, { useState, useEffect, useRef } from 'react';
import { createSnsLogin } from 'sns-login-sdk';

function LoginComponent() {
  const [loading, setLoading] = useState(false);
  const [message, setMessage] = useState('');
  const snsLoginRef = useRef(null);

  useEffect(() => {
    snsLoginRef.current = createSnsLogin({
      options: {
        baseURL: process.env.REACT_APP_API_BASE_URL,
      },
      callbacks: {
        onLoading: setLoading,
        onSuccess: (token) => {
          setMessage('登录成功！');
          localStorage.setItem('authToken', token);
          // 跳转到主页或处理登录成功逻辑
        },
        onError: (error) => {
          setMessage(`登录失败: ${error.message}`);
        },
        onMessage: (message) => {
          setMessage(message);
        },
      },
    });

    return () => {
      // 清理资源
      if (snsLoginRef.current) {
        snsLoginRef.current.destroy();
      }
    };
  }, []);

  const handleLogin = () => {
    snsLoginRef.current?.login();
  };

  return (
    <div>
      <button onClick={handleLogin} disabled={loading}>
        {loading ? '登录中...' : '统一身份登录'}
      </button>
      {message && <div>{message}</div>}
    </div>
  );
}

export default LoginComponent;
```

## 配置选项

### SnsLoginOptions

| 参数      | 类型     | 默认值                   | 说明                         |
| --------- | -------- | ------------------------ | ---------------------------- |
| `baseUrl` | `string` | `window.location.origin` | 域名配置（用于桌面应用调用） |
| `type`    | `number` | `1`                      | 类型参数 1-区域，2-业务      |

### SnsLoginCallbacks

| 参数        | 类型                                       | 说明                         |
| ----------- | ------------------------------------------ | ---------------------------- |
| `onLoading` | `(loading: boolean) => void`               | 加载状态变化回调             |
| `onSuccess` | `(token: string) => void`                  | 登录成功回调，返回认证 token |
| `onError`   | `(error: Error) => void`                   | 错误回调                     |
| `onMessage` | `(message: string, type?: string) => void` | 消息回调                     |

## API 方法

### `login()`

开始统一身份登录流程。

```javascript
await snsLogin.login();
```

### `stopPolling()`

停止轮询过程。

```javascript
snsLogin.stopPolling();
```

### `destroy()`

销毁 SDK 实例，清理所有资源。

```javascript
snsLogin.destroy();
```

## 工作流程

1. 调用 `login()` 方法开始登录流程
2. 生成唯一的 UUID 作为会话标识
3. 通过自定义协议 `tdid://` 调用本地桌面应用程序
4. 开始轮询服务器获取认证结果
5. 根据服务器响应处理不同的状态：
   - 成功：调用 `onSuccess` 回调并返回 token
   - 拒绝：调用 `onMessage` 回调提示用户
   - 超时：停止轮询并提示超时
   - 错误：继续轮询直到成功或超时

## 注意事项

1. 此 SDK 依赖于桌面应用程序，需要确保目标设备已安装相应的桌面客户端
2. 自定义协议 `tdid://` 需要在桌面应用程序中正确注册
3. 轮询机制会持续请求服务器，请合理设置轮询间隔以避免给服务器造成过大压力
4. 建议在组件销毁时调用 `destroy()` 方法以清理资源

## 浏览器兼容性

- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+

## 许可证

MIT License

## 贡献

欢迎提交 Issue 和 Pull Request 来改进这个项目。
