Files
tiantian-system/app/api/passport/qrLogin/index.ts
2026-04-08 17:10:58 +08:00

213 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import request from '@/utils/request';
import type { ApiResult } from '@/api';
import { SERVER_API_URL } from '@/config/setting';
function isSuccess(code?: number) {
return code === 0 || code === 200;
}
/**
* 二维码生成响应数据
* 后端只返回二维码内容前端负责生成base64二维码图片
*/
export interface QrCodeResponse {
token: string; // 二维码唯一标识token
qrCodeContent: string; // 二维码内容前端用此生成base64 QRCode
expiresIn: number; // 过期时间(秒)
wechatScanUrl?: string; // 微信扫码登录H5页面URL备用
miniprogramPath?: string; // 微信小程序页面路径
miniprogramQrCodeUrl?: string; // 小程序码图片URL已废弃
miniprogramQrCode?: string; // 小程序码Base64图片扫码后直接打开小程序优先使用
}
/**
* 二维码状态响应
*/
export interface QrCodeStatusResponse {
status: 'pending' | 'scanned' | 'bind_phone' | 'confirmed' | 'expired';
accessToken?: string; // 登录成功时返回的JWT token
access_token?: string; // 兼容后端下划线命名
userInfo?: any; // 用户信息
expiresIn?: number; // 剩余过期时间(秒)
tenantId?: string | number; // 租户ID
message?: string;
needBindPhone?: boolean;
}
/**
* 确认登录请求参数
*/
export interface QrLoginConfirmRequest {
token: string; // 二维码token
userId?: number; // 用户ID
platform?: string; // 登录平台
}
/**
* 生成登录二维码
*/
export async function generateQrCode(): Promise<QrCodeResponse> {
const res = await request.post<ApiResult<QrCodeResponse>>(
SERVER_API_URL + '/qr-login/generate',
{}
);
if (isSuccess(res.data.code) && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message || '生成二维码失败'));
}
/**
* 检查二维码状态
*/
export async function checkQrCodeStatus(token: string): Promise<QrCodeStatusResponse> {
const res = await request.get<ApiResult<QrCodeStatusResponse>>(
SERVER_API_URL + `/qr-login/status/${token}`
);
if (isSuccess(res.data.code) && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message || '检查二维码状态失败'));
}
/**
* 扫码确认登录(移动端调用)
*/
export async function confirmQrLogin(requestData: QrLoginConfirmRequest): Promise<QrCodeStatusResponse> {
const res = await request.post<ApiResult<QrCodeStatusResponse>>(
SERVER_API_URL + '/qr-login/confirm',
requestData
);
if (isSuccess(res.data.code) && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message || '确认登录失败'));
}
/**
* 扫码标记(移动端扫码时调用)
*/
export async function scanQrCode(token: string): Promise<boolean> {
const res = await request.post<ApiResult<boolean>>(
SERVER_API_URL + `/qr-login/scan/${token}`
);
if (isSuccess(res.data.code)) {
return res.data.data || true;
}
return Promise.reject(new Error(res.data.message || '扫码失败'));
}
/**
* 微信小程序扫码登录确认
*/
export async function wechatMiniProgramConfirm(requestData: QrLoginConfirmRequest): Promise<QrCodeStatusResponse> {
const res = await request.post<ApiResult<QrCodeStatusResponse>>(
SERVER_API_URL + '/qr-login/wechat-confirm',
requestData
);
if (isSuccess(res.data.code) && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message || '微信小程序登录确认失败'));
}
// ============ 微信扫码登录 H5 相关 ============
/**
* 微信扫码登录响应(用于 H5 页面)
*/
export interface WechatScanResponse {
status: 'success' | 'confirmed' | 'bind_required' | 'bind_phone' | 'not_bound';
accessToken?: string;
access_token?: string;
userInfo?: any;
message?: string;
tenantId?: number;
}
/**
* 微信扫码登录请求
*/
export interface WechatScanRequest {
token: string;
code?: string;
unionId?: string;
openId?: string;
}
/**
* 微信扫码登录确认H5 页面调用)
*/
export async function wechatScanConfirm(requestData: WechatScanRequest): Promise<WechatScanResponse> {
const res = await request.post<ApiResult<WechatScanResponse>>(
SERVER_API_URL + '/qr-login/wechat-scan',
requestData
);
if (isSuccess(res.data.code) && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message || '微信扫码登录失败'));
}
/**
* 获取微信网页授权 URL
*/
export async function getWechatOAuthUrl(token: string): Promise<string> {
const res = await request.get<ApiResult<string>>(
SERVER_API_URL + '/qr-login/wechat-oauth-url',
{ params: { token } }
);
if (isSuccess(res.data.code) && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message || '获取授权链接失败'));
}
/**
* 获取微信带参数二维码图片URL用于扫码关注登录
*/
export async function getWechatQrCodeUrl(token: string): Promise<string> {
const res = await request.get<ApiResult<string>>(
SERVER_API_URL + `/qr-login/wechat-qrcode/${token}`
);
if (isSuccess(res.data.code) && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message || '获取微信二维码失败'));
}
export interface QrLoginBindPhoneRequest {
token: string;
phone: string;
code: string;
}
export async function bindQrLoginPhone(requestData: QrLoginBindPhoneRequest): Promise<QrCodeStatusResponse> {
const res = await request.post<ApiResult<QrCodeStatusResponse>>(
SERVER_API_URL + '/qr-login/bind-phone',
requestData
);
if (isSuccess(res.data.code) && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message || '绑定手机号失败'));
}