310 lines
9.3 KiB
C#
310 lines
9.3 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using Kill.Managers;
|
||
using Kill.UI.Components;
|
||
using Kill.UI;
|
||
|
||
namespace Kill.Network
|
||
{
|
||
/// <summary>
|
||
/// 服务器响应状态码
|
||
/// </summary>
|
||
public enum ResponseCode
|
||
{
|
||
SUCCESS = 200, // 正常
|
||
NOT_FOUND = 404, // 访问对象不存在
|
||
FORBIDDEN = 403, // 禁止访问
|
||
INTERNAL_ERROR = 502, // 内部处理错误
|
||
RECORD_EXISTS = 610, // 访问对象已存在
|
||
UNAUTHORIZED = 601, // 访问未授权(Token失效)
|
||
ERROR_PASSWORD = 602, // 密码错误
|
||
INVALID_PARAM = 603, // 参数错误
|
||
INVALID_STATUS = 608, // 数据状态致操作无效
|
||
INVALID_FORMAT = 607, // 格式错误
|
||
}
|
||
|
||
/// <summary>
|
||
/// 响应码处理工具
|
||
/// </summary>
|
||
public static class ResponseCodeHandler
|
||
{
|
||
/// <summary>
|
||
/// 状态码与提示信息的映射
|
||
/// </summary>
|
||
private static readonly Dictionary<int, string> CodeMessages = new Dictionary<int, string>
|
||
{
|
||
{ 200, "操作成功" },
|
||
{ 404, "访问对象不存在" },
|
||
{ 403, "禁止访问" },
|
||
{ 502, "服务器内部错误" },
|
||
{ 610, "访问对象已存在" },
|
||
{ 601, "登录已过期,请重新登录" },
|
||
{ 602, "密码错误" },
|
||
{ 603, "参数错误" },
|
||
{ 608, "数据状态导致操作无效" },
|
||
{ 607, "格式错误" },
|
||
};
|
||
|
||
/// <summary>
|
||
/// 检查是否需要全局处理(只处理601 Token失效)
|
||
/// </summary>
|
||
/// <param name="code">状态码</param>
|
||
/// <returns>是否已全局处理</returns>
|
||
public static bool CheckGlobalHandle(int code)
|
||
{
|
||
// 只处理 601 Token失效
|
||
if (code == 601)
|
||
{
|
||
HandleUnauthorized();
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理响应码(只全局处理601,其他返回给调用方)
|
||
/// </summary>
|
||
/// <param name="code">状态码</param>
|
||
/// <param name="message">服务器返回的消息(可选)</param>
|
||
/// <returns>是否成功(code == 200)</returns>
|
||
public static bool Handle(int code, string message = null)
|
||
{
|
||
// 成功
|
||
if (code == 200)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
// 全局处理 601
|
||
if (CheckGlobalHandle(code))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// 其他错误码由调用方处理,这里只返回失败状态
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否需要全局处理(601 Token失效、网络错误等)
|
||
/// </summary>
|
||
/// <param name="response">HTTP响应</param>
|
||
/// <param name="code">输出状态码</param>
|
||
/// <param name="message">输出消息</param>
|
||
/// <returns>是否已全局处理</returns>
|
||
public static bool CheckGlobalHandle<T>(HttpResponse<T> response, out int code, out string message)
|
||
{
|
||
code = -1;
|
||
message = null;
|
||
|
||
// 空响应(网络异常)
|
||
if (response == null)
|
||
{
|
||
ShowErrorTip("100036");
|
||
return true;
|
||
}
|
||
|
||
// HTTP错误(网络层错误)
|
||
if (!response.IsSuccess)
|
||
{
|
||
ShowErrorTip("100036");
|
||
return true;
|
||
}
|
||
|
||
// 获取业务状态码
|
||
code = GetCodeFromResponse(response.Data);
|
||
message = GetMessageFromResponse(response.Data);
|
||
|
||
// 处理 601 Token失效
|
||
if (code == 601)
|
||
{
|
||
HandleUnauthorized();
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理响应结果(全局处理网络错误和601,其他返回给调用方)
|
||
/// </summary>
|
||
/// <typeparam name="T">响应数据类型</typeparam>
|
||
/// <param name="response">HTTP响应</param>
|
||
/// <param name="onSuccess">成功回调(code=200)</param>
|
||
/// <param name="onError">其他错误回调(可选,不传则自动提示)</param>
|
||
public static void HandleResponse<T>(HttpResponse<T> response, Action<T> onSuccess, Action<int, string> onError = null)
|
||
{
|
||
// 全局处理(网络错误、601等)
|
||
int code;
|
||
string message;
|
||
if (CheckGlobalHandle(response, out code, out message))
|
||
{
|
||
return; // 已被全局处理
|
||
}
|
||
|
||
// 成功
|
||
if (code == 200)
|
||
{
|
||
onSuccess?.Invoke(response.Data);
|
||
return;
|
||
}
|
||
|
||
// 有自定义错误处理
|
||
if (onError != null)
|
||
{
|
||
onError.Invoke(code, message);
|
||
}
|
||
else
|
||
{
|
||
// 自动显示错误提示
|
||
ShowErrorTip(code.ToString());
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理响应结果(简化版,只返回是否成功,错误自动提示)
|
||
/// </summary>
|
||
public static bool HandleSimple<T>(HttpResponse<T> response, Action<T> onSuccess) where T : class
|
||
{
|
||
HandleResponse(response, onSuccess, null);
|
||
// 返回是否成功(用于链式判断)
|
||
if (response?.Data == null) return false;
|
||
var code = GetCodeFromResponse(response.Data);
|
||
return code == 200;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取状态码对应的消息
|
||
/// </summary>
|
||
public static string GetMessage(int code, string serverMessage = null)
|
||
{
|
||
// 优先使用服务器返回的消息
|
||
if (!string.IsNullOrEmpty(serverMessage))
|
||
{
|
||
return serverMessage;
|
||
}
|
||
|
||
// 使用本地映射
|
||
if (CodeMessages.TryGetValue(code, out string message))
|
||
{
|
||
return message;
|
||
}
|
||
|
||
// 未知错误码
|
||
return $"未知错误({code})";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理未授权(Token失效)
|
||
/// </summary>
|
||
private static void HandleUnauthorized()
|
||
{
|
||
Debug.LogWarning("Token失效,需要重新登录");
|
||
|
||
// 清除本地登录状态
|
||
ClearAuthData();
|
||
|
||
// 显示提示
|
||
ShowErrorTip("100038");
|
||
JumpToLoginPage();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除登录数据
|
||
/// </summary>
|
||
private static void ClearAuthData()
|
||
{
|
||
// 使用 LocalDataManager 清除数据
|
||
// LocalDataManager.ClearLoginData();
|
||
|
||
// 清除全局请求头
|
||
if (NetworkCtrl.Instance != null)
|
||
{
|
||
NetworkCtrl.Instance.RemoveGlobalHeader("Authorization");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 跳转到登录页
|
||
/// </summary>
|
||
private static void JumpToLoginPage()
|
||
{
|
||
|
||
UIManager.Instance.OpenPage(UIManager.PageName.loginPage,null,false);
|
||
|
||
Debug.Log("跳转到登录页");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示错误提示(使用ToastUI)
|
||
/// </summary>
|
||
private static void ShowErrorTip(string code)
|
||
{
|
||
// 使用 ToastUI 显示横幅提示
|
||
ToastUI.Show(code);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从响应数据中获取code字段
|
||
/// </summary>
|
||
private static int GetCodeFromResponse<T>(T data)
|
||
{
|
||
if (data == null) return -1;
|
||
|
||
// 使用反射获取code字段
|
||
var type = data.GetType();
|
||
var codeField = type.GetField("code");
|
||
if (codeField != null)
|
||
{
|
||
var value = codeField.GetValue(data);
|
||
if (value is int code)
|
||
{
|
||
return code;
|
||
}
|
||
}
|
||
|
||
// 尝试获取属性
|
||
var codeProperty = type.GetProperty("code");
|
||
if (codeProperty != null)
|
||
{
|
||
var value = codeProperty.GetValue(data);
|
||
if (value is int code)
|
||
{
|
||
return code;
|
||
}
|
||
}
|
||
|
||
return 200; // 默认成功
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从响应数据中获取message字段
|
||
/// </summary>
|
||
private static string GetMessageFromResponse<T>(T data)
|
||
{
|
||
if (data == null) return null;
|
||
|
||
var type = data.GetType();
|
||
|
||
// 尝试获取message字段
|
||
var messageField = type.GetField("message");
|
||
if (messageField != null)
|
||
{
|
||
return messageField.GetValue(data)?.ToString();
|
||
}
|
||
|
||
// 尝试获取属性
|
||
var messageProperty = type.GetProperty("message");
|
||
if (messageProperty != null)
|
||
{
|
||
return messageProperty.GetValue(data)?.ToString();
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
|
||
|
||
}
|