框架 day50 BOS项目 4 批量导入(ocupload插件,pinyin4J)/POI解析Excel/Combobox下拉框/分区组合条件分页查询(ajax)/分区数据导出(Excel)
知识点:
批量导入(ocupload插件,pinyin4J
/POI解析Excel(apache POI)
/区域分页查询
/Combobox下拉框
/分区组合条件分页查询(ajax)
/分区数据导出(Excel下载)
BOS项目笔记第4天
1. 区域批量导入功能
*Ajax不支持文件上传。
*上传并且不刷新上传页面原理:
Target到一个0,0,0的隐藏iframe里,造成一个没有刷新的假象
*选择上传文件后自动上传(无上传按钮)原理:
文件输入框onchange事件 内容一变化就自动提交
1.1 一键上传插件使用
将js文件复制到项目中
jquery.ocupload-1.1.2.js
ocupload jquery 的应用代码
$(function () { $(".uploadfile").upload({ action: 'CourseXMLFileUploadHander.ashx', name: 'xml', params: { 'type': 'uploadCourseXMLFile', 'rand': Math.random() }, onSelect: function (self, element) { this.autoSubmit = false; var re = new RegExp("(xml){1}quot;, "i"); if (!re.test(this.filename())) { alert("Only xml file can be uploaded"); } else { this.submit(); } }, onSubmit: function (self, element) { $('.uploadfile').hide(); $('#ajax_update').parent().show(); //alert('Uploading file...'); }, onComplete: function (data, self, element) { $('#ajax_update').parent().hide(); $('.uploadfile').show(); self.resetInput(); try { var ret = data; if (ret.indexOf("exception") >= 0) { alert('Upload file exception: ' + eval(data)[0].exception); } else { showSuccess('File is successfully Load.'); uploadSuccess(ret); } } catch (err) { alert(data); } } }); });
在需要使用一键上传插件的页面引入js文件,提供一个元素,调用插件的upload方法,动态修改html元素
简单示例
原理:js插件会动态的创建form表单和iframe
1.1 在region.jsp页面应用一键上传插件
引入js文件
调用插件的upload方法
$(function(){$("#button-import").upload({action:'${pageContext.request.contextPath}/regionAction_importXls.action',name:'upload',onComplete: function (data, self, element) { if(data == '1'){$.messager.alert("提示信息","导入数据成功!","info");}else{$.messager.alert("提示信息","导入数据失败!","warning");}}});});
1.2 创建RegionAction提供importXls方法
@Controller
@Scope("prototype")
public class RegionAction extends BaseAction {private File upload;// 用于接收上传的文件public void setUpload(File upload) {this.upload = upload;}// 导入区域数据public String importXls() throws FileNotFoundException, IOException {System.out.println(upload);// 加载Excel文件到内存中HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(upload));// 读取第一个Sheet页HSSFSheet sheet = workbook.getSheetAt(0);List list = new ArrayList();for (Row row : sheet) {// int rowNum = row.getRowNum();String value1 = row.getCell(0).getStringCellValue();// idString value2 = row.getCell(1).getStringCellValue();// proviceString value3 = row.getCell(2).getStringCellValue();// cityString value4 = row.getCell(3).getStringCellValue();// districtString value5 = row.getCell(4).getStringCellValue();// postcodeRegion region = new Region(value1, value2, value3, value4, value5);// 简码String shortcode = StringUtils.join(PinYin4jUtils.getHeadByString(value2 + value3), "");// 城市编码String citycode = PinYin4jUtils.hanziToPinyin(value3, "");region.setShortcode(shortcode);region.setCitycode(citycode);list.add(region);}String f = "1";try {regionService.saveBatch(list);} catch (Exception e) {f = "0";}ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");ServletActionContext.getResponse().getWriter().print(f);return NONE;}
配置struts.xml
略
*重复导入时出现主键冲突:
Duplicate entry ......
解决方法:使用saveOrUpdate
1.3 使用apache POI解析Excel文件
/*** 测试POI解析Excel文件*/
public class POITest {@Testpublic void test1() throws FileNotFoundException, IOException {HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(new File("d:\\abc.xls")));HSSFSheet sheet = workbook.getSheetAt(0);//读取第一个sheet页for (Row row : sheet) {//循环读取每一行String v1 = row.getCell(0).getStringCellValue();//获得当前行的第一个单元格的文字内容String v2 = row.getCell(1).getStringCellValue();String v3 = row.getCell(2).getStringCellValue();String v4 = row.getCell(3).getStringCellValue();String v5 = row.getCell(4).getStringCellValue();System.out.println(v1 + " " + v2 + " " +v3 + " " + v4 + " " + v5);}}
}
Pinyin4J
@Testpublic void test1() {String city = "北京市";String province = "河北省";String city2 = "石家庄市";String district = "长安区";// 城市编码 北京市-----》beijingString str1 = PinYin4jUtils.hanziToPinyin(city.substring(0, city.length() - 1), "");System.out.println(str1);String info = province.substring(0, province.length() - 1)+ city2.substring(0, city2.length() - 1)+ district.substring(0, district.length() - 1);// 简码河北省石家庄市长安区-----》hbsjzcaString[] strings = PinYin4jUtils.getHeadByString(info);String join = StringUtils.join(strings, "");System.out.println(join);}
}
utils工具类
package cn.itcast.bos.utils;import java.util.Arrays;import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;public class PinYin4jUtils {/*** 将字符串转换成拼音数组* * @param src* @return*/public static String[] stringToPinyin(String src) {return stringToPinyin(src, false, null);}/*** 将字符串转换成拼音数组* * @param src* @return*/public static String[] stringToPinyin(String src, String separator) {return stringToPinyin(src, true, separator);}/*** 将字符串转换成拼音数组* * @param src* @param isPolyphone* 是否查出多音字的所有拼音* @param separator* 多音字拼音之间的分隔符* @return*/public static String[] stringToPinyin(String src, boolean isPolyphone,String separator) {// 判断字符串是否为空if ("".equals(src) || null == src) {return null;}char[] srcChar = src.toCharArray();int srcCount = srcChar.length;String[] srcStr = new String[srcCount];for (int i = 0; i < srcCount; i++) {srcStr[i] = charToPinyin(srcChar[i], isPolyphone, separator);}return srcStr;}/*** 将单个字符转换成拼音* * @param src* @return*/public static String charToPinyin(char src, boolean isPolyphone,String separator) {// 创建汉语拼音处理类HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();// 输出设置,大小写,音标方式defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);StringBuffer tempPinying = new StringBuffer();// 如果是中文if (src > 128) {try {// 转换得出结果String[] strs = PinyinHelper.toHanyuPinyinStringArray(src,defaultFormat);// 是否查出多音字,默认是查出多音字的第一个字符if (isPolyphone && null != separator) {for (int i = 0; i < strs.length; i++) {tempPinying.append(strs[i]);if (strs.length != (i + 1)) {// 多音字之间用特殊符号间隔起来tempPinying.append(separator);}}} else {tempPinying.append(strs[0]);}} catch (BadHanyuPinyinOutputFormatCombination e) {e.printStackTrace();}} else {tempPinying.append(src);}return tempPinying.toString();}public static String hanziToPinyin(String hanzi) {return hanziToPinyin(hanzi, " ");}/*** 将汉字转换成拼音* * @param hanzi* @param separator* @return*/public static String hanziToPinyin(String hanzi, String separator) {// 创建汉语拼音处理类HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();// 输出设置,大小写,音标方式defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);String pinyingStr = "";try {pinyingStr = PinyinHelper.toHanyuPinyinString(hanzi, defaultFormat,separator);} catch (BadHanyuPinyinOutputFormatCombination e) {// TODO Auto-generated catch blocke.printStackTrace();}return pinyingStr;}/*** 将字符串数组转换成字符串* * @param str* @param separator* 各个字符串之间的分隔符* @return*/public static String stringArrayToString(String[] str, String separator) {StringBuffer sb = new StringBuffer();for (int i = 0; i < str.length; i++) {sb.append(str[i]);if (str.length != (i + 1)) {sb.append(separator);}}return sb.toString();}/*** 简单的将各个字符数组之间连接起来* * @param str* @return*/public static String stringArrayToString(String[] str) {return stringArrayToString(str, "");}/*** 将字符数组转换成字符串* * @param str* @param separator* 各个字符串之间的分隔符* @return*/public static String charArrayToString(char[] ch, String separator) {StringBuffer sb = new StringBuffer();for (int i = 0; i < ch.length; i++) {sb.append(ch[i]);if (ch.length != (i + 1)) {sb.append(separator);}}return sb.toString();}/*** 将字符数组转换成字符串* * @param str* @return*/public static String charArrayToString(char[] ch) {return charArrayToString(ch, " ");}/*** 取汉字的首字母* * @param src* @param isCapital* 是否是大写* @return*/public static char[] getHeadByChar(char src, boolean isCapital) {// 如果不是汉字直接返回if (src <= 128) {return new char[] { src };}// 获取所有的拼音String[] pinyingStr = PinyinHelper.toHanyuPinyinStringArray(src);// 创建返回对象int polyphoneSize = pinyingStr.length;char[] headChars = new char[polyphoneSize];int i = 0;// 截取首字符for (String s : pinyingStr) {char headChar = s.charAt(0);// 首字母是否大写,默认是小写if (isCapital) {headChars[i] = Character.toUpperCase(headChar);} else {headChars[i] = headChar;}i++;}return headChars;}/*** 取汉字的首字母(默认是大写)* * @param src* @return*/public static char[] getHeadByChar(char src) {return getHeadByChar(src, true);}/*** 查找字符串首字母* * @param src* @return*/public static String[] getHeadByString(String src) {return getHeadByString(src, true);}/*** 查找字符串首字母* * @param src* @param isCapital* 是否大写* @return*/public static String[] getHeadByString(String src, boolean isCapital) {return getHeadByString(src, isCapital, null);}/*** 查找字符串首字母* * @param src* @param isCapital* 是否大写* @param separator* 分隔符* @return*/public static String[] getHeadByString(String src, boolean isCapital,String separator) {char[] chars = src.toCharArray();String[] headString = new String[chars.length];int i = 0;for (char ch : chars) {char[] chs = getHeadByChar(ch, isCapital);StringBuffer sb = new StringBuffer();if (null != separator) {int j = 1;for (char ch1 : chs) {sb.append(ch1);if (j != chs.length) {sb.append(separator);}j++;}} else {sb.append(chs[0]);}headString[i] = sb.toString();i++;}return headString;}public static void main(String[] args) {// pin4j 简码 和 城市编码 String s1 = "中华人民共和国"; String[] headArray = getHeadByString(s1); // 获得每个汉字拼音首字母System.out.println(Arrays.toString(headArray));String s2 ="长城" ; System.out.println(Arrays.toString(stringToPinyin(s2,true,",")));String s3 ="长";System.out.println(Arrays.toString(stringToPinyin(s3,true,",")));}
}
2. 区域分页查询
修改region.jsp页面中datagrid的url地址
在RegionAction中提供分页查询方法pageQuery
与上一天的代码重复需要提取到baseAction
3. 重构分页代码
在BaseAction中提取PageBean和DetachedCriteria对象
protected PageBean pageBean = new PageBean();// 离线条件查询对象,用于包装查询条件DetachedCriteria detachedCriteria = null;
在BaseAction中提供setPage和setRows方法
把分页ajax相应的两个参数row和page直接注入到上面提取的pageBean中
public void setPage(int page) {pageBean.setCurrentPage(page);// 当前页码}public void setRows(int rows) {pageBean.setPageSize(rows);// 每页显示记录数}
在BaseAction的构造方法中创建离线条件查询对象,并且注入给PageBean
构造方法获取实体类型后创建离线查询条件对象并注入到pageBean中
public BaseAction() {// 获得父类(BaseAction) 类型ParameterizedType superclass = (ParameterizedType) this.getClass().getGenericSuperclass();// 获得父类上的泛型数组Type[] typeArguments = superclass.getActualTypeArguments();// 获得实体类型Class domainClass = (Class) typeArguments[0];// 获得实体类型后创建离线条件查询对象detachedCriteria = DetachedCriteria.forClass(domainClass);pageBean.setDetachedCriteria(detachedCriteria);try {model = domainClass.newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}
在BaseAction中抽取方法writePageBean2Json和writeListBean2Json
/*** 将PageBean序列化为json返回*/public void writePageBean2Json(PageBean pageBean, String[] excludes) {// 使用jsonlib将PageBean对象序列化为json数据JsonConfig jsonConfig = new JsonConfig();jsonConfig.setExcludes(excludes);String json = JSONObject.fromObject(pageBean, jsonConfig).toString();ServletActionContext.getResponse().setContentType("text/json;charset=UTF-8");try {ServletActionContext.getResponse().getWriter().print(json);} catch (IOException e) {e.printStackTrace();}}/*** 将List序列化为json返回*/public void writeListBean2Json(List list, String[] excludes) {// 使用jsonlib将PageBean对象序列化为json数据JsonConfig jsonConfig = new JsonConfig();jsonConfig.setExcludes(excludes);String json = JSONArray.fromObject(list, jsonConfig).toString();ServletActionContext.getResponse().setContentType("text/json;charset=UTF-8");try {ServletActionContext.getResponse().getWriter().print(json);} catch (IOException e) {e.printStackTrace();}}
在RegionAction中的分页查询
分页查询代码简化为3条
/*** 分页查询方法* @throws IOException */public String pageQuery() throws IOException{regionService.pageQuery(pageBean);this.writePageBean2Json(pageBean, new String[]{"currentPage","pageSize","detachedCriteria","subareas"});return NONE;}
4. 分区添加功能
4.1 Combobox下拉框使用
方式一:给静态的select标签应用
方式二:使用input标签通过url动态获取数据(json)
textField:为"option"下拉显示的内容
valueField::为最终提交的value值
subarea分区页面的添加分区弹窗区域选择下拉框数据获取(模糊查询)
及添加分区功能
第一步:修改subarea.jsp页面中combobox的url地址
mode属性
定义了当文本改变时如何读取列表数据。设置为'remote'时,下拉列表框将会从服务器加载数据。
当设置为“remote”模式时,用户输入将被发送到名为'q'的HTTP请求参数到服务器检索新数据。
对应分区类也应增加与下拉栏textField对应的name属性(省市区)
private String id;//编号private String province;//省private String city;//市private String district;//区private String postcode;//邮编private String shortcode;//简码private String citycode;//城市编码private Set subareas = new HashSet(0);//区域对应的多个分区public String getName(){return province + city + district;}
第二步:在RegionAction中提供list方法查询区域数据
private String q;//模糊查询参数 public void setQ(String q) {this.q = q;}/*** 查询所有区域返回json*/public String list(){List list = null;if(StringUtils.isNotBlank(q)){//根据q进行模糊查询list = regionService.findByQ(q.trim());}else{//查询所有list = regionService.findAll();}String[] excludes = new String[]{"subareas"};this.writeListBean2Json(list, excludes);return NONE;}
Service中:
@Overridepublic List findByQ(String q) { return regionDao.findByNameQuery("findByQ","%"+q+"%","%"+q+"%","%"+q+"%");} baseIDaompl命名查询
@Overridepublic List findByNameQuery(String hqlName, Object... params) {List findByNamedQuery = this.getHibernateTemplate().findByNamedQuery(hqlName,params);return findByNamedQuery;}
对应*hbm.xml提供query hql语句
注意:命名查询配置语句中不能出现双引号" "会报错,因为语句是按字符串来提取的,xml配置+" "来拼接也不行
FROM Region WHERE city LIKE ? OR province LIKE ? OR district LIKE ?
第三步:为保存按钮绑定事件
保存
第四步:创建一个SubareaAction,提供add方法用于添加分区
略
5. 分区组合条件分页查询
基于datagrid的load方法实现组合条件分页查询
*带关联查询的分页查询转换json会出错
freemarker.template.TemplateModelException:
Method public java.lang.Stringorg.apache.commons.lang.exception
.NestableRuntimeException.getMessage(int)threw an exception when invoked on net.sf.json.JSONException:
java.lang.reflect.InvocationTargetException
原因:关联对象延迟加载是代理对象无法转换成json数据
解决: 修改对应需关联对象hbm,xml文件的lazy属性为false 解决关联查询问题
第一步:提供组合条件查询窗口
第二步:提供一个工具方法,将form表单中的输入项转为json数据,提交参数
$.fn.serializeJson=function(){ var serializeObj={}; var array=this.serializeArray();$(array).each(function(){ if(serializeObj[this.name]){ if($.isArray(serializeObj[this.name])){ serializeObj[this.name].push(this.value); }else{ serializeObj[this.name]=[serializeObj[this.name],this.value]; } }else{ serializeObj[this.name]=this.value; } }); return serializeObj; };
第三步:为查询按钮绑定事件,调用datagrid的load方法,重写发起ajax请求,提交参数
目的:这样发起的查询是ajax请求,条件参数会缓存在页面.
ajax没有全部刷新页面所以对应分页查询的条件也不会丢失
方法:load
参数:param
详情:
加载和显示第一页的所有行。如果指定了'param',它将取代'queryParams'属性。通常可以通过传递一些参数执行一次查询,通过调用这个方法从服务器加载新数据。
第四步:改造SubareaAction中的pageQuery方法,加入组合条件分页查询逻辑
Restrictions API
/*** 分页组合条件查询*/public String pageQuery() {DetachedCriteria subareaDC = pageBean.getDetachedCriteria();// 从模型对象中获取提交的查询参数String addresskey = model.getAddresskey();// 关键字// 单表查询if (StringUtils.isNotBlank(addresskey)) {// 添加查询条件,根据关键字进行模糊查询subareaDC.add(Restrictions.like("addresskey","%" + addresskey.trim() + "%"));}Region region = model.getRegion();// 多表查询if (region != null) {String province = region.getProvince();String city = region.getCity();String district = region.getDistrict();DetachedCriteria regionDC = subareaDC.createCriteria("region");if (StringUtils.isNotBlank(province)) {// 添加查询条件,根据省进行模糊查询regionDC.add(Restrictions.like("province", "%" + province + "%"));}if (StringUtils.isNotBlank(city)) {// 添加查询条件,根据省进行模糊查询regionDC.add(Restrictions.like("city", "%" + city + "%"));}if (StringUtils.isNotBlank(district)) {// 添加查询条件,根据省进行模糊查询regionDC.add(Restrictions.like("district", "%" + district + "%"));}}subareaService.pageQuery(pageBean);String[] excludes = new String[] { "decidedzone", "subareas" };this.writePageBean2Json(pageBean, excludes);return NONE;}
6. 分区数据导出功能(Excel提供下载)
第一步:修改subarea.jsp页面中导出按钮的事件
function doExport(){//发起请求Action,查询所有分区数据,写到Excel文件中并提供下载window.location.href = "${pageContext.request.contextPath}/subareaAction_exportXls.action";}
第二步:在Action中提供exportXls方法
两种方法:
方式一:原始手动设置响应下载
文件名乱码工具类
import java.io.IOException;
import java.net.URLEncoder;import sun.misc.BASE64Encoder;public class FileUtils {/*** 下载文件时,针对不同浏览器,进行附件名的编码* * @param filename* 下载文件名* @param agent* 客户端浏览器* @return 编码后的下载附件名* @throws IOException*/public static String encodeDownloadFilename(String filename, String agent)throws IOException {if (agent.contains("Firefox")) { // 火狐浏览器filename = "=?UTF-8?B?"+ new BASE64Encoder().encode(filename.getBytes("utf-8"))+ "?=";filename = filename.replaceAll("\r\n", "");} else { // IE及其他浏览器filename = URLEncoder.encode(filename, "utf-8");filename = filename.replace("+"," ");}return filename;}
}
/*** 导出分区数据到Excel文件并提供下载* * @throws IOException*/public String exportXls() throws IOException {List list = subareaService.findAll();// 使用POI将查询的数据写入Excel文件中HSSFWorkbook workbook = new HSSFWorkbook();// 在工作表中创建一个sheet页HSSFSheet sheet = workbook.createSheet("分区数据");// 创建标题行HSSFRow headRow = sheet.createRow(0);// 创建单元格headRow.createCell(0).setCellValue("分区编号");headRow.createCell(1).setCellValue("关键字");headRow.createCell(2).setCellValue("地址");headRow.createCell(3).setCellValue("省市区");for (Subarea subarea : list) {// 创建数据行HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1);String id = subarea.getId();String addresskey = subarea.getAddresskey();String position = subarea.getPosition();Region region = subarea.getRegion();dataRow.createCell(0).setCellValue(id);dataRow.createCell(1).setCellValue(addresskey);dataRow.createCell(2).setCellValue(position);if (region != null) {String province = region.getProvince();String city = region.getCity();String district = region.getDistrict();String info = province + city + district;dataRow.createCell(3).setCellValue(info);}}String filename = "分区数据.xls";String agent = ServletActionContext.getRequest().getHeader("user-agent");//浏览器类型filename = FileUtils.encodeDownloadFilename(filename, agent );//根据文件名称动态获得类型String contentType = ServletActionContext.getServletContext().getMimeType(filename);// 通知客户端下载文件的类型ServletActionContext.getResponse().setContentType(contentType);//指定以附件形式下载,指定文件名称ServletActionContext.getResponse().setHeader("content-disposition", "attachment;filename=" + filename);// 通过输出流向客户端浏览器写Excel文件ServletOutputStream out = ServletActionContext.getResponse().getOutputStream();workbook.write(out);return NONE;}
}
方式二:通过struts2的stream结果集下载
思路百度自博客(http://xiaowei-qi-epro-com-cn.iteye.com/blog/2030671):
思路是,先创建一个输出流,将这个excel写入到输出流里面,然后再通过这个输出流来得到我们所需要的输入流.
使用了ByteArrayOutputStream和ByteArrayInputStream类...处理的思想是,将HSSFWorkbook 写入ByteArrayOutputStream.然后用ByteArrayOutputStream来转换为字节流..然后再将字节流转换为ByteArrayInputStream ..至此,我们就在内存中将excel转换成了输入流
private InputStream target; public InputStream getTarget() { return target; } //下载文件名,存在中文乱码 private String downloadFileName; public String getDownloadFileName() throws UnsupportedEncodingException { // 处理中文乱码 if(downloadFileName != null){ return new String(downloadFileName.getBytes("GBK"),"ISO-8859-1"); } return downloadFileName; } /*** 下载所有分区信息以xls格式* @return* @throws IOException */public String export() throws IOException{List list=subareaService.findAll();//把list写入excel文档HSSFWorkbook book=new HSSFWorkbook();HSSFSheet sheet = book.createSheet("全部分区详情");//创建初始标题行HSSFRow row = sheet.createRow(0);row.createCell(0).setCellValue("分拣编号");row.createCell(1).setCellValue("省市区");row.createCell(2).setCellValue("关键字");row.createCell(3).setCellValue("位置");//遍历listfor (Subarea subarea : list) {HSSFRow createRow = sheet.createRow(sheet.getLastRowNum()+1);String id = subarea.getId();String nameInfo = subarea.getRegion().getName();String addresskey = subarea.getAddresskey();String position = subarea.getPosition();createRow.createCell(0).setCellValue(id);createRow.createCell(1).setCellValue(nameInfo);createRow.createCell(2).setCellValue(addresskey);createRow.createCell(3).setCellValue(position);}ByteArrayOutputStream out = new ByteArrayOutputStream();book.write(out);target = new ByteArrayInputStream(out.toByteArray()); out.close(); downloadFileName="分区详情.xls"; return "download";}
配置文件
/WEB-INF/pages/base/subarea.jsp attachment;filename=${downloadFileName} target
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
