parent
d22675fcd8
commit
496f77dbbc
@ -0,0 +1,74 @@
|
||||
package com.startsmake.llrisetabbardemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.startsmake.llrisetabbardemo.R;
|
||||
import com.startsmake.llrisetabbardemo.model.ChatMessage;
|
||||
import java.util.List;
|
||||
|
||||
public class ChatMessageAdapter extends RecyclerView.Adapter<ChatMessageAdapter.ViewHolder> {
|
||||
|
||||
private Context context;
|
||||
private List<ChatMessage> messageList;
|
||||
|
||||
public ChatMessageAdapter(Context context, List<ChatMessage> messageList) {
|
||||
this.context = context;
|
||||
this.messageList = messageList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(context).inflate(R.layout.item_chat_message, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
ChatMessage message = messageList.get(position);
|
||||
|
||||
if (message.isMe()) {
|
||||
// 自己发送的消息 - 右侧显示
|
||||
holder.layoutLeft.setVisibility(View.GONE);
|
||||
holder.layoutRight.setVisibility(View.VISIBLE);
|
||||
holder.tvRightMessage.setText(message.getContent());
|
||||
holder.tvRightTime.setText(message.getTime());
|
||||
} else {
|
||||
// 对方发送的消息 - 左侧显示
|
||||
holder.layoutRight.setVisibility(View.GONE);
|
||||
holder.layoutLeft.setVisibility(View.VISIBLE);
|
||||
holder.tvLeftMessage.setText(message.getContent());
|
||||
holder.tvLeftTime.setText(message.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return messageList.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
LinearLayout layoutLeft;
|
||||
LinearLayout layoutRight;
|
||||
TextView tvLeftMessage;
|
||||
TextView tvRightMessage;
|
||||
TextView tvLeftTime;
|
||||
TextView tvRightTime;
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
layoutLeft = itemView.findViewById(R.id.layoutLeft);
|
||||
layoutRight = itemView.findViewById(R.id.layoutRight);
|
||||
tvLeftMessage = itemView.findViewById(R.id.tvLeftMessage);
|
||||
tvRightMessage = itemView.findViewById(R.id.tvRightMessage);
|
||||
tvLeftTime = itemView.findViewById(R.id.tvLeftTime);
|
||||
tvRightTime = itemView.findViewById(R.id.tvRightTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
package com.startsmake.llrisetabbardemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.startsmake.llrisetabbardemo.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ImageAdapter extends BaseAdapter {
|
||||
|
||||
private Context context;
|
||||
private List<Uri> imageUris;
|
||||
private static final int MAX_IMAGES = 9;
|
||||
|
||||
public ImageAdapter(Context context, List<Uri> imageUris) {
|
||||
this.context = context;
|
||||
this.imageUris = imageUris;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return Math.min(imageUris.size() + 1, MAX_IMAGES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
if (position < imageUris.size()) {
|
||||
return imageUris.get(position);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ViewHolder holder;
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(context).inflate(R.layout.item_image, parent, false);
|
||||
holder = new ViewHolder();
|
||||
holder.imageView = convertView.findViewById(R.id.imageView);
|
||||
holder.deleteButton = convertView.findViewById(R.id.btnDelete);
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
if (position < imageUris.size()) {
|
||||
// 显示已选择的图片
|
||||
Uri imageUri = imageUris.get(position);
|
||||
Glide.with(context)
|
||||
.load(imageUri)
|
||||
.placeholder(android.R.drawable.ic_menu_gallery) // 使用系统图标作为占位符
|
||||
.into(holder.imageView);
|
||||
|
||||
holder.deleteButton.setVisibility(View.VISIBLE);
|
||||
holder.deleteButton.setOnClickListener(v -> {
|
||||
imageUris.remove(position);
|
||||
notifyDataSetChanged();
|
||||
});
|
||||
} else {
|
||||
// 显示添加按钮
|
||||
holder.imageView.setImageResource(android.R.drawable.ic_input_add); // 使用系统图标
|
||||
holder.deleteButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
static class ViewHolder {
|
||||
ImageView imageView;
|
||||
ImageView deleteButton;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
package com.startsmake.llrisetabbardemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.startsmake.llrisetabbardemo.R;
|
||||
import com.startsmake.llrisetabbardemo.model.MessageItem;
|
||||
import java.util.List;
|
||||
|
||||
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.ViewHolder> {
|
||||
|
||||
private Context context;
|
||||
private List<MessageItem> messageList;
|
||||
private OnItemClickListener onItemClickListener;
|
||||
|
||||
public MessageAdapter(Context context, List<MessageItem> messageList) {
|
||||
this.context = context;
|
||||
this.messageList = messageList;
|
||||
}
|
||||
|
||||
// 添加点击监听接口
|
||||
public interface OnItemClickListener {
|
||||
void onItemClick(MessageItem item);
|
||||
}
|
||||
|
||||
public void setOnItemClickListener(OnItemClickListener listener) {
|
||||
this.onItemClickListener = listener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(context).inflate(R.layout.item_message, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
MessageItem item = messageList.get(position);
|
||||
|
||||
// 设置默认白色头像背景
|
||||
holder.ivAvatar.setBackgroundResource(R.drawable.bg_avatar_placeholder);
|
||||
|
||||
holder.tvTitle.setText(item.getTitle());
|
||||
holder.tvContent.setText(item.getContent());
|
||||
holder.tvTime.setText(item.getTime());
|
||||
|
||||
// 未读消息数量
|
||||
if (item.getUnreadCount() > 0) {
|
||||
holder.tvUnreadCount.setVisibility(View.VISIBLE);
|
||||
holder.tvUnreadCount.setText(String.valueOf(item.getUnreadCount()));
|
||||
} else {
|
||||
holder.tvUnreadCount.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// 官方标识
|
||||
if (item.isOfficial()) {
|
||||
holder.ivOfficial.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.ivOfficial.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// 添加点击事件
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (onItemClickListener != null) {
|
||||
onItemClickListener.onItemClick(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return messageList.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
ImageView ivAvatar;
|
||||
TextView tvTitle;
|
||||
TextView tvContent;
|
||||
TextView tvTime;
|
||||
TextView tvUnreadCount;
|
||||
ImageView ivOfficial;
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ivAvatar = itemView.findViewById(R.id.ivAvatar);
|
||||
tvTitle = itemView.findViewById(R.id.tvTitle);
|
||||
tvContent = itemView.findViewById(R.id.tvContent);
|
||||
tvTime = itemView.findViewById(R.id.tvTime);
|
||||
tvUnreadCount = itemView.findViewById(R.id.tvUnreadCount);
|
||||
ivOfficial = itemView.findViewById(R.id.ivOfficial);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.startsmake.llrisetabbardemo.api;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ApiClient {
|
||||
private static final String BASE_URL = "http://localhost:8080/";
|
||||
private static Retrofit retrofit = null;
|
||||
|
||||
public static Retrofit getClient() {
|
||||
if (retrofit == null) {
|
||||
OkHttpClient client = new OkHttpClient.Builder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.writeTimeout(30, TimeUnit.SECONDS)
|
||||
.build();
|
||||
|
||||
retrofit = new Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build();
|
||||
}
|
||||
return retrofit;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.startsmake.llrisetabbardemo.api;
|
||||
|
||||
import com.startsmake.llrisetabbardemo.api.response.BaseResponse;
|
||||
import com.startsmake.llrisetabbardemo.api.response.ProductResponse;
|
||||
import com.startsmake.llrisetabbardemo.api.response.UserResponse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Field;
|
||||
import retrofit2.http.FormUrlEncoded;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
public interface ApiService {
|
||||
// 获取API状态
|
||||
@GET("api")
|
||||
Call<BaseResponse> getApiStatus();
|
||||
|
||||
// 用户登录
|
||||
@FormUrlEncoded
|
||||
@POST("api/login")
|
||||
Call<UserResponse> login(@Field("phone") String phone, @Field("password") String password);
|
||||
|
||||
// 用户注册
|
||||
@FormUrlEncoded
|
||||
@POST("api/register")
|
||||
Call<UserResponse> register(@Field("phone") String phone, @Field("password") String password,
|
||||
@Field("username") String username);
|
||||
|
||||
// 获取商品列表
|
||||
@GET("api/products")
|
||||
Call<BaseResponse<List<ProductResponse>>> getProducts();
|
||||
|
||||
// 搜索商品
|
||||
@GET("api/products/search")
|
||||
Call<BaseResponse<List<ProductResponse>>> searchProducts(@Query("keyword") String keyword);
|
||||
|
||||
// 获取商品详情
|
||||
@GET("api/products/detail")
|
||||
Call<BaseResponse<ProductResponse>> getProductDetail(@Query("id") String productId);
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.startsmake.llrisetabbardemo.api.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class BaseResponse<T> {
|
||||
@SerializedName("status")
|
||||
private String status;
|
||||
|
||||
@SerializedName("message")
|
||||
private String message;
|
||||
|
||||
@SerializedName("data")
|
||||
private T data;
|
||||
|
||||
// Getters and Setters
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return "success".equals(status);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
package com.startsmake.llrisetabbardemo.api.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ProductResponse {
|
||||
@SerializedName("id")
|
||||
private String id;
|
||||
|
||||
@SerializedName("title")
|
||||
private String title;
|
||||
|
||||
@SerializedName("description")
|
||||
private String description;
|
||||
|
||||
@SerializedName("category")
|
||||
private String category;
|
||||
|
||||
@SerializedName("price")
|
||||
private double price;
|
||||
|
||||
@SerializedName("image_urls")
|
||||
private List<String> imageUrls;
|
||||
|
||||
@SerializedName("contact")
|
||||
private String contact;
|
||||
|
||||
@SerializedName("publish_time")
|
||||
private long publishTime;
|
||||
|
||||
@SerializedName("seller_id")
|
||||
private String sellerId;
|
||||
|
||||
// Getters and Setters
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(double price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public List<String> getImageUrls() {
|
||||
return imageUrls;
|
||||
}
|
||||
|
||||
public void setImageUrls(List<String> imageUrls) {
|
||||
this.imageUrls = imageUrls;
|
||||
}
|
||||
|
||||
public String getContact() {
|
||||
return contact;
|
||||
}
|
||||
|
||||
public void setContact(String contact) {
|
||||
this.contact = contact;
|
||||
}
|
||||
|
||||
public long getPublishTime() {
|
||||
return publishTime;
|
||||
}
|
||||
|
||||
public void setPublishTime(long publishTime) {
|
||||
this.publishTime = publishTime;
|
||||
}
|
||||
|
||||
public String getSellerId() {
|
||||
return sellerId;
|
||||
}
|
||||
|
||||
public void setSellerId(String sellerId) {
|
||||
this.sellerId = sellerId;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.startsmake.llrisetabbardemo.api.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class UserResponse extends BaseResponse<UserResponse.UserInfo> {
|
||||
public static class UserInfo {
|
||||
@SerializedName("id")
|
||||
private String id;
|
||||
|
||||
@SerializedName("username")
|
||||
private String username;
|
||||
|
||||
@SerializedName("phone")
|
||||
private String phone;
|
||||
|
||||
@SerializedName("token")
|
||||
private String token;
|
||||
|
||||
// Getters and Setters
|
||||
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 getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.startsmake.llrisetabbardemo.decoration;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
|
||||
|
||||
private int spanCount;
|
||||
private int spacing;
|
||||
private boolean includeEdge;
|
||||
|
||||
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
|
||||
this.spanCount = spanCount;
|
||||
this.spacing = spacing;
|
||||
this.includeEdge = includeEdge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
|
||||
int position = parent.getChildAdapterPosition(view);
|
||||
int column = position % spanCount;
|
||||
|
||||
if (includeEdge) {
|
||||
outRect.left = spacing - column * spacing / spanCount;
|
||||
outRect.right = (column + 1) * spacing / spanCount;
|
||||
|
||||
if (position < spanCount) {
|
||||
outRect.top = spacing;
|
||||
}
|
||||
outRect.bottom = spacing;
|
||||
} else {
|
||||
outRect.left = column * spacing / spanCount;
|
||||
outRect.right = spacing - (column + 1) * spacing / spanCount;
|
||||
if (position >= spanCount) {
|
||||
outRect.top = spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.startsmake.llrisetabbardemo.model;
|
||||
|
||||
public class ChatMessage {
|
||||
private String sender;
|
||||
private String content;
|
||||
private String time;
|
||||
private boolean isMe;
|
||||
|
||||
public ChatMessage(String sender, String content, String time, boolean isMe) {
|
||||
this.sender = sender;
|
||||
this.content = content;
|
||||
this.time = time;
|
||||
this.isMe = isMe;
|
||||
}
|
||||
|
||||
// Getter and Setter methods
|
||||
public String getSender() { return sender; }
|
||||
public void setSender(String sender) { this.sender = sender; }
|
||||
|
||||
public String getContent() { return content; }
|
||||
public void setContent(String content) { this.content = content; }
|
||||
|
||||
public String getTime() { return time; }
|
||||
public void setTime(String time) { this.time = time; }
|
||||
|
||||
public boolean isMe() { return isMe; }
|
||||
public void setMe(boolean me) { isMe = me; }
|
||||
}
|
||||
@ -0,0 +1,121 @@
|
||||
package com.startsmake.llrisetabbardemo.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Item implements Serializable {
|
||||
private String id;
|
||||
private String title;
|
||||
private String description;
|
||||
private int wantCount;
|
||||
private double price;
|
||||
private List<String> imageUrls;
|
||||
private String category;
|
||||
private String location;
|
||||
private String contact;
|
||||
private String contactQQ; // 新增QQ联系方式
|
||||
private String contactWechat; // 新增微信联系方式
|
||||
private long publishTime;
|
||||
private String userId;
|
||||
private int viewCount; // 浏览数
|
||||
private int likeCount; // 点赞数
|
||||
|
||||
public Item() {
|
||||
imageUrls = new ArrayList<>();
|
||||
viewCount = 0;
|
||||
likeCount = 0;
|
||||
}
|
||||
|
||||
// Getter 和 Setter
|
||||
public int getWantCount() {
|
||||
return wantCount;
|
||||
}
|
||||
|
||||
public void setWantCount(int wantCount) {
|
||||
this.wantCount = wantCount;
|
||||
}
|
||||
|
||||
// 构造函数
|
||||
public Item(String title, String description, double price, String category, String location, String contact) {
|
||||
this();
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.price = price;
|
||||
this.category = category;
|
||||
this.location = location;
|
||||
this.contact = contact;
|
||||
this.publishTime = System.currentTimeMillis();
|
||||
this.userId = "user_" + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// Getter 和 Setter 方法
|
||||
public String getId() { return id; }
|
||||
public void setId(String id) { this.id = id; }
|
||||
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public double getPrice() { return price; }
|
||||
public void setPrice(double price) { this.price = price; }
|
||||
|
||||
public List<String> getImageUrls() { return imageUrls; }
|
||||
public void setImageUrls(List<String> imageUrls) { this.imageUrls = imageUrls; }
|
||||
public void addImageUrl(String imageUrl) { this.imageUrls.add(imageUrl); }
|
||||
|
||||
public String getCategory() { return category; }
|
||||
public void setCategory(String category) { this.category = category; }
|
||||
|
||||
public String getLocation() { return location; }
|
||||
public void setLocation(String location) { this.location = location; }
|
||||
|
||||
public String getContact() { return contact; }
|
||||
public void setContact(String contact) { this.contact = contact; }
|
||||
|
||||
public String getContactQQ() { return contactQQ; }
|
||||
public void setContactQQ(String contactQQ) { this.contactQQ = contactQQ; }
|
||||
|
||||
public String getContactWechat() { return contactWechat; }
|
||||
public void setContactWechat(String contactWechat) { this.contactWechat = contactWechat; }
|
||||
|
||||
public long getPublishTime() { return publishTime; }
|
||||
public void setPublishTime(long publishTime) { this.publishTime = publishTime; }
|
||||
|
||||
public String getUserId() { return userId; }
|
||||
public void setUserId(String userId) { this.userId = userId; }
|
||||
|
||||
public int getViewCount() { return viewCount; }
|
||||
public void setViewCount(int viewCount) { this.viewCount = viewCount; }
|
||||
|
||||
public int getLikeCount() { return likeCount; }
|
||||
public void setLikeCount(int likeCount) { this.likeCount = likeCount; }
|
||||
|
||||
/**
|
||||
* 增加浏览数
|
||||
*/
|
||||
public void incrementViewCount() {
|
||||
this.viewCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加点赞数
|
||||
*/
|
||||
public void incrementLikeCount() {
|
||||
this.likeCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Item{" +
|
||||
"id='" + id + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
", price=" + price +
|
||||
", category='" + category + '\'' +
|
||||
", location='" + location + '\'' +
|
||||
", publishTime=" + publishTime +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.startsmake.llrisetabbardemo.model;
|
||||
|
||||
public class MessageItem {
|
||||
private String title;
|
||||
private String content;
|
||||
private String time;
|
||||
private int unreadCount;
|
||||
private boolean isOfficial;
|
||||
|
||||
public MessageItem(String title, String content, String time, int unreadCount, boolean isOfficial) {
|
||||
this.title = title;
|
||||
this.content = content;
|
||||
this.time = time;
|
||||
this.unreadCount = unreadCount;
|
||||
this.isOfficial = isOfficial;
|
||||
}
|
||||
|
||||
// Getter and Setter methods
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
|
||||
public String getContent() { return content; }
|
||||
public void setContent(String content) { this.content = content; }
|
||||
|
||||
public String getTime() { return time; }
|
||||
public void setTime(String time) { this.time = time; }
|
||||
|
||||
public int getUnreadCount() { return unreadCount; }
|
||||
public void setUnreadCount(int unreadCount) { this.unreadCount = unreadCount; }
|
||||
|
||||
public boolean isOfficial() { return isOfficial; }
|
||||
public void setOfficial(boolean official) { isOfficial = official; }
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.startsmake.llrisetabbardemo.model;
|
||||
|
||||
public class User {
|
||||
private String phone;
|
||||
private String password;
|
||||
private String username;
|
||||
private long registerTime;
|
||||
|
||||
public User(String phone, String password) {
|
||||
this.phone = phone;
|
||||
this.password = password;
|
||||
this.username = "用户_" + phone.substring(7);
|
||||
this.registerTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getPhone() { return phone; }
|
||||
public void setPhone(String phone) { this.phone = phone; }
|
||||
|
||||
public String getPassword() { return password; }
|
||||
public void setPassword(String password) { this.password = password; }
|
||||
|
||||
public String getUsername() { return username; }
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
|
||||
public long getRegisterTime() { return registerTime; }
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#e0e0e0" />
|
||||
<corners android:radius="4dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f5f5f5" />
|
||||
<corners android:radius="24dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#e0e0e0" />
|
||||
</shape>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners
|
||||
android:topLeftRadius="0dp"
|
||||
android:topRightRadius="16dp"
|
||||
android:bottomLeftRadius="16dp"
|
||||
android:bottomRightRadius="16dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#e0e0e0" />
|
||||
</shape>
|
||||
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#07C160" />
|
||||
<corners
|
||||
android:topLeftRadius="16dp"
|
||||
android:topRightRadius="0dp"
|
||||
android:bottomLeftRadius="16dp"
|
||||
android:bottomRightRadius="16dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#99000000" />
|
||||
<corners android:radius="12dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#FFFFFF" />
|
||||
<stroke android:width="1dp" android:color="#E0E0E0" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f0f0f0" />
|
||||
<corners android:radius="4dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#e0e0e0" />
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f5f5f5" />
|
||||
<corners android:radius="18dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#FF5000" />
|
||||
<corners android:radius="9dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#87CEEB"/>
|
||||
<corners android:radius="12dp"/>
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<stroke android:width="1dp" android:color="#e0e0e0" />
|
||||
<corners android:radius="4dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#2196F3"/>
|
||||
<corners android:radius="16dp"/>
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#2196F3"/>
|
||||
<corners android:radius="12dp"/>
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f8f9fa" />
|
||||
<corners android:radius="8dp" />
|
||||
<stroke android:width="1dp" android:color="#dee2e6" />
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#FFFFFF"/>
|
||||
<corners android:radius="12dp"/>
|
||||
</shape>
|
||||
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<solid android:color="#FFFFFFFF" />
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#FFE0E0E0" />
|
||||
|
||||
<!-- 添加阴影效果 -->
|
||||
<padding
|
||||
android:left="2dp"
|
||||
android:top="2dp"
|
||||
android:right="2dp"
|
||||
android:bottom="2dp" />
|
||||
|
||||
</shape>
|
||||
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="12dp" />
|
||||
<solid android:color="#FF00BCD4" />
|
||||
<stroke
|
||||
android:width="0.5dp"
|
||||
android:color="#FF0097A7" />
|
||||
<padding
|
||||
android:left="8dp"
|
||||
android:top="2dp"
|
||||
android:right="8dp"
|
||||
android:bottom="2dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="22dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#F5F5F5"
|
||||
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners android:radius="16dp" />
|
||||
<stroke android:width="1dp" android:color="#f0f0f0" />
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<stroke android:width="1dp" android:color="#e0e0e0" />
|
||||
<corners android:radius="4dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f8f9fa" />
|
||||
<corners android:radius="20dp" />
|
||||
<stroke android:width="1dp" android:color="#e9ecef" />
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#fff2f2" />
|
||||
<corners android:radius="20dp" />
|
||||
<stroke android:width="1dp" android:color="#ff6b35" />
|
||||
</shape>
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:startColor="#E3F2FD"
|
||||
android:endColor="#BBDEFB"
|
||||
android:angle="90"/>
|
||||
</shape>
|
||||
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z M12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M12,6c-3.31,0 -6,2.69 -6,6s2.69,6 6,6 6,-2.69 6,-6 -2.69,-6 -6,-6z M12,16c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M12,9.5c-1.38,0 -2.5,1.12 -2.5,2.5s1.12,2.5 2.5,2.5 2.5,-1.12 2.5,-2.5 -1.12,-2.5 -2.5,-2.5z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="@color/white">
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||
|
||||
</vector>
|
||||
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:strokeColor="#FF666666"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="@android:color/transparent"
|
||||
android:pathData="M9,6l6,6l-6,6"/>
|
||||
</vector>
|
||||
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z M12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12.5,7H11v6l5.25,3.15l0.75,-1.23l-4.5,-2.67z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M7,12.5h10v-1H7z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M20,6h-2.18c0.11,-0.31 0.18,-0.65 0.18,-1c0,-1.66 -1.34,-3 -3,-3c-1.05,0 -1.96,0.54 -2.5,1.35C12.96,2.54 12.05,2 11,2C9.34,2 8,3.34 8,5c0,0.35 0.07,0.69 0.18,1H4c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2V8C22,6.89 21.11,6 20,6z M15,4c0.55,0 1,0.45 1,1s-0.45,1 -1,1s-1,-0.45 -1,-1S14.45,4 15,4z M11,4c0.55,0 1,0.45 1,1s-0.45,1 -1,1s-1,-0.45 -1,-1S10.45,4 11,4z M4,19v-6h6v6H4z M14,19v-6h6v6H14z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF757575"
|
||||
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF4CAF50"
|
||||
android:pathData="M20,2H4C2.9,2 2,2.9 2,4v12c0,1.1 0.9,2 2,2h4v3c0,0.55 0.45,1 1,1h0.5c0.25,0 0.49,-0.09 0.67,-0.26L13.9,18H20c1.1,0 2,-0.9 2,-2V4C22,2.9 21.1,2 20,2z M20,16h-6.09c-0.18,0 -0.35,0.06 -0.49,0.17l-1.42,1.42V16H4V4h16V16z"/>
|
||||
<path
|
||||
android:fillColor="#FF4CAF50"
|
||||
android:pathData="M11,11h2v2h-2z M11,7h2v2h-2z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z M12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M11,16h2v2h-2z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5C16,7.79 14.21,6 12,6z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M16,11c1.66,0 2.99,-1.34 2.99,-3S17.66,5 16,5c-1.66,0 -3,1.34 -3,3S14.34,11 16,11z M8,11c1.66,0 2.99,-1.34 2.99,-3S9.66,5 8,5C6.34,5 5,6.34 5,8S6.34,11 8,11z M8,13c-2.33,0 -7,1.17 -7,3.5V19h14v-2.5C15,14.17 10.33,13 8,13z M16,13c-0.29,0 -0.62,0.02 -0.97,0.05c1.16,0.84 1.97,1.97 1.97,3.45V19h6v-2.5C23,14.17 18.33,13 16,13z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M20,2H4C2.9,2 2,2.9 2,4v12c0,1.1 0.9,2 2,2h4v-2H4V4h16v12h-4v2h4c1.1,0 2,-0.9 2,-2V4C22,2.9 21.1,2 20,2z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M17,7l-1.41,1.41L18.17,11H8v2h10.17l-2.58,2.58L17,17l5,-5L17,7z M4,5h8V3H4C2.9,3 2,3.9 2,5v14c0,1.1 0.9,2 2,2h8v-2H4V5z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M6,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z M18,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z M12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M19,3H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3zM19,19H5V5h14V19z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M8.5,15H6.5l4,-7 4,7h-2l-1.5,-2.5L8.5,15z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M17,12.5h-4V11h4V12.5z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="12dp"
|
||||
android:height="12dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF5000"
|
||||
android:pathData="M12,2L4,5v6.09c0,5.05 3.41,9.76 8,10.91c4.59,-1.15 8,-5.86 8,-10.91V5L12,2z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22z M18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1L18,16z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M15,9H9v2h1v3h4v-3h1V9z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#BDBDBD"
|
||||
android:pathData="M19,5v14H5V5h14m0-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||
<path
|
||||
android:fillColor="#BDBDBD"
|
||||
android:pathData="M12,12c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM14,16v2h-4v-2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M13,3c-4.97,0 -9,4.03 -9,9H1l3.89,3.89l0.07,0.14L9,12H6c0,-3.87 3.13,-7 7,-7s7,3.13 7,7s-3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9z"/>
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,8v5l4.25,2.52l0.77,-1.28l-3.52,-2.09V8z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,39 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M3,11h8V3H3V11zM5,5h4v4H5V5z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M3,21h8v-8H3V21zM5,15h4v4H5V15z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M13,3v8h8V3H13zM19,9h-4V5h4V9z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M21,19h-2v2h2V19z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M13,13h2v2h-2V13z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M15,15h2v2h-2V15z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M13,17h2v2h-2V17z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M15,19h2v2h-2V19z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M17,17h2v2h-2V17z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M19,15h2v2h-2V15z"/>
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M17,13h2v2h-2V13z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF666666"
|
||||
android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.82,11.69 4.82,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#2196F3"
|
||||
android:pathData="M19,6h-2c0,-2.8 -2.2,-5 -5,-5S7,3.2 7,6H5C3.9,6 3,6.9 3,8v12c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V8C21,6.9 20.1,6 19,6z M12,3c1.7,0 3,1.3 3,3H9C9,4.3 10.3,3 12,3z M19,20H5V8h2v2c0,0.6 0.4,1 1,1s1,-0.4 1,-1V8h6v2c0,0.6 0.4,1 1,1s1,-0.4 1,-1V8h2V20z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFE44D"
|
||||
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21z"/>
|
||||
</vector>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#F5F5F5"/>
|
||||
<corners android:radius="8dp"/>
|
||||
<stroke android:width="1dp" android:color="#E3F2FD"/>
|
||||
</shape>
|
||||
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="12dp" />
|
||||
|
||||
<!-- 银白色渐变 -->
|
||||
<gradient
|
||||
android:type="linear"
|
||||
android:startColor="#FFE8E8E8"
|
||||
android:centerColor="#FFD6D6D6"
|
||||
android:endColor="#FFC0C0C0"
|
||||
android:angle="45" />
|
||||
|
||||
<stroke
|
||||
android:width="0.8dp"
|
||||
android:color="#FFA0A0A0" />
|
||||
|
||||
<padding
|
||||
android:left="8dp"
|
||||
android:top="2dp"
|
||||
android:right="8dp"
|
||||
android:bottom="2dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#2196F3" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners android:radius="@dimen/product_card_corner_radius" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#E3F2FD" />
|
||||
</shape>
|
||||
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- 阴影 -->
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#E3F2FD" />
|
||||
<corners android:radius="@dimen/product_card_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
<!-- 内容 -->
|
||||
<item android:top="2dp" android:bottom="2dp" android:left="2dp" android:right="2dp">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners android:radius="@dimen/product_card_corner_radius" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#BBDEFB" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners android:radius="25dp" />
|
||||
|
||||
<!-- 渐变背景 -->
|
||||
<gradient
|
||||
android:type="linear"
|
||||
android:startColor="#FFFFFF"
|
||||
android:endColor="#F8F9FA"
|
||||
android:angle="90" />
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#E0E0E0" />
|
||||
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#FFFFFF"/>
|
||||
<corners android:radius="24dp"/>
|
||||
<stroke android:width="1dp" android:color="#E3F2FD"/>
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#FFFFFF"/>
|
||||
<corners android:radius="18dp"/>
|
||||
<stroke android:width="1dp" android:color="#E0E0E0"/>
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#E3F2FD"/>
|
||||
<corners android:radius="18dp"/>
|
||||
<stroke android:width="1dp" android:color="#2196F3"/>
|
||||
</shape>
|
||||
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<!-- 圆角 -->
|
||||
<corners android:radius="16dp" />
|
||||
|
||||
<!-- 背景色 - 白色 -->
|
||||
<solid android:color="@color/white" />
|
||||
|
||||
<!-- 灰色边框 -->
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/gray_300" />
|
||||
|
||||
<!-- 内边距 -->
|
||||
<padding
|
||||
android:left="8dp"
|
||||
android:top="4dp"
|
||||
android:right="8dp"
|
||||
android:bottom="4dp" />
|
||||
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f5f5f5" />
|
||||
<stroke android:width="1dp" android:color="#e0e0e0" />
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners android:radius="16dp" />
|
||||
|
||||
<!-- 渐变背景 -->
|
||||
<gradient
|
||||
android:type="linear"
|
||||
android:startColor="@color/primary_blue_light"
|
||||
android:endColor="@color/primary_blue"
|
||||
android:angle="90" />
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/primary_blue_dark" />
|
||||
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#fff2f2" />
|
||||
<stroke android:width="1dp" android:color="#ff6b35" />
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#E3F2FD"/>
|
||||
<corners android:radius="10dp"/>
|
||||
</shape>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#E3F2FD" />
|
||||
<corners android:radius="6dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#2196F3" />
|
||||
</shape>
|
||||
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="#f5f5f5">
|
||||
|
||||
<!-- 标题栏 -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:background="@android:color/white"
|
||||
android:elevation="2dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivBack"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@android:drawable/ic_menu_close_clear_cancel"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="16dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="聊天"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_centerInParent="true" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- 聊天消息列表 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvChatMessages"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<!-- 输入框区域 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/white"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp"
|
||||
android:elevation="4dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etMessage"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_chat_input"
|
||||
android:hint="输入消息..."
|
||||
android:maxLines="3"
|
||||
android:padding="12dp"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnSend"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:src="@android:drawable/ic_menu_send"
|
||||
android:layout_marginStart="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
@ -0,0 +1,457 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@drawable/dialog_background"
|
||||
android:padding="0dp">
|
||||
|
||||
<!-- 标题栏 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="20dp"
|
||||
android:background="#fafafa">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="筛选"
|
||||
android:textColor="#333333"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn_reset"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="重置"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:padding="8dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="400dp"
|
||||
android:padding="20dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 价格筛选 -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="价格区间"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="24dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_min_price"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:hint="最低价"
|
||||
android:inputType="numberDecimal"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="至"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:paddingHorizontal="12dp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_max_price"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:hint="最高价"
|
||||
android:inputType="numberDecimal"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 商品类别 -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="商品类别"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/category_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="24dp">
|
||||
|
||||
<!-- 第一行类别 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category_digital"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:text="数码产品"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category_clothing"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:text="服装鞋帽"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category_home"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="家居日用"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 第二行类别 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category_books"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:text="图书文具"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category_beauty"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:text="美妆个护"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category_sports"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="运动户外"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 第三行类别 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category_other"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:text="其他"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<!-- 占位空间,保持布局平衡 -->
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 区域筛选 -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="区域"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="32dp">
|
||||
|
||||
<!-- 第一行区域 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_beijing"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:text="北京"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_shanghai"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:text="上海"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_guangzhou"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="广州"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 第二行区域 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_shenzhen"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:text="深圳"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_hangzhou"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:text="杭州"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_chengdu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="成都"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 第三行区域 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_wuhan"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:text="武汉"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_other"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:text="其他"
|
||||
android:textColor="#666666"
|
||||
android:textSize="13sp"
|
||||
android:background="@drawable/filter_tag_normal"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<!-- 占位空间,保持布局平衡 -->
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#f0f0f0" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_cancel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="取消"
|
||||
android:textColor="#666666"
|
||||
android:textSize="16sp"
|
||||
android:background="@drawable/button_secondary" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_confirm"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="确定"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:background="@drawable/button_primary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@android:color/white"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="选择区域"
|
||||
android:textColor="#333333"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_all"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="全区域"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#f0f0f0"
|
||||
android:layout_marginVertical="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_beijing"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="北京"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_shanghai"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="上海"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_guangzhou"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="广州"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_shenzhen"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="深圳"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_hangzhou"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="杭州"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_chengdu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="成都"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_wuhan"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="武汉"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/region_other"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="其他"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:padding="12dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
</LinearLayout>
|
||||
@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
android:background="#f5f5f5">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 商品图片 -->
|
||||
<ImageView
|
||||
android:id="@+id/ivItemImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:background="@drawable/bg_image_border"
|
||||
android:src="@mipmap/ic_launcher" />
|
||||
|
||||
<!-- 商品基本信息 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@android:color/white"
|
||||
android:padding="16dp"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="商品标题"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPrice"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="¥0.00"
|
||||
android:textColor="#ff4444"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginTop="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 商品详情 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@android:color/white"
|
||||
android:padding="16dp"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="商品详情"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDescription"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="商品描述"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:lineSpacingExtra="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 商品信息 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@android:color/white"
|
||||
android:padding="16dp"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="商品信息"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvCategory"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="分类:"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginTop="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLocation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="位置:"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvContact"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="联系方式:"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPublishTime"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="发布时间:"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 联系卖家按钮 -->
|
||||
<Button
|
||||
android:id="@+id/btnContact"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:text="联系卖家"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:background="@drawable/button_blue"
|
||||
android:textColor="@android:color/white"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
android:background="#f5f5f5">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 图片上传区域 -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="上传图片"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<GridView
|
||||
android:id="@+id/gridViewImages"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:numColumns="3"
|
||||
android:verticalSpacing="8dp"
|
||||
android:horizontalSpacing="8dp"
|
||||
android:stretchMode="columnWidth"
|
||||
android:background="@drawable/bg_edittext"
|
||||
android:padding="8dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="最多可上传9张图片"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#666"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- 商品信息区域 -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="商品信息"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="商品标题"
|
||||
android:maxLines="1"
|
||||
android:background="@drawable/bg_edittext"
|
||||
android:padding="12dp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etDescription"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:hint="商品描述"
|
||||
android:gravity="top"
|
||||
android:maxLines="5"
|
||||
android:background="@drawable/bg_edittext"
|
||||
android:padding="12dp"
|
||||
android:layout_marginTop="8dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etPrice"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="价格"
|
||||
android:inputType="numberDecimal"
|
||||
android:background="@drawable/bg_edittext"
|
||||
android:padding="12dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="元"
|
||||
android:textSize="14sp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 分类和位置 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerCategory"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_edittext"
|
||||
android:padding="8dp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerLocation"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="@drawable/bg_edittext"
|
||||
android:padding="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<EditText
|
||||
android:id="@+id/etContact"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="联系方式(微信/电话)"
|
||||
android:maxLines="1"
|
||||
android:background="@drawable/bg_edittext"
|
||||
android:padding="12dp"
|
||||
android:layout_marginTop="8dp" />
|
||||
|
||||
<!-- 发布按钮 -->
|
||||
<Button
|
||||
android:id="@+id/btnPublish"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:text="发布商品"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:background="@drawable/button_blue"
|
||||
android:textColor="@android:color/white"
|
||||
android:layout_marginTop="24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<!-- 对方消息(左侧) -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutLeft"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingEnd="48dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_chat_message_left"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLeftMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="对方消息"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLeftTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="时间"
|
||||
android:textColor="#999999"
|
||||
android:textSize="10sp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginStart="12dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 自己消息(右侧) -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutRight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_gravity="end"
|
||||
android:paddingStart="48dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_chat_message_right"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvRightMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="我的消息"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvRightTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="时间"
|
||||
android:textColor="#999999"
|
||||
android:textSize="10sp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginEnd="12dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:padding="2dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:background="@drawable/bg_image_border" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/btnDelete"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:src="@android:drawable/ic_delete"
|
||||
android:background="@drawable/bg_delete_button" />
|
||||
|
||||
</RelativeLayout>
|
||||
@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="72dp"
|
||||
android:background="@android:color/white"
|
||||
android:padding="12dp">
|
||||
|
||||
<!-- 白色头像占位 -->
|
||||
<ImageView
|
||||
android:id="@+id/ivAvatar"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/bg_avatar_placeholder" />
|
||||
|
||||
<!-- 官方标识 -->
|
||||
<ImageView
|
||||
android:id="@+id/ivOfficial"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:src="@drawable/ic_official"
|
||||
android:layout_alignTop="@id/ivAvatar"
|
||||
android:layout_alignEnd="@id/ivAvatar" />
|
||||
|
||||
<!-- 标题 -->
|
||||
<TextView
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="标题"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_toEndOf="@id/ivAvatar"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_alignTop="@id/ivAvatar" />
|
||||
|
||||
<!-- 内容 -->
|
||||
<TextView
|
||||
android:id="@+id/tvContent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="内容"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#666666"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:layout_toEndOf="@id/ivAvatar"
|
||||
android:layout_below="@id/tvTitle"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
<!-- 时间 -->
|
||||
<TextView
|
||||
android:id="@+id/tvTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="时间"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#999999"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignTop="@id/tvTitle" />
|
||||
|
||||
<!-- 未读消息计数 -->
|
||||
<TextView
|
||||
android:id="@+id/tvUnreadCount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="18dp"
|
||||
android:background="@drawable/bg_unread_count"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="10sp"
|
||||
android:gravity="center"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@id/tvTime"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
</RelativeLayout>
|
||||
@ -0,0 +1,2 @@
|
||||
'vac' 不是内部或外部命令,也不是可运行的程序
|
||||
或批处理文件。
|
||||
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>secondhand-market</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>SecondHandMarket</name>
|
||||
<description>二手市场后端应用</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.7.15</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Boot 核心依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Data JPA -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MySQL 驱动 -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- H2 内存数据库 (用于开发测试) -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot 测试 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Security 测试 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Lombok (简化实体类编写) -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- 用于密码加密的 BCrypt -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-crypto</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>central</id>
|
||||
<url>https://repo1.maven.org/maven2/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>central</id>
|
||||
<url>https://repo1.maven.org/maven2/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</project>
|
||||
@ -0,0 +1,13 @@
|
||||
package com.example.secondhandmarket;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SecondHandMarketApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SecondHandMarketApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.example.secondhandmarket.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Configuration
|
||||
public class CorsConfig {
|
||||
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
CorsConfiguration corsConfig = new CorsConfiguration();
|
||||
|
||||
// 允许所有来源
|
||||
corsConfig.setAllowedOrigins(Arrays.asList("*"));
|
||||
|
||||
// 允许所有HTTP方法
|
||||
corsConfig.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
|
||||
|
||||
// 允许的请求头
|
||||
corsConfig.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept", "Authorization", "X-Requested-With"));
|
||||
|
||||
// 允许暴露的响应头
|
||||
corsConfig.setExposedHeaders(Arrays.asList("Content-Length", "Content-Type", "X-Total-Count"));
|
||||
|
||||
// 允许携带认证信息
|
||||
corsConfig.setAllowCredentials(true);
|
||||
|
||||
// 预检请求的缓存时间
|
||||
corsConfig.setMaxAge(3600L);
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", corsConfig);
|
||||
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.example.secondhandmarket.config;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ControllerAdvice
|
||||
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
|
||||
|
||||
// 处理一般运行时异常
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public ResponseEntity<?> handleRuntimeException(RuntimeException ex, WebRequest request) {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("error", ex.getMessage());
|
||||
body.put("status", HttpStatus.BAD_REQUEST.value());
|
||||
|
||||
return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 处理空指针异常
|
||||
@ExceptionHandler(NullPointerException.class)
|
||||
public ResponseEntity<?> handleNullPointerException(NullPointerException ex, WebRequest request) {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("error", "请求处理时发生错误,请稍后再试");
|
||||
body.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
|
||||
return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
// 处理异常的通用方法
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<?> handleGenericException(Exception ex, WebRequest request) {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("error", "服务器内部错误");
|
||||
body.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
|
||||
// 记录异常日志
|
||||
ex.printStackTrace();
|
||||
|
||||
return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package com.example.secondhandmarket.controller;
|
||||
|
||||
import com.example.secondhandmarket.model.entity.ChatMessage;
|
||||
import com.example.secondhandmarket.service.ChatMessageService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/messages")
|
||||
public class ChatMessageController {
|
||||
|
||||
@Autowired
|
||||
private ChatMessageService chatMessageService;
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<?> sendMessage(@RequestBody ChatMessage message) {
|
||||
try {
|
||||
ChatMessage sentMessage = chatMessageService.sendMessage(message);
|
||||
return ResponseEntity.ok(sentMessage);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/conversation/{userId1}/{userId2}")
|
||||
public ResponseEntity<?> getConversation(
|
||||
@PathVariable Long userId1,
|
||||
@PathVariable Long userId2) {
|
||||
List<ChatMessage> messages = chatMessageService.getConversationBetweenUsers(userId1, userId2);
|
||||
// 标记消息为已读
|
||||
chatMessageService.markAllAsRead(userId2, userId1);
|
||||
return ResponseEntity.ok(messages);
|
||||
}
|
||||
|
||||
@GetMapping("/unread/{userId}")
|
||||
public ResponseEntity<?> getUnreadMessages(@PathVariable Long userId) {
|
||||
List<ChatMessage> unreadMessages = chatMessageService.getUnreadMessagesByUserId(userId);
|
||||
return ResponseEntity.ok(unreadMessages);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}/read")
|
||||
public ResponseEntity<?> markAsRead(@PathVariable Long id) {
|
||||
try {
|
||||
chatMessageService.markAsRead(id);
|
||||
return ResponseEntity.ok(Map.of("message", "消息已标记为已读"));
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@PutMapping("/read-all/{userId}/{senderId}")
|
||||
public ResponseEntity<?> markAllAsRead(
|
||||
@PathVariable Long userId,
|
||||
@PathVariable Long senderId) {
|
||||
try {
|
||||
chatMessageService.markAllAsRead(userId, senderId);
|
||||
return ResponseEntity.ok(Map.of("message", "所有消息已标记为已读"));
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/conversations/{userId}")
|
||||
public ResponseEntity<?> getUserConversations(@PathVariable Long userId) {
|
||||
List<Long> conversationUserIds = chatMessageService.getUserConversations(userId);
|
||||
return ResponseEntity.ok(conversationUserIds);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,132 @@
|
||||
package com.example.secondhandmarket.controller;
|
||||
|
||||
import com.example.secondhandmarket.model.entity.Item;
|
||||
import com.example.secondhandmarket.service.ItemService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/items")
|
||||
public class ItemController {
|
||||
|
||||
@Autowired
|
||||
private ItemService itemService;
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<?> createItem(@RequestBody Item item) {
|
||||
try {
|
||||
Item createdItem = itemService.createItem(item);
|
||||
return ResponseEntity.ok(createdItem);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<?> getItemById(@PathVariable Long id) {
|
||||
// 增加浏览次数
|
||||
itemService.incrementViewCount(id);
|
||||
|
||||
return itemService.findById(id)
|
||||
.map(item -> ResponseEntity.ok(item))
|
||||
.orElseGet(() -> ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<?> getAllItems(
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "10") int size) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
Page<Item> items = itemService.findAllAvailable(pageable);
|
||||
return ResponseEntity.ok(items);
|
||||
}
|
||||
|
||||
@GetMapping("/category/{category}")
|
||||
public ResponseEntity<?> getItemsByCategory(
|
||||
@PathVariable String category,
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "10") int size) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
Page<Item> items = itemService.findByCategory(category, pageable);
|
||||
return ResponseEntity.ok(items);
|
||||
}
|
||||
|
||||
@GetMapping("/seller/{sellerId}")
|
||||
public ResponseEntity<?> getItemsBySeller(
|
||||
@PathVariable Long sellerId,
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "10") int size) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
Page<Item> items = itemService.findBySeller(sellerId, pageable);
|
||||
return ResponseEntity.ok(items);
|
||||
}
|
||||
|
||||
@GetMapping("/search")
|
||||
public ResponseEntity<?> searchItems(
|
||||
@RequestParam String keyword,
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "10") int size) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
Page<Item> items = itemService.searchItems(keyword, pageable);
|
||||
return ResponseEntity.ok(items);
|
||||
}
|
||||
|
||||
@GetMapping("/price-range")
|
||||
public ResponseEntity<?> getItemsByPriceRange(
|
||||
@RequestParam Double minPrice,
|
||||
@RequestParam Double maxPrice,
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "10") int size) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
Page<Item> items = itemService.findByPriceRange(minPrice, maxPrice, pageable);
|
||||
return ResponseEntity.ok(items);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<?> updateItem(@PathVariable Long id, @RequestBody Item item) {
|
||||
try {
|
||||
item.setId(id);
|
||||
Item updatedItem = itemService.updateItem(item);
|
||||
return ResponseEntity.ok(updatedItem);
|
||||
} catch (RuntimeException e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<?> deleteItem(@PathVariable Long id) {
|
||||
try {
|
||||
itemService.deleteItem(id);
|
||||
return ResponseEntity.ok(Map.of("message", "商品删除成功"));
|
||||
} catch (RuntimeException e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@PutMapping("/{id}/status")
|
||||
public ResponseEntity<?> changeItemStatus(@PathVariable Long id, @RequestBody Map<String, String> statusMap) {
|
||||
try {
|
||||
String status = statusMap.get("status");
|
||||
itemService.changeStatus(id, status);
|
||||
return ResponseEntity.ok(Map.of("message", "状态更新成功"));
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/{id}/like")
|
||||
public ResponseEntity<?> likeItem(@PathVariable Long id) {
|
||||
try {
|
||||
itemService.incrementLikeCount(id);
|
||||
return ResponseEntity.ok(Map.of("message", "点赞成功"));
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package com.example.secondhandmarket.controller;
|
||||
|
||||
import com.example.secondhandmarket.model.entity.User;
|
||||
import com.example.secondhandmarket.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/users")
|
||||
public class UserController {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@PostMapping("/register")
|
||||
public ResponseEntity<?> register(@RequestBody User user) {
|
||||
try {
|
||||
User registeredUser = userService.register(user);
|
||||
return ResponseEntity.ok(registeredUser);
|
||||
} catch (RuntimeException e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<?> login(@RequestBody Map<String, String> credentials) {
|
||||
String phone = credentials.get("phone");
|
||||
String password = credentials.get("password");
|
||||
|
||||
return userService.login(phone, password)
|
||||
.map(user -> ResponseEntity.ok(user))
|
||||
.orElseGet(() -> ResponseEntity.badRequest().body(Map.of("error", "手机号或密码错误")));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<?> getUserById(@PathVariable Long id) {
|
||||
return userService.findById(id)
|
||||
.map(user -> ResponseEntity.ok(user))
|
||||
.orElseGet(() -> ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<?> updateUser(@PathVariable Long id, @RequestBody User user) {
|
||||
try {
|
||||
user.setId(id);
|
||||
User updatedUser = userService.update(user);
|
||||
return ResponseEntity.ok(updatedUser);
|
||||
} catch (RuntimeException e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/exists/phone/{phone}")
|
||||
public ResponseEntity<?> checkPhoneExists(@PathVariable String phone) {
|
||||
return ResponseEntity.ok(Map.of("exists", userService.existsByPhone(phone)));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.example.secondhandmarket.model.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import javax.persistence.*;
|
||||
import java.util.Date;
|
||||
|
||||
@Entity
|
||||
@Table(name = "chat_messages")
|
||||
@Data
|
||||
public class ChatMessage {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "sender_id", nullable = false)
|
||||
private User sender;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "receiver_id", nullable = false)
|
||||
private User receiver;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "item_id")
|
||||
private Item item;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "TEXT")
|
||||
private String content;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Date time;
|
||||
|
||||
private boolean read = false;
|
||||
private String type = "text";
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue