新增数据模型和网络层
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
package com.miraclegarden.smsmessage.model;
|
||||
|
||||
/**
|
||||
* **********************
|
||||
*
|
||||
* @Author MiracleGarden
|
||||
* 创建时间: 2026/4/5
|
||||
* API错误响应
|
||||
* **********************
|
||||
*/
|
||||
public class ApiError {
|
||||
private int statusCode;
|
||||
private String error;
|
||||
private String message;
|
||||
|
||||
public ApiError(int statusCode, String error, String message) {
|
||||
this.statusCode = statusCode;
|
||||
this.error = error;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public void setStatusCode(int statusCode) {
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否因token失效导致的错误
|
||||
*/
|
||||
public boolean isTokenExpired() {
|
||||
return statusCode == 401 && message != null &&
|
||||
(message.contains("登录已失效") || message.contains("token") || message.contains("Token"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.miraclegarden.smsmessage.model;
|
||||
|
||||
/**
|
||||
* **********************
|
||||
*
|
||||
* @Author MiracleGarden
|
||||
* 创建时间: 2026/4/5
|
||||
* App通知设置响应
|
||||
* **********************
|
||||
*/
|
||||
public class AppNotificationSettings {
|
||||
private boolean appNotificationAutoProcessEnabled;
|
||||
|
||||
public boolean isAppNotificationAutoProcessEnabled() {
|
||||
return appNotificationAutoProcessEnabled;
|
||||
}
|
||||
|
||||
public void setAppNotificationAutoProcessEnabled(boolean enabled) {
|
||||
this.appNotificationAutoProcessEnabled = enabled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.miraclegarden.smsmessage.model;
|
||||
|
||||
/**
|
||||
* **********************
|
||||
*
|
||||
* @Author MiracleGarden
|
||||
* 创建时间: 2026/4/5
|
||||
* 银行账户信息数据模型
|
||||
* **********************
|
||||
*/
|
||||
public class BankInfo {
|
||||
private String id; // 银行ID (bankInfoId)
|
||||
private String bankName; // 银行名称
|
||||
private String account; // 账户
|
||||
private String remark; // 备注
|
||||
private String userId; // 用户ID
|
||||
private String createdAt; // 创建时间
|
||||
private String updatedAt; // 更新时间
|
||||
|
||||
public BankInfo() {
|
||||
}
|
||||
|
||||
public BankInfo(String bankName, String account, String remark) {
|
||||
this.bankName = bankName;
|
||||
this.account = account;
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getBankName() {
|
||||
return bankName;
|
||||
}
|
||||
|
||||
public void setBankName(String bankName) {
|
||||
this.bankName = bankName;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(String createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public String getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(String updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取显示名称:银行名 + 账户
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
if (account != null && !account.isEmpty()) {
|
||||
return bankName + " (" + account + ")";
|
||||
}
|
||||
return bankName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.miraclegarden.smsmessage.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* **********************
|
||||
*
|
||||
* @Author MiracleGarden
|
||||
* 创建时间: 2026/4/5
|
||||
* 银行账户列表响应
|
||||
* **********************
|
||||
*/
|
||||
public class BankListResponse {
|
||||
private List<BankInfo> banks;
|
||||
|
||||
public List<BankInfo> getBanks() {
|
||||
return banks;
|
||||
}
|
||||
|
||||
public void setBanks(List<BankInfo> banks) {
|
||||
this.banks = banks;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.miraclegarden.smsmessage.model;
|
||||
|
||||
/**
|
||||
* **********************
|
||||
*
|
||||
* @Author MiracleGarden
|
||||
* 创建时间: 2026/4/5
|
||||
* 登录响应数据模型
|
||||
* **********************
|
||||
*/
|
||||
public class LoginResponse {
|
||||
private String token; // JWT token
|
||||
private UserInfo user; // 用户信息
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public UserInfo getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(UserInfo user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为首次登录
|
||||
*/
|
||||
public boolean isFirstLogin() {
|
||||
return user != null && user.isFirstLogin();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.miraclegarden.smsmessage.model;
|
||||
|
||||
/**
|
||||
* **********************
|
||||
*
|
||||
* @Author MiracleGarden
|
||||
* 创建时间: 2026/4/5
|
||||
* 通知上传响应
|
||||
* **********************
|
||||
*/
|
||||
public class UploadNotificationResponse {
|
||||
private boolean ok;
|
||||
private int received;
|
||||
private String id;
|
||||
private String processingStatus;
|
||||
private String emailSyncRecordId;
|
||||
private String duplicateOfEmailSyncRecordId;
|
||||
private String errorMessage;
|
||||
|
||||
public boolean isOk() {
|
||||
return ok;
|
||||
}
|
||||
|
||||
public void setOk(boolean ok) {
|
||||
this.ok = ok;
|
||||
}
|
||||
|
||||
public int getReceived() {
|
||||
return received;
|
||||
}
|
||||
|
||||
public void setReceived(int received) {
|
||||
this.received = received;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getProcessingStatus() {
|
||||
return processingStatus;
|
||||
}
|
||||
|
||||
public void setProcessingStatus(String processingStatus) {
|
||||
this.processingStatus = processingStatus;
|
||||
}
|
||||
|
||||
public String getEmailSyncRecordId() {
|
||||
return emailSyncRecordId;
|
||||
}
|
||||
|
||||
public void setEmailSyncRecordId(String emailSyncRecordId) {
|
||||
this.emailSyncRecordId = emailSyncRecordId;
|
||||
}
|
||||
|
||||
public String getDuplicateOfEmailSyncRecordId() {
|
||||
return duplicateOfEmailSyncRecordId;
|
||||
}
|
||||
|
||||
public void setDuplicateOfEmailSyncRecordId(String duplicateOfEmailSyncRecordId) {
|
||||
this.duplicateOfEmailSyncRecordId = duplicateOfEmailSyncRecordId;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.miraclegarden.smsmessage.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserInfo {
|
||||
private String id;
|
||||
private String username;
|
||||
private String role;
|
||||
private boolean isFirstLogin;
|
||||
private List<String> projectAccesses;
|
||||
private String parentUserId;
|
||||
private String googleExcelId;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(String role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public boolean isFirstLogin() {
|
||||
return isFirstLogin;
|
||||
}
|
||||
|
||||
public void setFirstLogin(boolean firstLogin) {
|
||||
isFirstLogin = firstLogin;
|
||||
}
|
||||
|
||||
public List<String> getProjectAccesses() {
|
||||
return projectAccesses;
|
||||
}
|
||||
|
||||
public void setProjectAccesses(List<String> projectAccesses) {
|
||||
this.projectAccesses = projectAccesses;
|
||||
}
|
||||
|
||||
public String getParentUserId() {
|
||||
return parentUserId;
|
||||
}
|
||||
|
||||
public void setParentUserId(String parentUserId) {
|
||||
this.parentUserId = parentUserId;
|
||||
}
|
||||
|
||||
public String getGoogleExcelId() {
|
||||
return googleExcelId;
|
||||
}
|
||||
|
||||
public void setGoogleExcelId(String googleExcelId) {
|
||||
this.googleExcelId = googleExcelId;
|
||||
}
|
||||
|
||||
public boolean hasProjectAccess(String projectType) {
|
||||
if (projectAccesses == null || projectAccesses.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return projectAccesses.contains(projectType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
package com.miraclegarden.smsmessage.network;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.miraclegarden.smsmessage.model.ApiError;
|
||||
import com.miraclegarden.smsmessage.model.AppNotificationSettings;
|
||||
import com.miraclegarden.smsmessage.model.BankInfo;
|
||||
import com.miraclegarden.smsmessage.model.BankListResponse;
|
||||
import com.miraclegarden.smsmessage.model.LoginResponse;
|
||||
import com.miraclegarden.smsmessage.model.UploadNotificationResponse;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* API服务类 - 封装所有网络请求
|
||||
*/
|
||||
public class ApiService {
|
||||
private static final String TAG = "ApiService";
|
||||
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
||||
private static final String BASE_URL = "https://www.judy88.xin";
|
||||
|
||||
private final OkHttpClient httpClient;
|
||||
private final Gson gson;
|
||||
private final TokenManager tokenManager;
|
||||
|
||||
public ApiService(Context context) {
|
||||
this.tokenManager = TokenManager.getInstance(context);
|
||||
this.gson = new Gson();
|
||||
this.httpClient = new OkHttpClient.Builder()
|
||||
.connectTimeout(15, TimeUnit.SECONDS)
|
||||
.writeTimeout(15, TimeUnit.SECONDS)
|
||||
.readTimeout(15, TimeUnit.SECONDS)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录接口
|
||||
*/
|
||||
public void login(String username, String password, ApiCallback<LoginResponse> callback) {
|
||||
try {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("username", username);
|
||||
json.put("password", password);
|
||||
json.put("clientType", "app");
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(BASE_URL + "/api/auth/login")
|
||||
.header("Content-Type", "application/json")
|
||||
.post(RequestBody.create(json.toString(), JSON))
|
||||
.build();
|
||||
|
||||
httpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onError(new ApiError(0, "NETWORK_ERROR", e.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
handleResponse(response, LoginResponse.class, callback);
|
||||
}
|
||||
});
|
||||
} catch (JSONException e) {
|
||||
callback.onError(new ApiError(0, "JSON_ERROR", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
*/
|
||||
public void changePassword(String oldPassword, String newPassword, ApiCallback<Void> callback) {
|
||||
try {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("oldPassword", oldPassword);
|
||||
json.put("newPassword", newPassword);
|
||||
|
||||
Request request = buildAuthRequest("/api/auth/change-password")
|
||||
.post(RequestBody.create(json.toString(), JSON))
|
||||
.build();
|
||||
|
||||
httpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onError(new ApiError(0, "NETWORK_ERROR", e.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
if (response.isSuccessful()) {
|
||||
callback.onSuccess(null);
|
||||
} else {
|
||||
callback.onError(parseError(response));
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (JSONException e) {
|
||||
callback.onError(new ApiError(0, "JSON_ERROR", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取银行账户列表
|
||||
*/
|
||||
public void getBankList(ApiCallback<List<BankInfo>> callback) {
|
||||
Request request = buildAuthRequest("/api/bank-email-parser/banks")
|
||||
.get()
|
||||
.build();
|
||||
|
||||
httpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onError(new ApiError(0, "NETWORK_ERROR", e.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
handleResponse(response, BankListResponse.class, new ApiCallback<BankListResponse>() {
|
||||
@Override
|
||||
public void onSuccess(BankListResponse result) {
|
||||
callback.onSuccess(result.getBanks());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiError error) {
|
||||
callback.onError(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建银行账户
|
||||
*/
|
||||
public void createBank(BankInfo bankInfo, ApiCallback<BankInfo> callback) {
|
||||
try {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("bankName", bankInfo.getBankName());
|
||||
json.put("account", bankInfo.getAccount());
|
||||
if (bankInfo.getRemark() != null) {
|
||||
json.put("remark", bankInfo.getRemark());
|
||||
}
|
||||
|
||||
Request request = buildAuthRequest("/api/bank-email-parser/banks")
|
||||
.post(RequestBody.create(json.toString(), JSON))
|
||||
.build();
|
||||
|
||||
httpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onError(new ApiError(0, "NETWORK_ERROR", e.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
handleResponse(response, BankInfo.class, callback);
|
||||
}
|
||||
});
|
||||
} catch (JSONException e) {
|
||||
callback.onError(new ApiError(0, "JSON_ERROR", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新银行账户
|
||||
*/
|
||||
public void updateBank(String bankId, BankInfo bankInfo, ApiCallback<BankInfo> callback) {
|
||||
try {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("bankName", bankInfo.getBankName());
|
||||
json.put("account", bankInfo.getAccount());
|
||||
if (bankInfo.getRemark() != null) {
|
||||
json.put("remark", bankInfo.getRemark());
|
||||
}
|
||||
|
||||
Request request = buildAuthRequest("/api/bank-email-parser/banks/" + bankId)
|
||||
.patch(RequestBody.create(json.toString(), JSON))
|
||||
.build();
|
||||
|
||||
httpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onError(new ApiError(0, "NETWORK_ERROR", e.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
handleResponse(response, BankInfo.class, callback);
|
||||
}
|
||||
});
|
||||
} catch (JSONException e) {
|
||||
callback.onError(new ApiError(0, "JSON_ERROR", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除银行账户
|
||||
*/
|
||||
public void deleteBank(String bankId, ApiCallback<Void> callback) {
|
||||
Request request = buildAuthRequest("/api/bank-email-parser/banks/" + bankId)
|
||||
.delete()
|
||||
.build();
|
||||
|
||||
httpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onError(new ApiError(0, "NETWORK_ERROR", e.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
if (response.isSuccessful()) {
|
||||
callback.onSuccess(null);
|
||||
} else {
|
||||
callback.onError(parseError(response));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取App通知设置
|
||||
*/
|
||||
public void getAppNotificationSettings(ApiCallback<AppNotificationSettings> callback) {
|
||||
Request request = buildAuthRequest("/api/settings/app-notification")
|
||||
.get()
|
||||
.build();
|
||||
|
||||
httpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onError(new ApiError(0, "NETWORK_ERROR", e.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
handleResponse(response, AppNotificationSettings.class, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新App通知设置
|
||||
*/
|
||||
public void updateAppNotificationSettings(boolean enabled, ApiCallback<Void> callback) {
|
||||
try {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("appNotificationAutoProcessEnabled", enabled);
|
||||
|
||||
Request request = buildAuthRequest("/api/settings/app-notification")
|
||||
.patch(RequestBody.create(json.toString(), JSON))
|
||||
.build();
|
||||
|
||||
httpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onError(new ApiError(0, "NETWORK_ERROR", e.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
if (response.isSuccessful()) {
|
||||
callback.onSuccess(null);
|
||||
} else {
|
||||
callback.onError(parseError(response));
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (JSONException e) {
|
||||
callback.onError(new ApiError(0, "JSON_ERROR", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传App通知
|
||||
*/
|
||||
public void uploadNotification(String jsonPayload, ApiCallback<UploadNotificationResponse> callback) {
|
||||
Request request = buildAuthRequest("/api/bills/app-upload")
|
||||
.post(RequestBody.create(jsonPayload, JSON))
|
||||
.build();
|
||||
|
||||
httpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onError(new ApiError(0, "NETWORK_ERROR", e.getMessage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
handleResponse(response, UploadNotificationResponse.class, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建带认证的请求
|
||||
*/
|
||||
private Request.Builder buildAuthRequest(String path) {
|
||||
Request.Builder builder = new Request.Builder()
|
||||
.url(BASE_URL + path)
|
||||
.header("Content-Type", "application/json");
|
||||
|
||||
String authHeader = tokenManager.getAuthHeader();
|
||||
if (authHeader != null) {
|
||||
builder.header("Authorization", authHeader);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理响应
|
||||
*/
|
||||
private <T> void handleResponse(Response response, Class<T> clazz, ApiCallback<T> callback) {
|
||||
try {
|
||||
if (response.isSuccessful()) {
|
||||
String body = response.body() != null ? response.body().string() : "";
|
||||
T result = gson.fromJson(body, clazz);
|
||||
callback.onSuccess(result);
|
||||
} else {
|
||||
callback.onError(parseError(response));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Response handling error", e);
|
||||
callback.onError(new ApiError(0, "PARSE_ERROR", e.getMessage()));
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析错误响应
|
||||
*/
|
||||
private ApiError parseError(Response response) {
|
||||
try {
|
||||
int code = response.code();
|
||||
String body = response.body() != null ? response.body().string() : "";
|
||||
|
||||
try {
|
||||
JSONObject json = new JSONObject(body);
|
||||
String error = json.optString("error", "UNKNOWN_ERROR");
|
||||
String message = json.optString("message", body);
|
||||
return new ApiError(code, error, message);
|
||||
} catch (JSONException e) {
|
||||
return new ApiError(code, "HTTP_ERROR", body.isEmpty() ? "HTTP " + code : body);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return new ApiError(response.code(), "READ_ERROR", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API回调接口
|
||||
*/
|
||||
public interface ApiCallback<T> {
|
||||
void onSuccess(T result);
|
||||
void onError(ApiError error);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.miraclegarden.smsmessage.network;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.miraclegarden.smsmessage.model.LoginResponse;
|
||||
import com.miraclegarden.smsmessage.model.UserInfo;
|
||||
|
||||
/**
|
||||
* JWT Token管理器
|
||||
*/
|
||||
public class TokenManager {
|
||||
private static final String PREFS_NAME = "auth_prefs";
|
||||
private static final String KEY_TOKEN = "jwt_token";
|
||||
private static final String KEY_USER_ID = "user_id";
|
||||
private static final String KEY_USERNAME = "username";
|
||||
private static final String KEY_ROLE = "role";
|
||||
private static final String KEY_IS_FIRST_LOGIN = "is_first_login";
|
||||
|
||||
private final SharedPreferences prefs;
|
||||
private static TokenManager instance;
|
||||
|
||||
private TokenManager(Context context) {
|
||||
prefs = context.getApplicationContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public static synchronized TokenManager getInstance(Context context) {
|
||||
if (instance == null) {
|
||||
instance = new TokenManager(context);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void saveLoginData(LoginResponse response) {
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString(KEY_TOKEN, response.getToken());
|
||||
|
||||
UserInfo user = response.getUser();
|
||||
if (user != null) {
|
||||
editor.putString(KEY_USER_ID, user.getId());
|
||||
editor.putString(KEY_USERNAME, user.getUsername());
|
||||
editor.putString(KEY_ROLE, user.getRole());
|
||||
editor.putBoolean(KEY_IS_FIRST_LOGIN, user.isFirstLogin());
|
||||
}
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return prefs.getString(KEY_TOKEN, null);
|
||||
}
|
||||
|
||||
public String getAuthHeader() {
|
||||
String token = getToken();
|
||||
return token != null ? "Bearer " + token : null;
|
||||
}
|
||||
|
||||
public boolean isLoggedIn() {
|
||||
return getToken() != null;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return prefs.getString(KEY_USER_ID, null);
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return prefs.getString(KEY_USERNAME, null);
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return prefs.getString(KEY_ROLE, null);
|
||||
}
|
||||
|
||||
public boolean isFirstLogin() {
|
||||
return prefs.getBoolean(KEY_IS_FIRST_LOGIN, false);
|
||||
}
|
||||
|
||||
public void setFirstLoginComplete() {
|
||||
prefs.edit().putBoolean(KEY_IS_FIRST_LOGIN, false).apply();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
prefs.edit().clear().apply();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user