前序:该篇文章将treegrid的使用,侧重于添加节点的方法,如何保存节点到数据库。不过获取节点数据的方法有点傻。将就着,若下次还遇到使用treegrid的情况,将会好好研究一下如何更好的传递节点数据到后台。另外,文章的代码存在小问题。不过都被我用取巧的方法解决掉。
存在的问题:为什么选中根节点后,用getSelected方法,得到的是null??
取巧的解决方法:初始化treegrid时,顺便加载onClickRow()方法,当选中一行的时候,将该行的id赋值到全局变量selectedSelfid,而当选中根节点时,selectedSelfid就是根节点的id,绕过用getSelected方法。
一、数据库表的设计
存储节点的表A:表主键Aid,节点id,父节点pid,表B的主键Bid,附件(类型为bytea)
表A与表B的关系:多对一
二、页面代码
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ include file="/common/comm.jsp"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <link rel="stylesheet" type="text/css"href="${path}/easyui/themes/bootstrap/easyui.css" /> <link rel="stylesheet" type="text/css"href="${path}/easyui/themes/icon.css" /> <link rel="stylesheet" type="text/css"href="${path}/ztree/css/zTreeStyle/zTreeStyle.css"> <link rel="stylesheet" type="text/css" href="${path}/css/base.css" /> <link rel="stylesheet" type="text/css" href="${path}/css/public.css" /> <script type="text/javascript" src="${path}/js/knockout-3.4.0.js"></script> <script type="text/javaScript" src="${path}/easyui/jquery-1.7.2.min.js"></script> <script type="text/javaScript" src="${path}/easyui/jquery.easyui.min.js"></script> <script type="text/javaScript"src="${path}/easyui/locale/easyui-lang-zh_CN.js"></script> <script type="text/javaScript"src="${path}/jquery/validate/jquery.form.js"></script> <script type="text/javaScript" src="${path}/easyui/etreegrid.js"></script> <script type="text/javascript" src="${path}/js/comm.js"></script> <script type="text/javaScript" src="${path}/js/base.js"></script> <script type="text/javaScript" src="${path}/js/tools.js"></script> <script type="text/javascript" src="${path}/js/constants.js"></script> <script type="text/javascript" src="${path}/js/artDialog/artDialog.js?skin=blue"></script> <script type="text/javascript" src="${path}/js/artDialog/plugins/iframeTools.js"></script> <script type="text/javascript"src="${path}/ztree/jquery.ztree.all-3.5.min.js"></script> <script type="text/javascript" src="${path}/easyui/validator.js?version=201601191559"></script> <script type="text/javascript" > var lastIndex = "" ; //处于编辑状态的节点的selfid var selectedSelfid ; $(function() { $('#plantylecode').combobox({ url:"dictionaryCtrl.do?method=getDictionaryItemsByCategory&type=1&categoryCode=PREPLAN_TYPE", valueField:'value', textField:'text', onLoadSuccess:function(data){ if (data) { if('${modal}' == 'new') $('#plantylecode').combobox('setValue',data[0].value); } } }); $('#planlevelcode').combobox({ url:"dictionaryCtrl.do?method=getDictionaryItemsByCategory&type=1&categoryCode=PREPLAN_LEVEL", valueField:'value', textField:'text', onLoadSuccess:function(data){ if (data) { if('${modal}' == 'new') $('#planlevelcode').combobox('setValue',data[0].value); } } }); if('${modal}' == 'edit'){ $("#plantylecode").combobox("setValue",'${c.plantypecode}'); $("#planlevelcode").combobox("setValues",'${c.planlevelcode}'); if('${c.attachment}' != '') { $("td[tdModel*='importFile']").hide(); } else { $("td[tdModel*='downloadFile']").hide(); } } if('${modal}' == 'new'){ $("td[tdModel*='downloadFile']").hide(); } //初始化treegrid插件 $('#resourcelist').treegrid({ url:"prePlan.do?method=getTreePlan&id="+encodeURI('${id}'), //data:[{"id":1,"planid":0,"contentitem":"新增222环节名称","contentitemno":1,"pid":-1,"selfid":1,"createtime":new Date(), // "chilren": [{"id":101,"planid":0,"contentitem":"新增环节名称","contentitemno":1,"pid":1,"selfid":101,"createtime":new Date()}, // {"id":102,"planid":0,"contentitem":"新增环节名称","contentitemno":2,"pid":1,"selfid":102,"createtime":new Date()}, // {"id":103,"planid":0,"contentitem":"新增环节名称","contentitemno":3,"pid":1,"selfid":103,"createtime":new Date()}]} // ], nowrap: false, animate:true, collapsible:true, idField:'selfid', fitColumns: true, rownumbers:true, //toolbar:'#tb', treeField:'contentitem', columns:[[ {title:'环节',field:'contentitem',width:200,editor:'text'} ]] , onDblClickCell:function(field,row){ lastIndex = row.selfid; $('#resourcelist').treegrid('beginEdit',row.selfid); //进行编辑 }, onClickRow:function(row){ $('#resourcelist').treegrid('endEdit', lastIndex); selectedSelfid = row.selfid; lastIndex = ""; //退出编辑后设为空 }, //右键 onContextMenu:function(e,row){ e.preventDefault(); $(this).treegrid('unselectAll'); $(this).treegrid('select', row.selfid); $('#access_menu').menu('show', { left: e.pageX, top: e.pageY }); }, }); }) function appendNode(parentId, id, selfid, contentitem, pid, planid, contentitemno, createtime){ $('#resourcelist').treegrid('append',{ parent: parentId, //不填此项默认创建根环节 data: [{ id: id, selfid: selfid, contentitem: contentitem, pid: pid, planid: planid, //后台设置 contentitemno: contentitemno, createtime: createtime }] }); } function addnode(){ if(lastIndex != "") { $.messager.alert("系统提示","请先退出当前环节的编辑!"); return false; } var row = $('#resourcelist').treegrid('getSelected'); var root=$('#resourcelist').treegrid('getRoot'); if(root != null && row==null){ $.messager.alert("系统提示","请先选中环节!"); return; } if(root == null){ //无任何环节的情况下,添加根环节 appendNode('-1', '1', '1','新增环节名称1', '-1', null, '1', new Date()); } if(row !=null) { var level=$('#resourcelist').treegrid('getLevel',row.selfid); if(level==1){ //存在其他根环节的情况下,添加根环节 var roots = $('#resourcelist').treegrid('getRoots'); //遍历所有同级子环节,求得同级子环节的最大值; var selfmax=parseInt(row.selfid); var item=0; for (var i = 0; i < roots.length; i++) { if(selfmax<parseInt(roots[i].selfid)) selfmax=parseInt(roots[i].selfid); if(item<roots[i].contentitemno){ item=roots[i].contentitemno; } } var nameId =parseInt(item)+1; appendNode('-1', selfmax+1, selfmax+1, '新增环节名称'+nameId, '-1', null, nameId, new Date()); } else { //除了根环节外,添加同级环节 var parent= $('#resourcelist').treegrid('getParent',row.selfid); //遍历所有同级子环节,求得同级子环节的最大值; var selfmax=parseInt(row.selfid); var item=1; var children=$('#resourcelist').treegrid('getChildren',parent.selfid); for (var i = 0; i < children.length; i++) { if(level==$('#resourcelist').treegrid('getLevel',children[i].selfid)) { if(selfmax<parseInt(children[i].selfid)) selfmax=parseInt(children[i].selfid); if(item<children[i].contentitemno){ item=children[i].contentitemno; } } } //添加环节 var nameId = selfmax+1; appendNode(parent.selfid, selfmax+1, selfmax+1, '新增环节名称'+nameId, parent.selfid, null, item+1, new Date()); } } } //添加子级环节 function addchildnode(){ if(lastIndex != "") { $.messager.alert("系统提示","请先退出当前环节的编辑!"); return false; } var row = $('#resourcelist').treegrid('getSelected'); if(row==null){ alert("请选中环节"); return; } var level=$('#resourcelist').treegrid('getLevel',row.selfid); if(level==3){ $.messager.alert("系统提示","最多只能有三层环节,已是第三层环节!"); return; } var children=$('#resourcelist').treegrid('getChildren',row.selfid); var selfmax=row.selfid*100; var item=0; if(children.length>0){ //遍历所有同级子环节,求得同级子环节的最大值; var childlevel=level+1; for (var i = 0; i < children.length; i++) { if(childlevel==$('#resourcelist').treegrid('getLevel',children[i].selfid)){ if(selfmax<parseInt(children[i].selfid)) selfmax=parseInt(children[i].selfid); if(item<children[i].contentitemno){ item=children[i].contentitemno; } } } } else { selfmax=parseInt(row.selfid)*100; item=0; } //添加环节 var nameId = selfmax+1; appendNode(row.selfid, selfmax+1, selfmax+1, '新增环节名称'+nameId, row.selfid, null, item+1, new Date()); } //删除环节 function deletenode(){ if(lastIndex != "") { $.messager.alert("系统提示","请先退出当前环节的编辑!"); return false; } var row = $('#resourcelist').treegrid('getSelected'); var level; var delSelfid; if(row != null ) { delSelfid = row.selfid; } else { //根节点 delSelfid = selectedSelfid; } level=$('#resourcelist').treegrid('getLevel',delSelfid); if(null != row || level == 1) { $.messager.confirm("系统提示","您确认要删除这个环节及该环节在的子环节吗?",function(r){ if(r){ $('#resourcelist').treegrid('remove',delSelfid); } }); } else { $.messager.alert("系统提示","请先选中环节!"); return; } } function save(){ if (!$('#myform').form('validate')) { return false; } if(lastIndex != "") { $.messager.alert("系统提示","请先退出当前环节的编辑!"); return false; } //存放要提交的数据:【表单】数据和【环节】数据 var savedata=new Array(); //获取form表单数据 savedata.push({id:'${id}',planname:$("#planname").val(),plantypecode:$("#plantylecode").combobox("getValue"), plantype:$("#plantylecode").combobox("getText"),planlevelcode:$("#planlevelcode").combobox("getValue"), planlevel:$("#planlevelcode").combobox("getText"),keyword:$("#keyword").val()}); var roots=$('#resourcelist').treegrid('getRoots'); //获取根环节的数据 for(var i=0;i<roots.length;i++){ var id=roots[i].id; var planid=roots[i].planid; var contentitem=roots[i].contentitem; var contentitemno=roots[i].contentitemno; var pid=roots[i].pid; var selfid=roots[i].selfid; //var createtime=root.createtime; var createtime=new Date(); savedata.push({id:id,planid:planid,contentitem:contentitem,contentitemno:contentitemno,pid:pid,selfid:selfid,createtime:createtime}); //获取该根环节下的环节的数据 var data2= $('#resourcelist').treegrid('getChildren',roots[i].selfid); for(var j=0;j<data2.length;j++){ var id=data2[j].id; var planid=data2[j].planid; var contentitem=data2[j].contentitem; var contentitemno=data2[j].contentitemno; var pid=data2[j].pid; var selfid=data2[j].selfid; var createtime=data2[j].createtime; savedata.push({id:id,planid:planid,contentitem:contentitem,contentitemno:contentitemno,pid:pid,selfid:selfid,createtime:createtime}) } } var commitData=new Array(); for(var i=0;i<savedata.length;i++){ commitData.push(JSON.stringify(savedata[i])); } $("#commitData").val(commitData); $('#myform').form('submit',{ url: "prePlan.do?method=savePrePlan", onSubmit: function(){ var excelfile = $("#attchment").filebox("getValue"); if(excelfile != '') { var exfile = excelfile.split("."); if(exfile[1].toUpperCase() != "DOC" && exfile[1].toUpperCase() != "DOCX"){ $.messager.alert('警告','上传文件格式不对 ,请选择WORD文件!'); return false; } } return $(this).form('validate'); //必须用return,不能用$("#myform").submit();否则成功时不会调用success方法 //$("#myform").submit(); }, success: function(data){ var data = eval('('+data+')'); if (data.code == 1) { artDialog.opener.$.messager.show({ title : '消息窗口', msg : decodeURI(data.message) }); artDialog.opener.$("#planList").datagrid('reload'); artDialog.close(); }else{ $.messager.alert("提示信息",decodeURI(data.message),"error"); } }, error: function() { alert('错误'); } }); } //右键进行编辑 function beginEdit(){ var row = $('#resourcelist').treegrid('getSelected'); if(row != null ) { lastIndex = row.selfid; $('#resourcelist').treegrid('beginEdit',row.selfid); } } //下载附件 function downloadAttachment(id) { window.location.href = "prePlan.do?method=downloadAttachment&id="+id; } //重新上传附件 function importAgain() { $("td[tdModel*='importFile']").show(); $("td[tdModel*='downloadFile']").hide(); } //结束编辑 $(document).ready(function(){ $("#body").bind("keydown",function(e){ // 兼容FF和IE和Opera var theEvent = e || window.event; var code = theEvent.keyCode || theEvent.which || theEvent.charCode; if (code == 13) { //回车执行查询 $('#resourcelist').treegrid('endEdit', lastIndex); lastIndex = ""; } }); }); </script> <style type="text/css"> .tree-folder-open, .tree-file, .tree-folder { background: url(images/org.png) no-repeat center center; } </style> </head> <body class="easyui-layout" id="body"> <div id="access_menu" class="easyui-menu" style="width:100px;"> <div id='access_menu_new' data-options="iconCls:'icon-add'" onclick="addnode()">新增同级环节</div> <div id='access_menu_new' data-options="iconCls:'icon-add'" onclick="addchildnode()">新增子环节</div> <div id='access_menu_edit'data-options="iconCls:'icon-edit'" onclick="beginEdit()" >编辑本环节</div> <div id='access_menu_del' data-options="iconCls:'icon-remove'" onclick="deletenode();">删除本环节</div> <!-- <div id='access_menu_refresh'>刷新环节</div> --> </div> <div style="height:14%"> <form id="myform" name="myform" method="post" enctype="multipart/form-data"> <!-- 存放数据 2016.5.6 --> <input id="commitData" name="commitData" type="hidden" /> <table id="searchtable" width="100%" > <tr height="40"> <td width="10%" align="right"><label style="color: red;">*</label>预案名称:</td> <td width="20%" class="body"><input type="text" class="easyui-validatebox" required="true" style="border-radius:5px;width: 98%;height:20px" name="planname" id="planname" value="${c.planname}" /></td> <td width="10%" align="right">预案类型:</td> <td width="12%" class="body"><input style="width: 98%" class="easyui-combobox" name="plantylecode" id="plantylecode" /></td> <td width="10%" align="right">预案等级:</td> <td width="12%" class="body"><input style="width: 98%" class="easyui-combobox" name="planlevelcode" id="planlevelcode" /></td> </tr> <tr> <td align="right">文本附件:</td> <td tdModel="downloadFile"><a href="javascript:void(0)" style="color:red;margin-right:10px" onclick="downloadAttachment(${id})">下载附件</a> <a href="javascript:void(0)" style="color:blue" onclick="importAgain()">重新上传</a></td> <td tdModel="importFile"><input name="attchment" id="attchment" class="easyui-filebox" data-options="prompt:'请选择文件...'" style="width:250px" /></td> <td align="right">关键词:</td> <td colspan="3"><input type="text" style="border-radius:5px;width: 98%;height:20px" name="keyword" id="keyword" value="${c.keyword}"/></td> </tr> </table> </form> </div> <div style="height:80%;width:100%" fit="true"> <div id="tb" style="margin-bottom:3px;"> <!--<a href="javascript:void(0)" class="easyui-linkbutton" onclick="addRoot()">添加同级环节</a>--> <a href="javascript:void(0)" class="easyui-linkbutton" onclick="addnode()">添加同级环节</a> <a href="javascript:void(0)" class="easyui-linkbutton" onclick="addchildnode()">添加子级环节</a> <a href="javascript:void(0)" class="easyui-linkbutton" onclick="deletenode()">删除</a> <span style="color:red;float:right;margin-right:20px"> * 回车或单击另一行可退出编辑状态</span> </div> <table id="resourcelist" style="width:800px;height:370px"></table> <div style="margin-top:10px"><a href="javascript:void(0)" class="easyui-linkbutton" onclick="save()">保存</a></div> </div> </body> </html>
其中,treegrid初始化时加载的URL的代码如下,实现了默认加载节点
@RequestMapping(params = "method=getTreePlan") @ResponseBody public List<Map<String,Object>> getTreePlan(HttpServletRequest request, HttpServletResponse response) throws Exception { String id = request.getParameter("id"); List<Map<String, Object>> list1 = new ArrayList<Map<String,Object>>(); if("0".equals(id)) { //data:[{"id":1,"planid":0,"contentitem":"新增方案名称","contentitemno":1,"pid":-1,"selfid":1,"createtime":{"date":25,"day":1,"hours":16,"minutes":38,"month":3,"nanos":0,"seconds":59,"time":1461573539000,"timezoneOffset":-480,"year":116}}], JSONObject dateJson = JSONObject.fromObject(new Date()); String jsonData = "{'contentitem':'新增环节名称1','contentitemno':1,'createtime':"+dateJson+",'id':1,'pid':-1,'planid':'','selfid':1," + "'children':[{'contentitem':'新增环节名称101','contentitemno':1,'createtime':"+dateJson+",'id':101,'pid':1,'planid':'','selfid':101}," + "{'contentitem':'新增环节名称102','contentitemno':2,'createtime':"+dateJson+",'id':102,'pid':1,'planid':'','selfid':102}" + "]}"; list1.add(parseJSON2Map(jsonData)); } else { Map map = new HashMap(); map.put("id", id); List<Map<String,Object>> menuNodes = new ArrayList<Map<String,Object>>(); JSONArray ja = this.manager.getPrePlanTree(map); Iterator<JSONObject> it =ja.iterator(); while(it.hasNext()){ JSONObject json2 = it.next(); list1.add(parseJSON2Map(json2.toString())); } } return list1; }
三、效果图
四、后台保存方法
1、controller代码
@RequestMapping @ResponseBody public Map savePrePlan(HttpServletRequest request,HttpServletResponse response, String commitData) throws IOException { //[{"id":"0","planname":"254","plantypecode":"交通事故","plantype":"交通事故","planlevelcode":"二级预案","planlevel":"二级预案","keyword":""}, {"id":1,"planid":0,"contentitem":"新增方案名称","contentitemno":1,"pid":-1,"selfid":1,"createtime":{"date":25,"day":1,"hours":16,"minutes":38,"month":3,"nanos":0,"seconds":59,"time":1461573539000,"timezoneOffset":-480,"year":116}}] //{"id":"0","planname":"1111","plantypecode":"交通事故","plantype":"交通事故","planlevelcode":"二级预案","planlevel":"二级预案","keyword":""},{"id":101,"planid":null,"contentitem":"新增环节1","contentitemno":1,"pid":"1","selfid":101,"createtime":"2016-05-09T06:07:28.317Z"},{"id":10101,"planid":null,"contentitem":"新增环节1.1","contentitemno":1,"pid":101,"selfid":10101,"createtime":"2016-05-09T06:07:35.466Z"},{"id":10102,"planid":null,"contentitem":"新增环节1.2","contentitemno":1,"pid":101,"selfid":10102,"createtime":"2016-05-09T06:07:41.442Z"},{"id":102,"planid":null,"contentitem":"新增环节","contentitemno":1,"pid":"1","selfid":102,"createtime":"2016-05-09T06:07:47.846Z"},{"id":null,"planid":null,"contentitem":"新增预案名称1","contentitemno":"1","pid":"-1","selfid":"1","createtime":"2016-05-09T06:07:55.255Z"} //将字符串转成json数组 JSONArray jsonArray = JSONArray.fromObject("["+commitData+"]" ); if(jsonArray.size()>0){ //步骤一,获取附件 MultipartHttpServletRequest mrequest = (MultipartHttpServletRequest) request; MultipartFile multipartFile = mrequest.getFile("attchment"); File file = null; if(StringUtils.isNotEmpty(multipartFile.getOriginalFilename())) { //获取file文件 CommonsMultipartFile cmf = (CommonsMultipartFile) multipartFile; DiskFileItem dfi = (DiskFileItem)cmf.getFileItem(); file = dfi.getStoreLocation(); //验证文件大小 if (file.exists() && file.isFile()){ if(file.length()/1024/1024 > 10) return Common.messageBox("文本附件过大,请上传10M内的文件!", "0"); }else{ return Common.messageBox("文件不存在!", "0"); } } //步骤二,获取当前登录人 UserSession userSession = (UserSession) request.getSession().getAttribute("userSession"); //步骤三,处理form表单数据,转成实体 JSONObject planObject = JSONObject.fromObject(jsonArray.get(0)); PrePlan plan = (PrePlan)JSONObject.toBean(planObject,PrePlan.class); //步骤四,获取节点数据 List<PrePlanContent> contentlist=new ArrayList<PrePlanContent>();//得到预案对象 for(int i=1;i<jsonArray.size();i++){ JSONObject jsonObject = JSONObject.fromObject(jsonArray.get(i)); //把json格式的字符串,转换成json对象 //JSONArray ja = JSONArray.fromObject(jsonObject); PrePlanContent prePlanContent=(PrePlanContent)JSONObject.toBean(jsonObject,PrePlanContent.class); if(prePlanContent!=null) contentlist.add(prePlanContent); } try { //步骤五,保存数据 this.manager.savePlanContent(contentlist, plan, userSession, file); return Common.messageBox("保存成功!", "1"); } catch (Exception e) { e.printStackTrace(); String msg = e.getMessage(); if ((msg == null) || ("".equals(msg))) { msg = "NullPointerException"; } else { msg = "保存失败!"; } return Common.messageBox(msg, "0"); } } else { return Common.messageBox("获取页面数据失败!", "0"); } }
2、manager中的保存数据方法
public void savePlanContent(List<PrePlanContent> planlist,PrePlan plan, UserSession userSession, File file) throws Exception { PrePlan oldplan = null; byte[] byteData = null; if(null != file) { //转成流 InputStream ips = new FileInputStream(file); //转成字节数组 byteData = new byte[(int) file.length()]; ips.read(byteData, 0, byteData.length); } if(StringUtils.isNotEmpty(plan.getId()+"") && plan.getId() != 0){//修改 oldplan=this.dao.getPrePlanById(plan.getId()); plan.setStatuscode(oldplan.getStatuscode()); plan.setStatus(oldplan.getStatus()); plan.setCreatetime(oldplan.getCreatetime()); plan.setCreateperson(oldplan.getCreateperson()); if(null == byteData) {//修改时没上传新附件 plan.setAttachment(oldplan.getAttachment()); } else {//修改时上传新附件 plan.setAttachment(byteData); } } else{//新增 plan.setStatus("待审核"); plan.setStatuscode((long) 1); plan.setCreatetime(new Date()); plan.setAttachment(byteData); if(null!=userSession) plan.setCreateperson(userSession.getSysuser().getYhmc()); } this.dao.savePlanContent(planlist, plan); }
3、dao方法
@Transactional public Long savePlanContent(List<PrePlanContent> planlist,PrePlan plan) throws Exception { long count = 0; //新增预案 if(plan.getId()==null || plan.getId() == 0){ //plan.setAttachment(byteData); count = (Long) getCurrentSession().save(plan); //对预案内容的planid进行设置 for(int i=0;i<planlist.size();i++){ planlist.get(i).setId(null); planlist.get(i).setPlanid(count); getCurrentSession().save(planlist.get(i)); } }else{//修改预案 PrePlan onl = (PrePlan) getCurrentSession().merge(plan); getCurrentSession().update(onl); this.getCurrentSession().createQuery("delete from PrePlanContent where planid="+onl.getId()).executeUpdate(); for(int i=0;i<planlist.size();i++){ planlist.get(i).setPlanid(onl.getId()); PrePlanContent current=planlist.get(i); count=(Long)getCurrentSession().save(current); } } return count; }
五、实现下载数据库保存的二进制文件
@RequestMapping public void downloadAttachment(String id, HttpServletRequest request,HttpServletResponse response) throws Exception { PrePlan p = new PrePlan(); OutputStream ops = null; try { p = manager.getPrePlanById(Long.parseLong(id)); //查出存储二进制文件的实体 try { ops = response.getOutputStream(); BufferedOutputStream stream = new BufferedOutputStream(ops); // 输出内容文件流,提供下载 response.reset(); response.setContentType("application/x-msdownload"); // 文件名 String fileName ="【"+p.getPlanname()+"】文本附件.docx"; String name = "attachment; filename=\"" + fileName + "\""; response.addHeader("Content-Disposition", new String(name.getBytes("gb2312"), "iso-8859-1")); stream.write(p.getAttachment()); } catch (Exception ex) { ex.printStackTrace(); } finally { ops.close(); } } catch (Exception e) { e.printStackTrace(); } }
时间: 2024-10-03 14:45:15