修复问题
This commit is contained in:
parent
c7e75a912a
commit
f4c9a42974
|
|
@ -29,6 +29,16 @@ spring:
|
|||
url: jdbc:mysql://1.15.149.240:3306/zhibo?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8
|
||||
username: zhibo
|
||||
password: zCETFpGMwYN3CNeH
|
||||
# JPA 配置 - 只新增字段,不删除已有字段
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update # update: 只新增表/字段,不删除
|
||||
show-sql: false
|
||||
open-in-view: false
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
|
||||
physical_naming_strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
|
||||
redis:
|
||||
host: 127.0.0.1 #地址
|
||||
port: 6379 #端口
|
||||
|
|
|
|||
|
|
@ -79,6 +79,12 @@
|
|||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- JPA 自动建表 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 模板引擎 mybatis code generator时需要使用-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
|||
|
|
@ -9,16 +9,20 @@ import lombok.Data;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 私聊会话实体类
|
||||
* 同时支持 MyBatis-Plus 和 JPA
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("eb_conversation")
|
||||
@Entity
|
||||
@Table(name = "eb_conversation")
|
||||
@ApiModel(value = "Conversation对象", description = "私聊会话")
|
||||
public class Conversation implements Serializable {
|
||||
|
||||
|
|
@ -26,41 +30,55 @@ public class Conversation implements Serializable {
|
|||
|
||||
@ApiModelProperty(value = "会话ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "用户1的ID")
|
||||
@Column(name = "user1_id", nullable = false)
|
||||
private Integer user1Id;
|
||||
|
||||
@ApiModelProperty(value = "用户2的ID")
|
||||
@Column(name = "user2_id", nullable = false)
|
||||
private Integer user2Id;
|
||||
|
||||
@ApiModelProperty(value = "最后一条消息内容")
|
||||
@Column(name = "last_message", length = 500)
|
||||
private String lastMessage;
|
||||
|
||||
@ApiModelProperty(value = "最后一条消息时间")
|
||||
@Column(name = "last_message_time")
|
||||
private Date lastMessageTime;
|
||||
|
||||
@ApiModelProperty(value = "用户1的未读数量")
|
||||
@Column(name = "user1_unread_count", columnDefinition = "INT DEFAULT 0")
|
||||
private Integer user1UnreadCount;
|
||||
|
||||
@ApiModelProperty(value = "用户2的未读数量")
|
||||
@Column(name = "user2_unread_count", columnDefinition = "INT DEFAULT 0")
|
||||
private Integer user2UnreadCount;
|
||||
|
||||
@ApiModelProperty(value = "用户1是否删除会话")
|
||||
@Column(name = "user1_deleted", columnDefinition = "TINYINT(1) DEFAULT 0")
|
||||
private Boolean user1Deleted;
|
||||
|
||||
@ApiModelProperty(value = "用户2是否删除会话")
|
||||
@Column(name = "user2_deleted", columnDefinition = "TINYINT(1) DEFAULT 0")
|
||||
private Boolean user2Deleted;
|
||||
|
||||
@ApiModelProperty(value = "用户1是否静音")
|
||||
@Column(name = "user1_muted", columnDefinition = "TINYINT(1) DEFAULT 0")
|
||||
private Boolean user1Muted;
|
||||
|
||||
@ApiModelProperty(value = "用户2是否静音")
|
||||
@Column(name = "user2_muted", columnDefinition = "TINYINT(1) DEFAULT 0")
|
||||
private Boolean user2Muted;
|
||||
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
@Column(name = "create_time")
|
||||
private Date createTime;
|
||||
|
||||
@ApiModelProperty(value = "更新时间")
|
||||
@Column(name = "update_time")
|
||||
private Date updateTime;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,16 +9,25 @@ import lombok.Data;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 私信消息实体类
|
||||
* 同时支持 MyBatis-Plus 和 JPA
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("eb_private_message")
|
||||
@Entity
|
||||
@Table(name = "eb_private_message", indexes = {
|
||||
@Index(name = "idx_conversation_id", columnList = "conversation_id"),
|
||||
@Index(name = "idx_sender_id", columnList = "sender_id"),
|
||||
@Index(name = "idx_receiver_id", columnList = "receiver_id"),
|
||||
@Index(name = "idx_create_time", columnList = "create_time")
|
||||
})
|
||||
@ApiModel(value = "PrivateMessage对象", description = "私信消息")
|
||||
public class PrivateMessage implements Serializable {
|
||||
|
||||
|
|
@ -26,35 +35,47 @@ public class PrivateMessage implements Serializable {
|
|||
|
||||
@ApiModelProperty(value = "消息ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "会话ID")
|
||||
@Column(name = "conversation_id", nullable = false)
|
||||
private Long conversationId;
|
||||
|
||||
@ApiModelProperty(value = "发送者用户ID")
|
||||
@Column(name = "sender_id", nullable = false)
|
||||
private Integer senderId;
|
||||
|
||||
@ApiModelProperty(value = "接收者用户ID")
|
||||
@Column(name = "receiver_id", nullable = false)
|
||||
private Integer receiverId;
|
||||
|
||||
@ApiModelProperty(value = "消息内容")
|
||||
@Column(name = "content", columnDefinition = "TEXT")
|
||||
private String content;
|
||||
|
||||
@ApiModelProperty(value = "消息类型: text, image, file")
|
||||
@Column(name = "message_type", length = 20, columnDefinition = "VARCHAR(20) DEFAULT 'text'")
|
||||
private String messageType;
|
||||
|
||||
@ApiModelProperty(value = "消息状态: sending, sent, read")
|
||||
@Column(name = "status", length = 20, columnDefinition = "VARCHAR(20) DEFAULT 'sent'")
|
||||
private String status;
|
||||
|
||||
@ApiModelProperty(value = "是否已删除(发送者)")
|
||||
@Column(name = "sender_deleted", columnDefinition = "TINYINT(1) DEFAULT 0")
|
||||
private Boolean senderDeleted;
|
||||
|
||||
@ApiModelProperty(value = "是否已删除(接收者)")
|
||||
@Column(name = "receiver_deleted", columnDefinition = "TINYINT(1) DEFAULT 0")
|
||||
private Boolean receiverDeleted;
|
||||
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
@Column(name = "create_time")
|
||||
private Date createTime;
|
||||
|
||||
@ApiModelProperty(value = "已读时间")
|
||||
@Column(name = "read_time")
|
||||
private Date readTime;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ public class StoreCoupon implements Serializable {
|
|||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "优惠券名称")
|
||||
private String name;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ import org.mybatis.spring.annotation.MapperScan;
|
|||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
|
@ -31,6 +33,8 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
|||
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) //去掉数据源
|
||||
@ComponentScan(basePackages = {"com.zbkj", "com.zbkj.front"})
|
||||
@MapperScan(basePackages = {"com.zbkj.**.dao"})
|
||||
@EntityScan(basePackages = {"com.zbkj.common.model"}) // JPA实体扫描
|
||||
@EnableJpaRepositories(basePackages = {"com.zbkj.service.repository"}) // JPA仓库扫描(可选)
|
||||
public class CrmebFrontApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(CrmebFrontApplication.class, args);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,19 @@ spring:
|
|||
url: jdbc:mysql://1.15.149.240:3306/zhibo?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8
|
||||
username: zhibo
|
||||
password: zCETFpGMwYN3CNeH
|
||||
# JPA 配置 - 只新增字段,不删除已有字段
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update # update: 只新增表/字段,不删除;none: 不做任何操作
|
||||
show-sql: false # 生产环境建议关闭
|
||||
open-in-view: false # 关闭懒加载视图
|
||||
properties:
|
||||
hibernate:
|
||||
format_sql: true
|
||||
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
|
||||
# 命名策略:将驼峰转为下划线
|
||||
physical_naming_strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
|
||||
implicit_naming_strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
|
||||
redis:
|
||||
host: 127.0.0.1 #地址
|
||||
port: 6379 #端口
|
||||
|
|
|
|||
|
|
@ -100,6 +100,13 @@
|
|||
<version>3.3.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JPA 自动建表 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
<version>2.2.6.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<!--generator-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ public class ConversationActivity extends AppCompatActivity {
|
|||
private static final String EXTRA_CONVERSATION_TITLE = "extra_conversation_title";
|
||||
private static final String EXTRA_UNREAD_COUNT = "extra_unread_count";
|
||||
private static final int PAGE_SIZE = 20;
|
||||
private static final long POLL_INTERVAL = 3000; // 3秒轮询一次
|
||||
|
||||
private ActivityConversationBinding binding;
|
||||
private final OkHttpClient httpClient = new OkHttpClient();
|
||||
|
|
@ -52,6 +53,8 @@ public class ConversationActivity extends AppCompatActivity {
|
|||
private ConversationMessagesAdapter adapter;
|
||||
private final List<ChatMessage> messages = new ArrayList<>();
|
||||
private Handler handler;
|
||||
private Runnable pollRunnable;
|
||||
private boolean isPolling = false;
|
||||
|
||||
private String conversationId;
|
||||
private int currentPage = 1;
|
||||
|
|
@ -78,7 +81,15 @@ public class ConversationActivity extends AppCompatActivity {
|
|||
|
||||
conversationId = getIntent() != null ? getIntent().getStringExtra(EXTRA_CONVERSATION_ID) : null;
|
||||
initialUnreadCount = getIntent() != null ? getIntent().getIntExtra(EXTRA_UNREAD_COUNT, 0) : 0;
|
||||
|
||||
// 先尝试从 AuthStore 获取 userId
|
||||
currentUserId = AuthStore.getUserId(this);
|
||||
Log.d(TAG, "从AuthStore获取的用户ID: " + currentUserId);
|
||||
|
||||
// 如果 userId 为空,尝试从用户信息接口获取
|
||||
if (currentUserId == null || currentUserId.isEmpty()) {
|
||||
fetchCurrentUserId();
|
||||
}
|
||||
|
||||
binding.backButton.setOnClickListener(new DebounceClickListener() {
|
||||
@Override
|
||||
|
|
@ -99,6 +110,42 @@ public class ConversationActivity extends AppCompatActivity {
|
|||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
stopPolling();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
startPolling();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始轮询新消息
|
||||
*/
|
||||
private void startPolling() {
|
||||
if (isPolling) return;
|
||||
isPolling = true;
|
||||
|
||||
pollRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isPolling || isFinishing() || isDestroyed()) return;
|
||||
loadMessagesFromServer();
|
||||
handler.postDelayed(this, POLL_INTERVAL);
|
||||
}
|
||||
};
|
||||
// 延迟开始轮询,避免和初始加载冲突
|
||||
handler.postDelayed(pollRunnable, POLL_INTERVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止轮询
|
||||
*/
|
||||
private void stopPolling() {
|
||||
isPolling = false;
|
||||
if (pollRunnable != null && handler != null) {
|
||||
handler.removeCallbacks(pollRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMessages() {
|
||||
|
|
@ -116,6 +163,58 @@ public class ConversationActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从服务器获取当前用户ID
|
||||
*/
|
||||
private void fetchCurrentUserId() {
|
||||
String token = AuthStore.getToken(this);
|
||||
if (token == null) {
|
||||
Log.w(TAG, "未登录,无法获取用户ID");
|
||||
return;
|
||||
}
|
||||
|
||||
String url = ApiConfig.getBaseUrl() + "/api/front/user/info";
|
||||
Log.d(TAG, "获取用户信息: " + url);
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.addHeader("Authori-zation", token)
|
||||
.get()
|
||||
.build();
|
||||
|
||||
httpClient.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
Log.e(TAG, "获取用户信息失败", e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
String body = response.body() != null ? response.body().string() : "";
|
||||
Log.d(TAG, "用户信息响应: " + body);
|
||||
try {
|
||||
JSONObject json = new JSONObject(body);
|
||||
if (json.optInt("code", -1) == 200) {
|
||||
JSONObject data = json.optJSONObject("data");
|
||||
if (data != null) {
|
||||
int uid = data.optInt("uid", 0);
|
||||
if (uid > 0) {
|
||||
currentUserId = String.valueOf(uid);
|
||||
// 保存到 AuthStore
|
||||
AuthStore.setUserInfo(ConversationActivity.this, currentUserId, data.optString("nickname", ""));
|
||||
Log.d(TAG, "从服务器获取到用户ID: " + currentUserId);
|
||||
// 重新加载消息以正确显示
|
||||
runOnUiThread(() -> loadMessagesFromServer());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "解析用户信息失败", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 从服务器加载消息列表
|
||||
*/
|
||||
|
|
@ -182,7 +281,7 @@ public class ConversationActivity extends AppCompatActivity {
|
|||
private ChatMessage parseChatMessage(JSONObject item) {
|
||||
try {
|
||||
String messageId = item.optString("messageId", "");
|
||||
int userId = item.optInt("userId", 0);
|
||||
int senderId = item.optInt("userId", 0); // 后端返回的 userId 实际是 senderId
|
||||
String username = item.optString("username", "未知用户");
|
||||
String message = item.optString("message", "");
|
||||
long timestamp = item.optLong("timestamp", System.currentTimeMillis());
|
||||
|
|
@ -191,7 +290,20 @@ public class ConversationActivity extends AppCompatActivity {
|
|||
boolean isSystem = item.optBoolean("isSystemMessage", false);
|
||||
|
||||
// 判断是否是自己发送的消息
|
||||
boolean isMine = currentUserId != null && currentUserId.equals(String.valueOf(userId));
|
||||
// 每次都重新从 AuthStore 获取最新的 userId,确保登录后能正确获取
|
||||
String myUserId = AuthStore.getUserId(this);
|
||||
if (myUserId == null || myUserId.isEmpty()) {
|
||||
myUserId = currentUserId;
|
||||
} else {
|
||||
currentUserId = myUserId; // 同步更新
|
||||
}
|
||||
|
||||
boolean isMine = false;
|
||||
if (myUserId != null && !myUserId.isEmpty() && senderId > 0) {
|
||||
isMine = myUserId.equals(String.valueOf(senderId));
|
||||
}
|
||||
Log.d(TAG, "消息判断: myUserId=" + myUserId + ", senderId=" + senderId + ", isMine=" + isMine);
|
||||
|
||||
String displayName = isMine ? "我" : username;
|
||||
|
||||
ChatMessage.MessageStatus msgStatus;
|
||||
|
|
@ -457,6 +569,7 @@ public class ConversationActivity extends AppCompatActivity {
|
|||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
stopPolling();
|
||||
handler = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,17 +300,17 @@ public class ConversationMessagesAdapter extends ListAdapter<ChatMessage, Recycl
|
|||
switch (message.getStatus()) {
|
||||
case SENDING:
|
||||
statusIcon.setImageResource(R.drawable.ic_clock_24);
|
||||
statusIcon.setColorFilter(itemView.getContext().getColor(android.R.color.darker_gray));
|
||||
statusIcon.setColorFilter(android.graphics.Color.GRAY, android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
statusIcon.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case SENT:
|
||||
statusIcon.setImageResource(R.drawable.ic_check_24);
|
||||
statusIcon.setColorFilter(itemView.getContext().getColor(android.R.color.darker_gray));
|
||||
statusIcon.setColorFilter(android.graphics.Color.GRAY, android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
statusIcon.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case READ:
|
||||
statusIcon.setImageResource(R.drawable.ic_check_double_24);
|
||||
statusIcon.setColorFilter(0xFF4CAF50);
|
||||
statusIcon.setColorFilter(android.graphics.Color.parseColor("#4CAF50"), android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
statusIcon.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -100,23 +100,7 @@ public class LoginActivity extends AppCompatActivity {
|
|||
binding.loginButton.setEnabled(false);
|
||||
binding.loadingProgress.setVisibility(View.VISIBLE);
|
||||
|
||||
// ============================================
|
||||
// 测试模式:直接使用演示模式登录,跳过网络请求
|
||||
// 当后端接口接入后,可以删除此代码,恢复下面的网络请求
|
||||
// ============================================
|
||||
// 模拟网络请求延迟(让用户看到加载状态)
|
||||
binding.getRoot().postDelayed(() -> {
|
||||
handleDemoModeLogin(account);
|
||||
}, 500); // 延迟500ms,模拟网络请求
|
||||
|
||||
// 以下代码在测试模式下被注释,接入后端后可以恢复
|
||||
/*
|
||||
// TODO: 接入后端接口 - 用户登录
|
||||
// 接口路径: POST /api/front/login(ApiService中已定义)
|
||||
// 请求参数: LoginRequest {account: string, password: string}
|
||||
// 返回数据格式: ApiResponse<LoginResponse>
|
||||
// LoginResponse对象应包含: token, userId, nickname, avatarUrl等字段
|
||||
// 登录成功后,保存token到AuthStore,并更新用户信息到本地SharedPreferences
|
||||
// 调用后端登录接口
|
||||
ApiClient.getService(getApplicationContext()).login(new LoginRequest(account, password))
|
||||
.enqueue(new Callback<ApiResponse<LoginResponse>>() {
|
||||
@Override
|
||||
|
|
@ -128,15 +112,8 @@ public class LoginActivity extends AppCompatActivity {
|
|||
ApiResponse<LoginResponse> body = response.body();
|
||||
LoginResponse loginData = body != null ? body.getData() : null;
|
||||
|
||||
// 如果响应不成功或数据无效,检查是否是后端未接入的情况
|
||||
// 如果响应不成功或数据无效
|
||||
if (!response.isSuccessful() || body == null || !body.isOk() || loginData == null) {
|
||||
// 如果是404、500等错误,可能是后端未接入,使用演示模式
|
||||
if (!response.isSuccessful() && (response.code() == 404 || response.code() == 500 || response.code() == 502 || response.code() == 503)) {
|
||||
// 后端服务未启动或未接入,使用演示模式
|
||||
handleDemoModeLogin(account);
|
||||
return;
|
||||
}
|
||||
|
||||
String errorMsg = "登录失败";
|
||||
if (body != null && !TextUtils.isEmpty(body.getMessage())) {
|
||||
errorMsg = body.getMessage();
|
||||
|
|
@ -158,9 +135,10 @@ public class LoginActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
// 保存用户信息到 AuthStore
|
||||
AuthStore.setUserInfo(getApplicationContext(),
|
||||
loginData.getUid(),
|
||||
loginData.getNikeName());
|
||||
String uid = loginData.getUid();
|
||||
String nickname = loginData.getNikeName();
|
||||
android.util.Log.d("LoginActivity", "登录返回的 uid: " + uid + ", nickname: " + nickname);
|
||||
AuthStore.setUserInfo(getApplicationContext(), uid, nickname);
|
||||
|
||||
// 保存用户信息到本地 SharedPreferences
|
||||
SharedPreferences prefs = getSharedPreferences("profile_prefs", MODE_PRIVATE);
|
||||
|
|
@ -171,8 +149,7 @@ public class LoginActivity extends AppCompatActivity {
|
|||
prefs.edit().putString("profile_phone", loginData.getPhone()).apply();
|
||||
}
|
||||
|
||||
// 登录成功,返回上一页(如果是从其他页面跳转过来的)
|
||||
// 如果是直接打开登录页面,则跳转到主页面
|
||||
// 登录成功
|
||||
Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
|
||||
|
||||
// 检查是否有上一个Activity
|
||||
|
|
@ -194,74 +171,14 @@ public class LoginActivity extends AppCompatActivity {
|
|||
binding.loginButton.setEnabled(true);
|
||||
binding.loadingProgress.setVisibility(View.GONE);
|
||||
|
||||
// 检测是否是网络连接错误(后端未启动)
|
||||
boolean isNetworkError = false;
|
||||
String errorMsg = "网络错误";
|
||||
if (t != null) {
|
||||
String msg = t.getMessage();
|
||||
if (msg != null) {
|
||||
if (msg.contains("Unable to resolve host") ||
|
||||
msg.contains("timeout") ||
|
||||
msg.contains("Connection refused") ||
|
||||
msg.contains("Failed to connect")) {
|
||||
isNetworkError = true;
|
||||
errorMsg = "无法连接到服务器,已切换到演示模式";
|
||||
} else {
|
||||
errorMsg = "网络错误:" + msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是网络连接错误(后端未接入),使用演示模式登录
|
||||
if (isNetworkError) {
|
||||
handleDemoModeLogin(account);
|
||||
} else {
|
||||
Toast.makeText(LoginActivity.this, errorMsg, Toast.LENGTH_LONG).show();
|
||||
if (t != null && t.getMessage() != null) {
|
||||
errorMsg = "网络错误:" + t.getMessage();
|
||||
}
|
||||
Toast.makeText(LoginActivity.this, errorMsg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理演示模式登录(测试模式:直接登录成功)
|
||||
*/
|
||||
private void handleDemoModeLogin(String account) {
|
||||
// 恢复UI状态
|
||||
isLoggingIn = false;
|
||||
binding.loginButton.setEnabled(true);
|
||||
binding.loadingProgress.setVisibility(View.GONE);
|
||||
|
||||
// 测试模式:允许任意账号密码登录(仅用于开发测试)
|
||||
// 生成一个演示token(基于账号)
|
||||
String demoToken = "demo_token_" + account.hashCode();
|
||||
android.util.Log.d("LoginActivity", "演示模式 - 生成 token: " + demoToken);
|
||||
AuthStore.setToken(getApplicationContext(), demoToken);
|
||||
|
||||
// 保存用户信息到本地
|
||||
SharedPreferences prefs = getSharedPreferences("profile_prefs", MODE_PRIVATE);
|
||||
String displayName = account.length() > 0 ? account : "演示用户";
|
||||
prefs.edit()
|
||||
.putString("profile_name", displayName)
|
||||
.putString("user_id", "demo_user_" + account.hashCode())
|
||||
.apply();
|
||||
|
||||
// 登录成功提示
|
||||
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
|
||||
|
||||
// 登录成功,返回上一页(如果是从其他页面跳转过来的)
|
||||
// 如果是直接打开登录页面,则跳转到主页面
|
||||
// 检查是否有上一个Activity
|
||||
if (isTaskRoot()) {
|
||||
// 如果没有上一个Activity,跳转到主页面
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
} else {
|
||||
// 有上一个Activity,直接返回
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ public final class AuthStore {
|
|||
|
||||
public static void setUserInfo(Context context, @Nullable String userId, @Nullable String nickname) {
|
||||
if (context == null) return;
|
||||
Log.d(TAG, "setUserInfo: userId=" + userId + ", nickname=" + nickname);
|
||||
context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
|
||||
.edit()
|
||||
.putString(KEY_USER_ID, userId)
|
||||
|
|
@ -61,8 +62,14 @@ public final class AuthStore {
|
|||
@Nullable
|
||||
public static String getUserId(Context context) {
|
||||
if (context == null) return null;
|
||||
return context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
|
||||
.getString(KEY_USER_ID, "");
|
||||
String userId = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
|
||||
.getString(KEY_USER_ID, null);
|
||||
// 确保空字符串也返回 null
|
||||
if (userId != null && userId.trim().isEmpty()) {
|
||||
userId = null;
|
||||
}
|
||||
Log.d(TAG, "getUserId: " + userId);
|
||||
return userId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user