您的位置:首页 > 编程语言 > Java开发

java poi导出execl类

2015-08-03 16:45 471 查看
这里需要用到poi的jar包。需要自行下载.

/*这个类的目的是封装了javabean导出execl*/
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;

public class ExcelUtil {
private static HSSFWorkbook wb;

private static CellStyle titleStyle; // 标题行样式
private static Font titleFont; // 标题行字体
private static CellStyle dateStyle; // 日期行样式
private static Font dateFont; // 日期行字体
private static CellStyle headStyle; // 表头行样式
private static Font headFont; // 表头行字体
private static CellStyle contentStyle; // 内容行样式
private static Font contentFont; // 内容行字体

/**
* 导出到流
*
* @param setInfo
* @return
* @throws Exception
*/
public static void export2Stream(ExcelExportData setInfo,OutputStream out)
throws Exception {
init();
Set<Entry<String, List<?>>> set = setInfo.getDataMap().entrySet();
String[] sheetNames = new String[setInfo.getDataMap().size()];
int sheetNameNum = 0;
for (Entry<String, List<?>> entry : set) {
sheetNames[sheetNameNum] = entry.getKey();
sheetNameNum++;
}
HSSFSheet[] sheets = getSheets(setInfo.getDataMap().size(), sheetNames);
int sheetNum = 0;
for (Entry<String, List<?>> entry : set) {
// Sheet
List<?> objs = entry.getValue();

// 标题行
createTableTitleRow(setInfo, sheets, sheetNum);

// 日期行
createTableDateRow(setInfo, sheets, sheetNum);

// 表头
creatTableHeadRow(setInfo, sheets, sheetNum);

// 表体
String[] fieldNames = setInfo.getFieldNames().get(sheetNum);

int rowNum = 3;
for (Object obj : objs) {
HSSFRow contentRow = sheets[sheetNum].createRow(rowNum);
contentRow.setHeight((short) 300);
HSSFCell[] cells = getCells(contentRow, setInfo.getFieldNames()
.get(sheetNum).length);
int cellNum = 1; // 去掉一列序号,因此从1开始
if (fieldNames != null) {
for (int num = 0; num < fieldNames.length; num++) {

Object value = ReflectionUtil.invokeGetterMethod(obj,
fieldNames[num]);
cells[cellNum].setCellValue(value == null ? "" : value
.toString());
cellNum++;
}
}
rowNum++;
}
adjustColumnSize(sheets, sheetNum, fieldNames); // 自动调整列宽
sheetNum++;
}
wb.write(out);
}

/**
* @Description: 初始化
*/
private static void init() {
wb = new HSSFWorkbook();

titleFont = wb.createFont();
titleStyle = wb.createCellStyle();
dateStyle = wb.createCellStyle();
dateFont = wb.createFont();
headStyle = wb.createCellStyle();
headFont = wb.createFont();
contentStyle = wb.createCellStyle();
contentFont = wb.createFont();

initTitleCellStyle();
initTitleFont();
initDateCellStyle();
initDateFont();
initHeadCellStyle();
initHeadFont();
initContentCellStyle();
initContentFont();
}

/**
* @Description: 自动调整列宽
*/
private static void adjustColumnSize(HSSFSheet[] sheets, int sheetNum,
String[] fieldNames) {
for (int i = 0; i < fieldNames.length + 1; i++) {
sheets[sheetNum].autoSizeColumn(i, true);
}
}

/**
* @Description: 创建标题行(需合并单元格)
*/
private static void createTableTitleRow(ExcelExportData setInfo,
HSSFSheet[] sheets, int sheetNum) {
CellRangeAddress titleRange = new CellRangeAddress(0, 0, 0, setInfo
.getFieldNames().get(sheetNum).length);
sheets[sheetNum].addMergedRegion(titleRange);
HSSFRow titleRow = sheets[sheetNum].createRow(0);
titleRow.setHeight((short) 800);
HSSFCell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(titleStyle);
titleCell.setCellValue(setInfo.getTitles()[sheetNum]);
}

/**
* @Description: 创建日期行(需合并单元格)
*/
private static void createTableDateRow(ExcelExportData setInfo,
HSSFSheet[] sheets, int sheetNum) {
CellRangeAddress dateRange = new CellRangeAddress(1, 1, 0, setInfo
.getFieldNames().get(sheetNum).length);
sheets[sheetNum].addMergedRegion(dateRange);
HSSFRow dateRow = sheets[sheetNum].createRow(1);
dateRow.setHeight((short) 350);
HSSFCell dateCell = dateRow.createCell(0);
dateCell.setCellStyle(dateStyle);
// dateCell.setCellValue("导出时间:" + new
// SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
// .format(new Date()));
dateCell.setCellValue(new SimpleDateFormat("yyyy-MM-dd")
.format(new Date()));
}

/**
* @Description: 创建表头行(需合并单元格)
*/
private static void creatTableHeadRow(ExcelExportData setInfo,
HSSFSheet[] sheets, int sheetNum) {
// 表头
HSSFRow headRow = sheets[sheetNum].createRow(2);
headRow.setHeight((short) 350);
// 序号列
HSSFCell snCell = headRow.createCell(0);
snCell.setCellStyle(headStyle);
snCell.setCellValue("序号");
// 列头名称
for (int num = 1, len = setInfo.getColumnNames().get(sheetNum).length; num <= len; num++) {
HSSFCell headCell = headRow.createCell(num);
headCell.setCellStyle(headStyle);
headCell.setCellValue(setInfo.getColumnNames().get(sheetNum)[num - 1]);
}
}

/**
* @Description: 创建所有的Sheet
*/
private static HSSFSheet[] getSheets(int num, String[] names) {
HSSFSheet[] sheets = new HSSFSheet[num];
for (int i = 0; i < num; i++) {
sheets[i] = wb.createSheet(names[i]);
}
return sheets;
}

/**
* @Description: 创建内容行的每一列(附加一列序号)
*/
private static HSSFCell[] getCells(HSSFRow contentRow, int num) {
HSSFCell[] cells = new HSSFCell[num + 1];

for (int i = 0, len = cells.length; i < len; i++) {
cells[i] = contentRow.createCell(i);
cells[i].setCellStyle(contentStyle);
}

// 设置序号列值,因为出去标题行和日期行,所有-2
cells[0].setCellValue(contentRow.getRowNum() - 2);

return cells;
}

/**
* @Description: 初始化标题行样式
*/
private static void initTitleCellStyle() {
titleStyle.setAlignment(CellStyle.ALIGN_CENTER);
titleStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
titleStyle.setFont(titleFont);
titleStyle.setFillBackgroundColor(IndexedColors.SKY_BLUE.index);
}

/**
* @Description: 初始化日期行样式
*/
private static void initDateCellStyle() {
dateStyle.setAlignment(CellStyle.ALIGN_CENTER_SELECTION);
dateStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
dateStyle.setFont(dateFont);
dateStyle.setFillBackgroundColor(IndexedColors.SKY_BLUE.index);
}

/**
* @Description: 初始化表头行样式
*/
private static void initHeadCellStyle() {
headStyle.setAlignment(CellStyle.ALIGN_CENTER);
headStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
headStyle.setFont(headFont);
headStyle.setFillBackgroundColor(IndexedColors.YELLOW.index);
headStyle.setBorderTop(CellStyle.BORDER_MEDIUM);
headStyle.setBorderBottom(CellStyle.BORDER_THIN);
headStyle.setBorderLeft(CellStyle.BORDER_THIN);
headStyle.setBorderRight(CellStyle.BORDER_THIN);
headStyle.setTopBorderColor(IndexedColors.BLUE.index);
headStyle.setBottomBorderColor(IndexedColors.BLUE.index);
headStyle.setLeftBorderColor(IndexedColors.BLUE.index);
headStyle.setRightBorderColor(IndexedColors.BLUE.index);
}

/**
* @Description: 初始化内容行样式
*/
private static void initContentCellStyle() {
contentStyle.setAlignment(CellStyle.ALIGN_CENTER);
contentStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
contentStyle.setFont(contentFont);
contentStyle.setBorderTop(CellStyle.BORDER_THIN);
contentStyle.setBorderBottom(CellStyle.BORDER_THIN);
contentStyle.setBorderLeft(CellStyle.BORDER_THIN);
contentStyle.setBorderRight(CellStyle.BORDER_THIN);
contentStyle.setTopBorderColor(IndexedColors.BLUE.index);
contentStyle.setBottomBorderColor(IndexedColors.BLUE.index);
contentStyle.setLeftBorderColor(IndexedColors.BLUE.index);
contentStyle.setRightBorderColor(IndexedColors.BLUE.index);
contentStyle.setWrapText(true); // 字段换行
}

/**
* @Description: 初始化标题行字体
*/
private static void initTitleFont() {
titleFont.setFontName("华文楷体");
titleFont.setFontHeightInPoints((short) 20);
titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
titleFont.setCharSet(Font.DEFAULT_CHARSET);
titleFont.setColor(IndexedColors.BLUE_GREY.index);
}

/**
* @Description: 初始化日期行字体
*/
private static void initDateFont() {
dateFont.setFontName("隶书");
dateFont.setFontHeightInPoints((short) 10);
dateFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
dateFont.setCharSet(Font.DEFAULT_CHARSET);
dateFont.setColor(IndexedColors.BLUE_GREY.index);
}

/**
* @Description: 初始化表头行字体
*/
private static void initHeadFont() {
headFont.setFontName("宋体");
headFont.setFontHeightInPoints((short) 10);
headFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
headFont.setCharSet(Font.DEFAULT_CHARSET);
headFont.setColor(IndexedColors.BLUE_GREY.index);
}

/**
* @Description: 初始化内容行字体
*/
private static void initContentFont() {
contentFont.setFontName("宋体");
contentFont.setFontHeightInPoints((short) 10);
contentFont.setBoldweight(Font.BOLDWEIGHT_NORMAL);
contentFont.setCharSet(Font.DEFAULT_CHARSET);
contentFont.setColor(IndexedColors.BLUE_GREY.index);
}

/**
* Excel导出数据类
*
* @author jimmy
*
*/
public static class ExcelExportData {

/**
* 导出数据 key:String 表示每个Sheet的名称 value:List<?> 表示每个Sheet里的所有数据行
*/
private LinkedHashMap<String, List<?>> dataMap;

/**
* 每个Sheet里的顶部大标题
*/
private String[] titles;

/**
* 单个sheet里的数据列标题
*/
private List<String[]> columnNames;

/**
* 单个sheet里每行数据的列对应的对象属性名称
*/
private List<String[]> fieldNames;

public List<String[]> getFieldNames() {
return fieldNames;
}

public void setFieldNames(List<String[]> fieldNames) {
this.fieldNames = fieldNames;
}

public String[] getTitles() {
return titles;
}

public void setTitles(String[] titles) {
this.titles = titles;
}

public List<String[]> getColumnNames() {
return columnNames;
}

public void setColumnNames(List<String[]> columnNames) {
this.columnNames = columnNames;
}

public LinkedHashMap<String, List<?>> getDataMap() {
return dataMap;
}

public void setDataMap(LinkedHashMap<String, List<?>> dataMap) {
this.dataMap = dataMap;
}

}
}

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
//import org.springframework.util.Assert;

/**
* 反射工具类.
*
* 提供访问私有变量,获取泛型类型Class, 提取集合中元素的属性, 转换字符串到对象等Util函数.
*
*/

public class ReflectionUtil {

private static Log logger = LogFactory.getLog(ReflectionUtil.class);

static {
DateLocaleConverter dc = new DateLocaleConverter();
// dc.setPatterns(new String[] { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss" });
ConvertUtils.register(dc, Date.class);
}

/**
* 调用Getter方法.
*/
public static Object invokeGetterMethod(Object target, String propertyName) {
String getterMethodName = "get" + StringUtils.capitalize(propertyName);
return invokeMethod(target, getterMethodName, new Class[] {},
new Object[] {});
}

/**
* 调用Setter方法.使用value的Class来查找Setter方法.
*/
public static void invokeSetterMethod(Object target, String propertyName,
Object value) {
invokeSetterMethod(target, propertyName, value, null);
}

/**
* 调用Setter方法.
*
* @param propertyType
*            用于查找Setter方法,为空时使用value的Class替代.
*/
public static void invokeSetterMethod(Object target, String propertyName,
Object value, Class<?> propertyType) {
Class<?> type = propertyType != null ? propertyType : value.getClass();
String setterMethodName = "set" + StringUtils.capitalize(propertyName);
invokeMethod(target, setterMethodName, new Class[] { type },
new Object[] { value });
}

/**
* 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
*/
public static Object getFieldValue(final Object object,
final String fieldName) {
Field field = getDeclaredField(object, fieldName);

if (field == null) {
throw new IllegalArgumentException("Could not find field ["
+ fieldName + "] on target [" + object + "]");
}

makeAccessible(field);

Object result = null;
try {
result = field.get(object);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常{}" + e.getMessage());
}
return result;
}

/**
* 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
*/
public static void setFieldValue(final Object object,
final String fieldName, final Object value) {
Field field = getDeclaredField(object, fieldName);

if (field == null) {
throw new IllegalArgumentException("Could not find field ["
+ fieldName + "] on target [" + object + "]");
}

makeAccessible(field);

try {
field.set(object, value);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常:{}" + e.getMessage());
}
}

/**
* 直接调用对象方法, 无视private/protected修饰符.
*/
public static Object invokeMethod(final Object object,
final String methodName, final Class<?>[] parameterTypes,
final Object[] parameters) {
Method method = getDeclaredMethod(object, methodName, parameterTypes);
if (method == null) {
throw new IllegalArgumentException("Could not find method ["
+ methodName + "] parameterType " + parameterTypes
+ " on target [" + object + "]");
}

method.setAccessible(true);

try {
return method.invoke(object, parameters);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}

/**
* 循环向上转型, 获取对象的DeclaredField.
*
* 如向上转型到Object仍无法找到, 返回null.
*/
protected static Field getDeclaredField(final Object object,
final String fieldName) {
//Assert.notNull(object, "object不能为空");
//Assert.hasText(fieldName, "fieldName");
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
.getSuperclass()) {
try {
return superClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {// NOSONAR
// Field不在当前类定义,继续向上转型
}
}
return null;
}

/**
* 强行设置Field可访问.
*/
protected static void makeAccessible(final Field field) {
if (!Modifier.isPublic(field.getModifiers())
|| !Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
field.setAccessible(true);
}
}

/**
* 循环向上转型, 获取对象的DeclaredMethod.
*
* 如向上转型到Object仍无法找到, 返回null.
*/
protected static Method getDeclaredMethod(Object object, String methodName,
Class<?>[] parameterTypes) {
//Assert.notNull(object, "object不能为空");

for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
.getSuperclass()) {
try {
return superClass.getDeclaredMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {// NOSONAR
// Method不在当前类定义,继续向上转型
}
}
return null;
}

/**
* 通过反射, 获得Class定义中声明的父类的泛型参数的类型. 如无法找到, 返回Object.class. eg. public UserDao
* extends HibernateDao<User>
*
* @param clazz
*            The class to introspect
* @return the first generic declaration, or Object.class if cannot be
*         determined
*/
@SuppressWarnings("unchecked")
public static <T> Class<T> getSuperClassGenricType(final Class<?> clazz) {
return getSuperClassGenricType(clazz, 0);
}

/**
* 通过反射, 获得定义Class时声明的父类的泛型参数的类型. 如无法找到, 返回Object.class.
*
* 如public UserDao extends HibernateDao<User,Long>
*
* @param clazz
*            clazz The class to introspect
* @param index
*            the Index of the generic ddeclaration,start from 0.
* @return the index generic declaration, or Object.class if cannot be
*         determined
*/
@SuppressWarnings("unchecked")
public static Class getSuperClassGenricType(final Class<?> clazz,
final int index) {
Type genType = clazz.getGenericSuperclass();

if (!(genType instanceof ParameterizedType)) {
logger.warn(clazz.getSimpleName()
+ "'s superclass not ParameterizedType");
return Object.class;
}

Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

if (index >= params.length || index < 0) {
logger.warn("Index: " + index + ", Size of "
+ clazz.getSimpleName() + "'s Parameterized Type: "
+ params.length);
return Object.class;
}
if (!(params[index] instanceof Class)) {
logger.warn(clazz.getSimpleName()
+ " not set the actual class on superclass generic parameter");
return Object.class;
}

return (Class) params[index];
}

/**
* 提取集合中的对象的属性(通过getter函数), 组合成List.
*
* @param collection
*            来源集合.
* @param propertyName
*            要提取的属性名.
*/

public static List convertElementPropertyToList(
final Collection collection, final String propertyName) {
List list = new ArrayList();

try {
for (Object obj : collection) {
list.add(PropertyUtils.getProperty(obj, propertyName));
}
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}

return list;
}

/**
* 提取集合中的对象的属性(通过getter函数), 组合成由分割符分隔的字符串.
*
* @param collection
*            来源集合.
* @param propertyName
*            要提取的属性名.
* @param separator
*            分隔符.
*/
@SuppressWarnings("unchecked")
public static String convertElementPropertyToString(
final Collection collection, final String propertyName,
final String separator) {
List list = convertElementPropertyToList(collection, propertyName);
return StringUtils.join(list, separator);
}

/**
* 转换字符串到相应类型.
*
* @param value
*            待转换的字符串
* @param toType
*            转换目标类型
*/
@SuppressWarnings("unchecked")
public static <T> T convertStringToObject(String value, Class<T> toType) {
try {
return (T) ConvertUtils.convert(value, toType);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}

/**
* 将反射时的checked exception转换为unchecked exception.
*/
public static RuntimeException convertReflectionExceptionToUnchecked(
Exception e) {
return convertReflectionExceptionToUnchecked(null, e);
}

public static RuntimeException convertReflectionExceptionToUnchecked(
String desc, Exception e) {
desc = (desc == null) ? "Unexpected Checked Exception." : desc;
if (e instanceof IllegalAccessException
|| e instanceof IllegalArgumentException
|| e instanceof NoSuchMethodException) {
return new IllegalArgumentException(desc, e);
} else if (e instanceof InvocationTargetException) {
return new RuntimeException(desc,
((InvocationTargetException) e).getTargetException());
} else if (e instanceof RuntimeException) {
return (RuntimeException) e;
}
return new RuntimeException(desc, e);
}

public static final <T> T getNewInstance(Class<T> cls) {
try {
return cls.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}

/**
* 拷贝 source 指定的porperties 属性 到 dest中
*
* @return void
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public static void copyPorperties(Object dest, Object source,
String[] porperties) throws InvocationTargetException,
IllegalAccessException {
for (String por : porperties) {
Object srcObj = invokeGetterMethod(source, por);
logger.debug("属性名:" + por + "------------- 属性值:" + srcObj);
if (srcObj != null) {
try {
BeanUtils.setProperty(dest, por, srcObj);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
throw e;
} catch (InvocationTargetException e) {
throw e;
}
}
}
}

/**
* 两者属性名一致时,拷贝source里的属性到dest里
*
* @return void
* @throws IllegalAccessException
* @throws InvocationTargetException
*/

public static void copyPorperties(Object dest, Object source)
throws IllegalAccessException, InvocationTargetException {
Class<? extends Object> srcCla = source.getClass();
Field[] fsF = srcCla.getDeclaredFields();

for (Field s : fsF) {
String name = s.getName();
Object srcObj = invokeGetterMethod(source, name);
try {
BeanUtils.setProperty(dest, name, srcObj);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
throw e;
} catch (InvocationTargetException e) {
throw e;
}
}
// BeanUtils.copyProperties(dest, orig);
}

public static void main(String[] args) throws InvocationTargetException,
IllegalAccessException {
/*
* Document document = new Document(); document.setId(2);
* document.setCreateDate(new Date()); DocumentVo dcoVo = new
* DocumentVo(); ReflectionUtils.copyPorperties(dcoVo, document,new
* String[]{"id","businessName","createDate","applyName","docTitle",
* "transactStatus"}); System.out.println(dcoVo.getId());
*/
}
}

List<Chart> list = service.getprouductreport(st, et);
List<SumChart> list2 = new ArrayList<SumChart>();
SumChart ch = new SumChart();
//会员扣卡金额
String totalmoneybykk=service.sumTotalPriceByPayWay(st, et, Integer.parseInt("1"));
//销售额
String totalmoney = service.sumTotalPrice(st, et);
ch.setS1(totalmoneybykk);
ch.setS2(totalmoney);
list2.add(ch);

List<String[]> columNames = new ArrayList<String[]>();
columNames.add(new String[] { "商品ID", "商品种类","销售数量", "成本", "销售额","利润",});
columNames.add(new String[] {"会员扣卡金额","销售额"});
List<String[]> fieldNames = new ArrayList<String[]>();
fieldNames.add(new String[] { "id", "name","saleNum", "unitPrice", "totalPrice","profit",});
fieldNames.add(new String[] {"s1","s2"});
LinkedHashMap<String, List<?>> map = new LinkedHashMap<String, List<?>>();
map.put("销售报表", list);
map.put("总计", list2);
ExcelExportData setInfo = new ExcelExportData();
setInfo.setDataMap(map);
setInfo.setFieldNames(fieldNames);
setInfo.setTitles(new String[] {"销售报表","总计"});
setInfo.setColumnNames(columNames);

try {
OutputStream out = response.getOutputStream();
ExcelUtil.export2Stream(setInfo,out);
out.flush();
System.out.println("excel导出成功!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: