京东筛选更新了,很好,很炫酷。那什么,我们也不差是吧,于是就有了这个demo。话不多说,先看图,不想看代码的朋友,直接点底部下demo。
图1里面呢,就两点,弹出的PopupWindow的高度为屏幕高的一半,另一半为半透明高端黑,简单点就用weight属性来写,方便快捷。然后在上半部分写个GridView,在GridView的底部有个LinearLayout,用来放俩Button,但是Button比较难处理布局,本着高仿的原则,我还是用的TextView。哈哈,机智如我。
先来看看这个PopupWindow的布局吧:
<?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:background="#33000000"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#ffffff"
android:orientation="vertical">
<GridView
android:id="@+id/grid"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="14dp"
android:layout_weight="1"
android:horizontalSpacing="14dp"
android:numColumns="3"
android:verticalSpacing="14dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#cccccc" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="48dp">
<TextView
android:id="@+id/reset"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="重置" />
<TextView
android:id="@+id/ok"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#ff0033"
android:gravity="center"
android:text="确定"
android:textColor="#ffffff" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
布局简单吧,反正我是没怎么费脑筋就给搞出来的。下面来看看PopupWindow的代码:
package lx.com.filter.view;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import lx.com.filter.R;
import lx.com.filter.adapter.PopupAdapter;
import lx.com.filter.vo.Vo;
public class PricePopup extends PopupWindow {
private View contentView;
private GridView grid;
private TextView reset;
private TextView ok;
private PopupAdapter adapter;
private List<Vo> data;
public PricePopup(final Activity context, final List<Vo> data) {
this.data = data;
adapter = new PopupAdapter(context);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
contentView = inflater.inflate(R.layout.popup, null);
grid = (GridView) contentView.findViewById(R.id.grid);
reset = (TextView) contentView.findViewById(R.id.reset);
ok = (TextView) contentView.findViewById(R.id.ok);
grid.setAdapter(adapter);
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
data.get(position).setChecked(!data.get(position).isChecked());
for (int i = 0; i < data.size(); i++) {
if (i == position) {
continue;
}
data.get(i).setChecked(false);
}
Toast.makeText(context, data.get(position).getStr2(), Toast.LENGTH_SHORT).show();
adapter.notifyDataSetChanged(data);
}
});
int h = context.getWindowManager().getDefaultDisplay().getHeight();
int w = context.getWindowManager().getDefaultDisplay().getWidth();
this.setContentView(contentView);
this.setWidth(w);
this.setHeight(h);
ColorDrawable dw = new ColorDrawable(00000000);
this.setBackgroundDrawable(dw);
this.setFocusable(true);
this.setOutsideTouchable(false);
this.update();
}
public void showPricePopup(View parent, final List<Vo> data) {
if (!this.isShowing()) {
this.showAsDropDown(parent);
adapter.notifyDataSetChanged(data);
} else {
this.dismiss();
}
}
}
Adapter就不放了,demo里面有的。接下来,图2里面的就比较复杂了。还是先看布局吧:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_popup"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<View
android:id="@+id/popup_goods_noview"
android:layout_width="48dp"
android:layout_height="match_parent"
android:background="#88000000" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/filter_layout"
android:orientation="vertical"
android:padding="14dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="服务" />
<GridView
android:id="@+id/yuguo_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="14dp"
android:horizontalSpacing="14dp"
android:numColumns="3"
android:verticalSpacing="14dp"></GridView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="14dp"
android:text="价格区间" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="14dp"
android:layout_marginTop="14dp"
android:orientation="horizontal">
<EditText
android:layout_width="0dp"
android:layout_height="36dp"
android:layout_weight="1"
android:background="@drawable/edittext_shape"
android:digits="0123456789"
android:gravity="center"
android:hint="最低价"
android:inputType="number" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="---" />
<EditText
android:layout_width="0dp"
android:layout_height="36dp"
android:layout_weight="1"
android:background="@drawable/edittext_shape"
android:digits="0123456789"
android:gravity="center"
android:hint="最高价"
android:inputType="number" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/selection_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@null"
android:dividerHeight="14dp"
android:orientation="vertical"
android:scrollbars="none" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/filter_layout"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:background="#ffffff"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#cccccc" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/filter_reset"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="重置" />
<TextView
android:id="@+id/filter_sure"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#ff0033"
android:gravity="center"
android:text="确定"
android:textColor="#ffffff" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
PopupWindow代码:
package lx.com.filter.view;
import android.app.ActionBar.LayoutParams;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import lx.com.filter.R;
import lx.com.filter.adapter.GoodsAttrListAdapter;
import lx.com.filter.adapter.GoodsAttrsAdapter;
import lx.com.filter.vo.SaleAttributeNameVo;
import lx.com.filter.vo.SaleAttributeVo;
/**
* 筛选商品属性选择的popupwindow
*/
public class FilterPopupWindow extends PopupWindow {
private View contentView;
private Context context;
private View goodsNoView;
private GridView serviceGrid;
private ListView selectionList;
private TextView filterReset;
private TextView filterSure;
private GoodsAttrListAdapter adapter;
private GoodsAttrsAdapter serviceAdapter;
private List<SaleAttributeNameVo> itemData;
private List<SaleAttributeVo> serviceList;
private String[] serviceStr = new String[]{"仅看有货", "促销", "手机专享"};
/**
* 商品属性选择的popupwindow
*/
public FilterPopupWindow(final Activity context) {
this.context = context;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
contentView = inflater.inflate(R.layout.popup_goods_details, null);
goodsNoView = contentView.findViewById(R.id.popup_goods_noview);
serviceGrid = (GridView) contentView.findViewById(R.id.yuguo_service);
selectionList = (ListView) contentView.findViewById(R.id.selection_list);
filterReset = (TextView) contentView.findViewById(R.id.filter_reset);
filterSure = (TextView) contentView.findViewById(R.id.filter_sure);
goodsNoView.setOnClickListener(new CancelOnClickListener());
contentView.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK) {
dismiss();
}
return true;
}
});
serviceList = new ArrayList<SaleAttributeVo>();
for (int i = 0; i < serviceStr.length; i++) {
SaleAttributeVo vo = new SaleAttributeVo();
vo.setValue(serviceStr[i]);
serviceList.add(vo);
}
serviceAdapter = new GoodsAttrsAdapter(context);
serviceGrid.setAdapter(serviceAdapter);
serviceAdapter.notifyDataSetChanged(true, serviceList);
serviceGrid.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
//设置当前选中的位置的状态为非。
serviceList.get(arg2).setChecked(!serviceList.get(arg2).isChecked());
for (int i = 0; i < serviceList.size(); i++) {
//跳过已设置的选中的位置的状态
if (i == arg2) {
continue;
}
serviceList.get(i).setChecked(false);
}
serviceAdapter.notifyDataSetChanged(true, serviceList);
}
});
itemData = new ArrayList<SaleAttributeNameVo>();
adapter = new GoodsAttrListAdapter(context, itemData);
selectionList.setAdapter(adapter);
String str = "["
+ "{\"nameId\":\"V2QASD\",\"saleVo\":["
+ "{\"value\":\"2核\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"1\"},"
+ "{\"value\":\"4核\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"6核\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"8核\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"}"
+ "],\"name\":\"CPU\"},"
+ "{\"nameId\":\"V2QASD\",\"saleVo\":["
+ "{\"value\":\"全网通\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"移动4G\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"1\"},"
+ "{\"value\":\"电信4G\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"联通4G\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"}"
+ "],\"name\":\"网络制式\"},"
+ "{\"nameId\":\"V2QASD\",\"saleVo\":["
+ "{\"value\":\"OPPO\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"荣耀\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"苹果\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"1\"},"
+ "{\"value\":\"鸭梨\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"月饼\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"vivo\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"}"
+ "],\"name\":\"品牌\"},"
+ "{\"nameId\":\"V2QASD\",\"saleVo\":["
+ "{\"value\":\"音乐\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"1\"},"
+ "{\"value\":\"拍照\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"待机长\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"}"
+ "],\"name\":\"主打\"},"
+ "{\"nameId\":\"V2QLAH\",\"saleVo\":["
+ "{\"value\":\"4.5英寸\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"5英寸\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"5.5英寸\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"0\"},"
+ "{\"value\":\"6英寸\",\"goods\":null,\"goodsAndValId\":\"C6VOWQ\",\"checkStatus\":\"1\"}"
+ "],\"name\":\"尺寸\"}" + "]";
JSONArray json = null;
try {
json = new JSONArray(str);
refreshAttrs(json);
} catch (JSONException e) {
e.printStackTrace();
}
// 重置的点击监听,将所有选项全设为false
filterReset.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
for (int i = 0; i < itemData.size(); i++) {
for (int j = 0; j < itemData.get(i).getSaleVo().size(); j++) {
itemData.get(i).getSaleVo().get(j).setChecked(false);
}
}
adapter.notifyDataSetChanged();
}
});
// 确定的点击监听,将所有已选中项列出
filterSure.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String str = "";
for (int i = 0; i < itemData.size(); i++) {
for (int j = 0; j < itemData.get(i).getSaleVo().size(); j++) {
if (itemData.get(i).getSaleVo().get(j).isChecked()) {
str = str + itemData.get(i).getSaleVo().get(j).getValue();
}
}
}
Toast.makeText(FilterPopupWindow.this.context, str, Toast.LENGTH_SHORT).show();
}
});
this.setContentView(contentView);
this.setWidth(LayoutParams.MATCH_PARENT);
this.setHeight(LayoutParams.MATCH_PARENT);
ColorDrawable dw = new ColorDrawable(00000000);
this.setBackgroundDrawable(dw);
this.setFocusable(true);
this.setOutsideTouchable(false);
this.update();
}
/**
* 刷新商品属性
*
* @param json
* @throws JSONException
*/
public void refreshAttrs(JSONArray json) throws JSONException {
itemData.clear();
for (int i = 0; i < json.length(); i++) {
SaleAttributeNameVo saleName = new SaleAttributeNameVo();
JSONObject obj = (JSONObject) json.opt(i);
saleName.setName(obj.getString("name"));
List<SaleAttributeVo> list = new ArrayList<SaleAttributeVo>();
net.sf.json.JSONArray array = new net.sf.json.JSONArray();
array = net.sf.json.JSONArray.fromObject(obj.getString("saleVo"));
for (int j = 0; j < array.size(); j++) {
net.sf.json.JSONObject object = array.getJSONObject(j);
SaleAttributeVo vo = new SaleAttributeVo();
vo.setGoods(object.getString("goods"));
vo.setValue(object.getString("value"));
vo.setGoodsAndValId(object.getString("goodsAndValId"));
if ("1".equals(object.getString("checkStatus"))) {
vo.setChecked(true);
} else {
vo.setChecked(false);
}
list.add(vo);
}
saleName.setSaleVo(list);
// 是否展开
saleName.setNameIsChecked(false);
itemData.add(saleName);
}
adapter.notifyDataSetChanged();
}
public class CancelOnClickListener implements OnClickListener {
@Override
public void onClick(View v) {
dismiss();
}
}
public boolean onKeyDown(Context context, int keyCode, KeyEvent event) {
this.context = context;
if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK) {
dismiss();
}
return true;
}
public void showFilterPopup(View parent) {
if (!this.isShowing()) {
this.showAsDropDown(parent);
} else {
this.dismiss();
}
}
}
额,好像代码有点长,没办法,东西有这么多的。看Adapter吧:
package lx.com.filter.adapter;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
import lx.com.filter.R;
import lx.com.filter.vo.SaleAttributeNameVo;
/**
* 属性listview的适配器
*/
public class GoodsAttrListAdapter extends BaseAdapter {
private Context context;
private List<SaleAttributeNameVo> data;
public GoodsAttrListAdapter(Context context, List<SaleAttributeNameVo> data) {
this.context = context;
this.data = data;
}
public int getCount() {
return data == null ? 0 : data.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(final int position, View v, ViewGroup parent) {
final MyView myView;
if (v == null) {
myView = new MyView();
v = View.inflate(context, R.layout.item_goods_attr_list, null);
myView.name = (TextView) v.findViewById(R.id.attr_list_name);
myView.img = (ImageView) v.findViewById(R.id.attr_list_img);
myView.grid = (GridView) v.findViewById(R.id.attr_list_grid);
myView.grid.setSelector(new ColorDrawable(Color.TRANSPARENT));
v.setTag(myView);
} else {
myView = (MyView) v.getTag();
}
myView.name.setText(data.get(position).getName());
final GoodsAttrsAdapter adapter = new GoodsAttrsAdapter(context);
myView.grid.setAdapter(adapter);
adapter.notifyDataSetChanged(data.get(position).isNameIsChecked(), data.get(position).getSaleVo());
myView.img.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (data.get(position).isNameIsChecked()) {
((ImageView) v).setImageResource(R.drawable.sort_common_up);
} else {
((ImageView) v).setImageResource(R.drawable.sort_common_down);
}
adapter.notifyDataSetChanged(data.get(position).isNameIsChecked(), data.get(position).getSaleVo());
data.get(position).setNameIsChecked(!data.get(position).isNameIsChecked());
}
});
myView.grid.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
//设置当前选中的位置的状态为非。
data.get(position).getSaleVo().get(arg2).setChecked(!data.get(position).getSaleVo().get(arg2).isChecked());
for (int i = 0; i < data.get(position).getSaleVo().size(); i++) {
//跳过已设置的选中的位置的状态
if (i == arg2) {
continue;
}
data.get(position).getSaleVo().get(i).setChecked(false);
}
if (!data.get(position).isNameIsChecked()) {
myView.img.setImageResource(R.drawable.sort_common_up);
} else {
myView.img.setImageResource(R.drawable.sort_common_down);
}
adapter.notifyDataSetChanged(!data.get(position).isNameIsChecked(), data.get(position).getSaleVo());
}
});
return v;
}
static class MyView {
public TextView name;
public ImageView img;
public GridView grid;
}
}
我把监听写这里面的。内部Adapter如下:
package lx.com.filter.adapter;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import lx.com.filter.R;
import lx.com.filter.vo.SaleAttributeVo;
/**
* 子属性GridView的适配器
*/
public class GoodsAttrsAdapter extends BaseAdapter {
private Context context;
private List<SaleAttributeVo> data = new ArrayList<SaleAttributeVo>();
public GoodsAttrsAdapter(Context context) {
this.context = context;
}
@Override
public int getCount() {
return data == null ? 0 : data.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(final int position, View v, ViewGroup parent) {
final MyView myView;
if (v == null) {
myView = new MyView();
v = View.inflate(context, R.layout.item_goods_attrs, null);
myView.attr = (TextView) v.findViewById(R.id.attr_name);
v.setTag(myView);
} else {
myView = (MyView) v.getTag();
}
myView.attr.setText(data.get(position).getValue());
/**
* 根据选中状态来设置item的背景和字体颜色
*/
if (data.get(position).isChecked()) {
myView.attr.setBackgroundResource(R.drawable.goods_attr_selected_shape);
myView.attr.setTextColor(Color.WHITE);
} else {
myView.attr.setBackgroundResource(R.drawable.goods_attr_unselected_shape);
myView.attr.setTextColor(Color.GRAY);
}
return v;
}
static class MyView {
public TextView attr;
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
public void notifyDataSetChanged(boolean isUnfold,
final List<SaleAttributeVo> tempData) {
if (tempData == null || 0 == tempData.size()) {
return;
}
data.clear();
// 如果是展开的,则加入全部data,反之则只显示3条
if (isUnfold) {
data.addAll(tempData);
} else {
data.add(tempData.get(0));
data.add(tempData.get(1));
data.add(tempData.get(2));
}
notifyDataSetChanged();
}
}
其中的isNameIsChecked()其实是因为懒,没有改名字,这个是判断是否需要子属性展开的。
好了,就酱。demo放出:
http://download.csdn.net/detail/u013806766/9579156
突然还想起个问题,之前用Android Studio没有配好Gradle,于是就用的Eclipse先写的,导出的时候选的Gradle,再用Android Studio编辑的,结果报错了,大概意思就是Gradle版本的问题,于是乎:
gradle编译时失败报错,需将 项目名称\gradle\wrapper\gradle-wrapper.properties里的
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
改为
distributionUrl=http\://services.gradle.org/distributions/gradle-2.10-all.zip
后面的数字即开发环境配置中gradle的版本
时间: 2024-10-06 09:31:54