1、基于最新的ExtJS 5.1免费无限制版本开发。
2、支持MySQL、SQL Server、Oracle、DB2等关系数据库。
3、本系统可作为OA、网站、电子政务、ERP、CRM等基于B/S架构的应用软件系统的快速开发框架。
源码有50多M(包括Jar包和SQL文件),点此获取。咨询QQ:1345523590(咨询和技术支持)
二、特色功能
1、采用Spring MVC的静态加载缓存功能,在首页将Javascript文件、CSS文件和图片等静态资源文件加载进来放进内存,极大提高ExtJS的加载速度。
2、增加新的ExtJS Neptune Theme,让系统显得时髦,更具现代感,创造最佳的应用体验和多浏览器支持。
3、分别封装了模型层、控制层、业务逻辑层和数据持久层的通用操作模块,层次分明,大大减少代码冗余,二次开发效率高。
三、图片欣赏
1、修改信息
2、ExtJS的HtmlEditor的图片文件上传插件。
3、Grid列表,包含添加、删除、批量删除、修改、查看、图片查看等功能。
4、按条件查询列表。
5、导入Excel数据,支持xlsx和xls文件。
6、用户管理列表。
7、 权限管理。不仅可管理各个功能模块的权限,也可以管理功能模块里的页面按钮权限。
8、报表统计。
9、采用开源的互动地图Javascript库Leaflet,处理自定义在线地图。Panel里包含2个组件,在2个组件间传递参数显示数据。
四、开发工具和采用技术
1、开发工具:Eclipse、MyEclipse等IDE。
2、采用ExtJS 5.1无限制免费版本,放心用于网站开发。
3、采用Spring MVC 4.0.9。
4、采用Hibernate 4.3.8。
5、Hibernate集成二级缓存框架Ehcache。
6、数据库是MySQL 5,Hibernate的Dialect可使程序移植到其他数据库。
7、采用开源的互动地图Javascript库Leaflet,处理自定义在线地图。
五、代码结构
部分代码作用:
1、BaseParameter、ExtJSBaseController、BaseService、BaseDao:分别封装了模型层、控制层、业务逻辑层和数据持久层的通用操作模块。
2、ListView、PageView和QueryResult:作为ExtJS的后台分页模块。
3、SystemInitListener:加载以XML格式的数据字典,放进内存供调用。
4、LoginFilter:处理登录各种情况,将session为null的操作重定向到登录页面。
5、CustomDateEditor:处理日期参数并注册到控制器里,否则Spring MVC的参数处理将出错。
6、ExceptionCode、ServiceException:处理异常信息。
7、CacheFactory:处理Ehcache二级缓存。
8、还有其他很多工具类等等。
六、技术要点讲解
1、处理POST和GET的中文乱码问题。
1.1、POST的中文乱码处理可在web.xml上加上Spring提供的字符编码处理Filter。
- <filter>
- <filter-name>characterEncoding</filter-name>
- <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
- <init-param>
- <param-name>encoding</param-name>
- <param-value>UTF-8</param-value>
- </init-param>
- <init-param>
- <param-name>forceEncoding</param-name>
- <param-value>true</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>characterEncoding</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
1.2、GET的中文乱码处理可继承HttpServletRequestWrapper建立一个类来处理request。不用在应用服务器里设置URIEncoding。
- package core.web;
- import java.io.UnsupportedEncodingException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletRequestWrapper;
- public class GetHttpServletRequestWrapper extends HttpServletRequestWrapper {
- private String charset = "UTF-8";
- public GetHttpServletRequestWrapper(HttpServletRequest request) {
- super(request);
- }
- /**
- * 获得被装饰对象的引用和采用的字符编码
- *
- * @param request
- * @param charset
- */
- public GetHttpServletRequestWrapper(HttpServletRequest request, String charset) {
- super(request);
- this.charset = charset;
- }
- /**
- * 调用被包装的请求对象的getParameter方法获得参数,然后再进行编码转换
- */
- public String getParameter(String name) {
- String value = super.getParameter(name);
- value = value == null ? null : convert(value);
- return value;
- }
- public String convert(String target) {
- try {
- return new String(target.trim().getBytes("ISO-8859-1"), charset);
- } catch (UnsupportedEncodingException e) {
- return target;
- }
- }
- }
2、开发ExtJS的HtmlEditor的图片文件上传插件。建议:不要在ExtJS里集成百度编辑器、KindEditor或CKEditor等HTML编辑器,因为在某种情况下会遇到界面扭曲、浏览器兼容问题。
2.1、ExtJS的图片文件上传插件界面如下。
2.2.1、ExtJS的图片文件上传插件Javascript代码如下。
- Ext.define('Ext.ux.custom.ImageHtmlEditor', {
- extend : 'Ext.util.Observable',
- alias : 'widget.imagehtmleditor',
- langTitle : '插入图片',
- langIconCls : 'icon-image',
- init : function(view) {
- var scope = this;
- view.on('render', function() {
- scope.onRender(view);
- });
- },
- /**
- * 添加"插入图片"按钮
- */
- onRender : function(view) {
- var scope = this;
- view.getToolbar().add({
- iconCls : scope.langIconCls,
- tooltip : {
- title : scope.langTitle,
- width : 160,
- text : '上传本地图片或链接网络图片'
- },
- handler : function() {
- scope.showImgWindow(view);
- }
- });
- },
- /**
- * 显示"插入图片"窗体
- */
- showImgWindow : function(view) {
- var scope = this;
- Ext.create('Ext.window.Window', {
- width : 400,
- height : 310,
- title : scope.langTitle,
- layout : 'fit',
- autoShow : true,
- modal : true,
- resizable : false,
- maximizable : false,
- constrain : true,
- plain : true,
- enableTabScroll : true,
- border : false,
- items : [ {
- xtype : 'tabpanel',
- enableTabScroll : true,
- bodyPadding : 10,
- items : [ {
- title : '上传本地图片',
- items : [ {
- xtype : 'form',
- layout : 'column',
- autoScroll : true,
- border : false,
- defaults : {
- columnWidth : 1,
- labelWidth : 80,
- labelAlign : 'left',
- padding : 5,
- allowBlank : false
- },
- items : [ {
- xtype : 'fileuploadfield',
- fieldLabel : '选择文件',
- afterLabelTextTpl : '<span style="color:#FF0000;">*</span>',
- buttonText : '请选择...',
- name : 'uploadAttachment',
- emptyText : '请选择图片',
- blankText : '图片不能为空',
- listeners : {
- change : function(view, value, eOpts) {
- scope.uploadImgCheck(view, value);
- }
- }
- }, {
- xtype : 'fieldcontainer',
- fieldLabel : '图片大小',
- layout : 'hbox',
- defaultType : 'numberfield',
- defaults : {
- flex : 1,
- labelWidth : 20,
- labelAlign : 'left',
- allowBlank : true
- },
- items : [ {
- fieldLabel : '宽',
- name : 'width',
- minValue : 1
- }, {
- fieldLabel : '高',
- name : 'height',
- minValue : 1
- } ]
- }, {
- xtype : 'textfield',
- fieldLabel : '图片说明',
- name : 'content',
- allowBlank : true,
- maxLength : 100,
- emptyText : '简短的图片说明'
- }, {
- columnWidth : 1,
- xtype : 'fieldset',
- title : '上传须知',
- layout : {
- type : 'table',
- columns : 1
- },
- collapsible : false,// 是否可折叠
- defaultType : 'label',// 默认的Form表单组件
- items : [ {
- html : '1、上传图片大小不超过2MB.'
- }, {
- html : '2、支持以下格式的图片:jpg,jpeg,png,gif,bmp.'
- } ]
- } ],
- buttons : [ '->', {
- text : '保存',
- action : 'btn_save',
- iconCls : 'icon-save',
- handler : function(btn) {
- scope.saveUploadImg(btn, view);
- }
- }, {
- text : '取消',
- iconCls : 'icon-cancel',
- handler : function(btn) {
- btn.up('window').close();
- }
- }, '->' ]
- } ]
- }, {
- title : '链接网络图片',
- items : [ {
- xtype : 'form',
- layout : 'column',
- autoScroll : true,
- border : false,
- defaults : {
- columnWidth : 1,
- labelWidth : 80,
- labelAlign : 'left',
- padding : 5,
- allowBlank : false
- },
- items : [ {
- xtype : 'textfield',
- fieldLabel : '图片地址',
- afterLabelTextTpl : '<span style="color:#FF0000;">*</span>',
- name : 'url',
- emptyText : '请填入支持外链的长期有效的图片URL',
- blankText : '图片地址不能为空',
- vtype : 'url'
- }, {
- xtype : 'fieldcontainer',
- fieldLabel : '图片大小',
- layout : 'hbox',
- defaultType : 'numberfield',
- defaults : {
- flex : 1,
- labelWidth : 20,
- labelAlign : 'left',
- allowBlank : true
- },
- items : [ {
- fieldLabel : '宽',
- name : 'width',
- minValue : 1
- }, {
- fieldLabel : '高',
- name : 'height',
- minValue : 1
- } ]
- }, {
- xtype : 'textfield',
- fieldLabel : '图片说明',
- name : 'content',
- allowBlank : true,
- maxLength : 100,
- emptyText : '简短的图片说明'
- } ],
- buttons : [ '->', {
- text : '保存',
- action : 'btn_save',
- iconCls : 'icon-save',
- handler : function(btn) {
- scope.saveRemoteImg(btn, view);
- }
- }, {
- text : '取消',
- iconCls : 'icon-cancel',
- handler : function(btn) {
- btn.up('window').close();
- }
- }, '->' ]
- } ]
- } ]
- } ]
- });
- },
- /**
- * 上传图片验证
- */
- uploadImgCheck : function(fileObj, fileName) {
- var scope = this;
- // 图片类型验证
- if (!(scope.getImgTypeCheck(scope.getImgHZ(fileName)))) {
- globalObject.errTip('上传图片类型有误!');
- fileObj.reset();// 清空上传内容
- return;
- }
- },
- /**
- * 获取图片后缀(小写)
- */
- getImgHZ : function(imgName) {
- // 后缀
- var hz = '';
- // 图片名称中最后一个.的位置
- var index = imgName.lastIndexOf('.');
- if (index != -1) {
- // 后缀转成小写
- hz = imgName.substr(index + 1).toLowerCase();
- }
- return hz;
- },
- /**
- * 图片类型验证
- */
- getImgTypeCheck : function(hz) {
- var typestr = 'jpg,jpeg,png,gif,bmp';
- var types = typestr.split(',');// 图片类型
- for (var i = 0; i < types.length; i++) {
- if (hz == types[i]) {
- return true;
- }
- }
- return false;
- },
- /**
- * 上传图片
- */
- saveUploadImg : function(btn, view) {
- var scope = this;
- var windowObj = btn.up('window');// 获取Window对象
- var formObj = btn.up('form');// 获取Form对象
- if (formObj.isValid()) { // 验证Form表单
- formObj.form.doAction('submit', {
- url : appBaseUri + '/sys/forestrytype/uploadAttachement',
- method : 'POST',
- submitEmptyText : false,
- waitMsg : '正在上传图片,请稍候...',
- timeout : 60000, // 60s
- success : function(response, options) {
- var result = options.result;
- if (!result.success) {
- globalObject.errTip(result.msg);
- return;
- }
- var url = result.data;
- var content = formObj.getForm().findField("content").getValue();
- var width = formObj.getForm().findField("width").getValue();
- var height = formObj.getForm().findField("height").getValue();
- var values = {
- url : appBaseUri + '/static/img/upload/' + url,
- content : content,
- width : width,
- height : height
- };
- scope.insertImg(view, values);
- windowObj.close();// 关闭窗体
- },
- failure : function(response, options) {
- globalObject.errTip(options.result.msg);
- }
- });
- }
- },
- /**
- * 保存远程的图片
- */
- saveRemoteImg : function(btn, view) {
- var scope = this;
- var windowObj = btn.up('window');// 获取Window对象
- var formObj = btn.up('form');// 获取Form对象
- if (formObj.isValid()) {// 验证Form表单
- var values = formObj.getValues();// 获取Form表单的值
- scope.insertImg(view, values);
- windowObj.close();// 关闭窗体
- }
- },
- /**
- * 插入图片
- */
- insertImg : function(view, data) {
- var url = data.url;
- var content = data.content;
- var width = data.width;
- var height = data.height;
- var str = '<img src="' + url + '" border="0" ';
- if (content != undefined && content != null && content != '') {
- str += ' title="' + content + '" ';
- }
- if (width != undefined && width != null && width != 0) {
- str += ' width="' + width + '" ';
- }
- if (height != undefined && height != null && height != 0) {
- str += ' height="' + height + '" ';
- }
- str += ' />';
- view.insertAtCursor(str);
- }
- });
2.2.2、ExtJS的图片文件上传插件Java后台代码如下。Spring MVC对文件上传已有直接处理,不用再自写文件上传组件。
- @RequestMapping(value = "/uploadAttachement", method = RequestMethod.POST)
- public void uploadAttachement(@RequestParam(value = "uploadAttachment", required = false) MultipartFile file, HttpServletRequest request, HttpServletResponse response) throws Exception {
- RequestContext requestContext = new RequestContext(request);
- JSONObject json = new JSONObject();
- if (!file.isEmpty()) {
- if (file.getSize() > 2097152) {
- json.put("msg", requestContext.getMessage("g_fileTooLarge"));
- } else {
- try {
- String originalFilename = file.getOriginalFilename();
- String fileName = sdf.format(new Date()) + ForestryUtils.getRandomString(3) + originalFilename.substring(originalFilename.lastIndexOf("."));
- File filePath = new File(getClass().getClassLoader().getResource("/").getPath().replace("/WEB-INF/classes/", "/static/img/upload/" + DateFormatUtils.format(new Date(), "yyyyMM")));
- if (!filePath.exists()) {
- filePath.mkdirs();
- }
- file.transferTo(new File(filePath.getAbsolutePath() + "\\" + fileName));
- json.put("success", true);
- json.put("data", DateFormatUtils.format(new Date(), "yyyyMM") + "/" + fileName);
- json.put("msg", requestContext.getMessage("g_uploadSuccess"));
- } catch (Exception e) {
- e.printStackTrace();
- json.put("msg", requestContext.getMessage("g_uploadFailure"));
- }
- }
- } else {
- json.put("msg", requestContext.getMessage("g_uploadNotExists"));
- }
- writeJSON(response, json.toString());
- }
3、继承Ext.grid.Panel重写列表组件,在toolbar上定义全局通用的“添加”、“导入”、“删除”等功能点,减少了代码冗余。
- Ext.define('Ext.ux.custom.GlobalGridPanel', {
- extend : 'Ext.grid.Panel',
- alias : 'widget.globalgrid',
- xtype : 'cell-editing',
- initComponent : function() {
- var me = this;
- var singleId;
- var uniqueID = me.cName + (me.cId ? me.cId : '') + (me.myId ? me.myId : '');
- this.cellEditing = Ext.create('Ext.grid.plugin.CellEditing', {
- clicksToEdit : 2
- });
- var tbarMenus = new Array();
- if (globalObject.haveActionMenu(me.cButtons, 'Add')) {
- tbarMenus.push({
- xtype : 'button',
- itemId : 'btnAdd',
- iconCls : 'icon-add',
- text : '添加',
- scope : this,
- handler : me.onAddClick
- });
- }
- if (globalObject.haveActionMenu(me.cButtons, 'Import')) {
- tbarMenus.push({
- xtype : 'button',
- itemId : 'btnImport',
- iconCls : 'icon-excel',
- text : '导入',
- scope : this,
- handler : me.onImportClick
- });
- }
- if (globalObject.haveActionMenu(me.cButtons, 'Delete')) {
- tbarMenus.push({
- xtype : 'button',
- itemId : 'btnDelete',
- iconCls : 'icon-delete',
- text : '删除',
- scope : this,
- disabled : true,
- handler : me.onDeleteClick
- });
- }
- if (globalObject.haveActionMenu(me.cButtons, 'Export')) {
- tbarMenus.push({
- xtype : 'splitbutton',
- itemId : 'btnImport',
- text : '导出',
- scope : this,
- handler : function() {
- me.onExportClick(false);
- },
- menu : [ {
- text : '导出(包括隐藏列)',
- handler : function() {
- me.onExportClick(true);
- }
- }, {
- text : '导出选中数据',
- handler : function() {
- me.onExportClick(false, true);
- }
- }, {
- text : '导出选中数据(包括隐藏列)',
- handler : function() {
- me.onExportClick(true, true);
- }
- } ]
- });
- }
- if (tbarMenus.length == 0)
- me.hideTBar = true;
- this.ttoolbar = Ext.create('Ext.toolbar.Toolbar', {
- hidden : me.hideTBar || false,
- items : tbarMenus
- });
- Ext.apply(this, {
- stateful : me.cName ? true : false,
- stateId : me.cName ? (uniqueID + 'gird') : null,
- enableColumnMove : me.cName ? true : false,
- plugins : this.plugins,
- selModel : Ext.create('Ext.selection.CheckboxModel'),
- border : false,
- tbar : this.ttoolbar,
- bbar : me.hideBBar ? null : Ext.create('Ext.PagingToolbar', {
- store : me.getStore(),
- displayInfo : true
- }),
- listeners : {
- itemdblclick : function(dataview, record, item, index, e) {
- me.onViewClick();
- }
- }
- });
- this.getSelectionModel().on('selectionchange', function(sm, records) {
- if (me.down('#btnDelete'))
- me.down('#btnDelete').setDisabled(sm.getCount() == 0);
- });
- this.callParent(arguments);
- },
- createStore : function(config) {
- Ext.applyIf(this, config);
- return Ext.create('Ext.data.Store', {
- model : config.modelName,
- // autoDestroy: true,
- // autoLoad: true,
- remoteSort : true,
- pageSize : globalPageSize,
- proxy : {
- type : 'ajax',
- url : config.proxyUrl,
- extraParams : config.extraParams || null,
- reader : {
- type : 'json',
- root : 'data',
- totalProperty : 'totalRecord',
- successProperty : "success"
- }
- },
- sorters : [ {
- property : config.sortProperty || 'id',
- direction : config.sortDirection || 'DESC'
- } ]
- });
- },
- getTabId : function() {
- return this.up('panel').getId();
- },
- onAddClick : function() {
- },
- onEditClick : function() {
- },
- onImportClick : function() {
- },
- onViewClick : function() {
- },
- onDeleteClick : function() {
- var me = this;
- globalObject.confirmTip('删除的记录不可恢复,继续吗?', function(btn) {
- if (btn == 'yes') {
- var s = me.getSelectionModel().getSelection();
- var ids = [];
- var idProperty = me.idProperty || 'id';
- for (var i = 0, r; r = s[i]; i++) {
- ids.push(r.get(idProperty));
- }
- Ext.Ajax.request({
- url : me.proxyDeleteUrl,
- params : {
- ids : ids.join(',') || singleId
- },
- success : function(response) {
- if (response.responseText != '') {
- var res = Ext.JSON.decode(response.responseText);
- if (res.success) {
- globalObject.msgTip('操作成功!');
- // Ext.example.msg('系统信息', '{0}', "操作成功!");
- me.getStore().reload();
- } else {
- globalObject.errTip('操作失败!' + res.msg);
- }
- }
- }
- });
- }
- });
- },
- onExportClick : function(importHideColumn, onlySelected) {
- globalObject.exportToExcel(this, importHideColumn, onlySelected);
- }
- });
4、开发Excel数据导入模块,同时支持xls和xlsx文件,在Java后台代码对导入过程中各种条件判断和异常有严格的处理。
4.1、Excel数据导入模块的界面如下。
4.2、Excel数据导入模块的Java后台代码如下。
- private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
- @RequestMapping(value = "/importForestryFile", method = RequestMethod.POST)
- public void importForestryFile(@RequestParam(value = "importedFile", required = false) MultipartFile file, HttpServletRequest request, HttpServletResponse response) throws Exception {
- RequestContext requestContext = new RequestContext(request);
- JSONObject json = new JSONObject();
- if (!file.isEmpty()) {
- if (file.getSize() > 2097152) {
- json.put("msg", requestContext.getMessage("g_fileTooLarge"));
- } else {
- try {
- String originalFilename = file.getOriginalFilename();
- String fileName = sdf.format(new Date()) + ForestryUtils.getRandomString(3) + originalFilename.substring(originalFilename.lastIndexOf("."));
- File filePath = new File(getClass().getClassLoader().getResource("/").getPath().replace("/WEB-INF/classes/", "/static/download/attachment/" + DateFormatUtils.format(new Date(), "yyyyMM")));
- if (!filePath.exists()) {
- filePath.mkdirs();
- }
- String serverFile = filePath.getAbsolutePath() + "\\" + fileName;
- file.transferTo(new File(serverFile));
- String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
- if (!fileType.equalsIgnoreCase("xls") && !fileType.equalsIgnoreCase("xlsx")) {
- json.put("success", false);
- json.put("msg", requestContext.getMessage("g_notValidExcel"));
- writeJSON(response, json.toString());
- return;
- }
- int count = 0;
- StringBuilder stringBuilder = new StringBuilder();
- InputStream xls = new FileInputStream(serverFile);
- Workbook wb = null;
- Sheet sheet = null;
- Row currentRow = null;
- Row headRow = null;
- Cell currentCell = null;
- if (fileType.equals("xls")) {
- wb = new HSSFWorkbook(xls);
- } else if (fileType.equals("xlsx")) {
- wb = new XSSFWorkbook(xls);
- }
- sheet = wb.getSheetAt(0);// excel中至少会存在一个sheet页
- int rowNum = sheet.getPhysicalNumberOfRows();// 物理有效行数
- Object[] rowValues = null;// excel中一行树木信息
- List<Object[]> models = new ArrayList<Object[]>();// excel中全部树木信息
- if (rowNum > 1) {
- headRow = sheet.getRow(0);
- columns: for (int i = 1; i < rowNum; i++) {
- currentRow = sheet.getRow(i);
- if (currentRow != null) {
- rowValues = new Object[5];
- // int cellNum = currentRow.getLastCellNum();// 总单元格数目
- for (short j = 0; j < 5; j++) {
- try {
- currentCell = currentRow.getCell(j);
- Object obj = null;
- if (currentCell == null) {
- obj = "";
- } else {
- switch (currentCell.getCellType()) {
- case Cell.CELL_TYPE_BLANK:
- obj = "";
- break;
- case Cell.CELL_TYPE_STRING:
- obj = currentCell.getRichStringCellValue();
- break;
- case Cell.CELL_TYPE_NUMERIC:
- if (HSSFDateUtil.isCellDateFormatted(currentCell)) {
- double d = currentCell.getNumericCellValue();
- Date date = HSSFDateUtil.getJavaDate(d);
- obj = sdfDate.format(date);
- } else {
- NumberFormat nf = NumberFormat.getInstance();
- nf.setGroupingUsed(false);//true时的格式:1,234,567,890
- obj = nf.format(currentCell.getNumericCellValue());
- }
- break;
- default:
- obj = "";
- break;
- }
- }
- String cellVal = obj.toString();
- rowValues[j] = cellVal;
- } catch (IllegalStateException e) {
- rowValues = null;
- stringBuilder.append("第" + i + "行," + headRow.getCell(j).getRichStringCellValue() + "列输入了非法值,未导入成功!");
- continue columns;
- } catch (NullPointerException e) {
- rowValues = null;
- stringBuilder.append("第" + i + "行," + headRow.getCell(j).getRichStringCellValue() + "列输入了空值,未导入成功!");
- continue columns;
- } catch (Exception e) {
- rowValues = null;
- stringBuilder.append(e.getMessage());
- continue columns;
- }
- }
- if (rowValues != null) {
- models.add(rowValues);
- }
- }
- }
- } else if (rowNum <= 1 && rowNum > 0) {// 表示模版中只存在头部信息
- json.put("success", false);
- json.put("msg", "Excel表格中没有需要导入 的内容!");
- writeJSON(response, json.toString());
- return;
- } else if (rowNum <= 0) {// 表示这是一个空sheet页
- json.put("success", false);
- json.put("msg", "所导入文件格式不正确,请下载模板!");
- writeJSON(response, json.toString());
- return;
- }
- List<Forestry> list = objectToForestry(models);// Object-->Forestry
- for (int i = 0; i < list.size(); i++) {
- if (StringUtils.isBlank(list.get(i).getEpcId()) || StringUtils.isBlank(list.get(i).getName())) {
- stringBuilder.append("第" + (i + 1) + "行记录的必填项有空值,导入失败。");
- continue;
- }
- Forestry checkForestryEpcId = forestryService.getByProerties("epcId", list.get(i).getEpcId());
- if (checkForestryEpcId != null) {
- stringBuilder.append("第" + (i + 1) + "行记录的epc编码已存在,导入失败。");
- continue;
- }
- if (list.get(i).getForestryType() == null) {
- stringBuilder.append("第" + (i + 1) + "行记录的种类为空或不存在,导入失败。");
- continue;
- }
- forestryService.persist(list.get(i));
- count++;
- }
- json.put("success", true);
- json.put("msg", count + "条记录导入完成。" + stringBuilder.toString());
- } catch (Exception e) {
- e.printStackTrace();
- json.put("success", false);
- json.put("msg", requestContext.getMessage("g_operateFailure"));
- writeJSON(response, json.toString());
- }
- }
- } else {
- json.put("success", false);
- json.put("msg", requestContext.getMessage("g_uploadNotExists"));
- }
- writeJSON(response, json.toString());
- }
- private List<Forestry> objectToForestry(List<Object[]> models) {
- List<Forestry> forestryList = new ArrayList<Forestry>();
- Forestry forestry = null;
- for (int i = 0; i < models.size(); i++) {
- try {
- forestry = new Forestry();
- forestry.setEpcId(models.get(i)[0].toString());
- forestry.setName(models.get(i)[1].toString());
- if (StringUtils.isBlank(models.get(i)[2].toString())) {
- forestry.setPlantTime(null);
- } else {
- forestry.setPlantTime(sdfDate.parse(models.get(i)[2].toString()));
- }
- if (StringUtils.isBlank(models.get(i)[3].toString())) {
- forestry.setEntryTime(null);
- } else {
- forestry.setEntryTime(sdfDate.parse(models.get(i)[3].toString()));
- }
- ForestryType forestryType = forestryTypeService.getByProerties("name", models.get(i)[4].toString());
- forestry.setForestryType(forestryType);
- forestryList.add(forestry);
- } catch (Exception e) {
- e.printStackTrace();
- continue;
- }
- }
- return forestryList;
- }
5、开发权限管理。不仅可以管理功能模块的权限,也可以管理功能模块里面各个按钮的权限。
5.1、权限管理的界面如下。
5.2、权限管理的代码如下。
- // 权限管理
- Ext.define('Forestry.app.systemManage.AuthorizationManagement', {
- extend : 'Ext.panel.Panel',
- initComponent : function() {
- var me = this;
- Ext.apply(this, {
- layout : 'border',
- items : [ Ext.create('Forestry.app.systemManage.AuthorizationManagement.SysUserGrid', {
- cButtons : me.cButtons,
- cName : me.cName
- }), Ext.create('Forestry.app.systemManage.AuthorizationManagement.MenuTree') ]
- });
- this.callParent(arguments);
- }
- });
- // 角色列表
- Ext.define('Forestry.app.systemManage.AuthorizationManagement.SysUserGrid', {
- extend : 'Ext.grid.Panel',
- id : 'authorizationmanagement-sysusergrid',
- region : 'west',
- width : '18%',
- initComponent : function() {
- var me = this;
- Ext.define('SysUserRoleList', {
- extend : 'Ext.data.Model',
- idProperty : 'role',
- fields : [ {
- name : 'role',
- type : 'short'
- }, 'roleName' ]
- });
- var sysusergridstore = Ext.create('Ext.data.Store', {
- model : 'SysUserRoleList',
- // autoDestroy: true,
- autoLoad : true,
- remoteSort : true,
- pageSize : globalPageSize,
- proxy : {
- type : 'ajax',
- url : appBaseUri + '/sys/sysuser/getRoleNameList',
- extraParams : me.extraParams || null,
- reader : {
- type : 'json',
- root : 'data',
- totalProperty : 'totalRecord',
- successProperty : "success"
- }
- }
- });
- var sysusergridcolumns = [ {
- text : "roleId",
- dataIndex : 'role',
- hidden : true,
- sortable : false,
- editor : {
- allowBlank : false
- }
- }, {
- text : "角色",
- dataIndex : 'roleName',
- sortable : false,
- width : '85%',
- editor : {
- allowBlank : false
- }
- } ];
- Ext.apply(this, {
- store : sysusergridstore,
- selModel : Ext.create('Ext.selection.CheckboxModel'),
- columns : sysusergridcolumns,
- listeners : {
- 'itemclick' : function(item, record) {
- me.currentRole = record.get('role');
- Ext.getCmp('authorizationmanagement-rolemenu').getStore().load({
- params : {
- 'role' : me.currentRole
- }
- });
- }
- }
- });
- this.callParent(arguments);
- }
- });
- // 树形菜单
- Ext.define('Forestry.app.systemManage.AuthorizationManagement.MenuTree', {
- extend : 'Ext.tree.Panel',
- id : 'authorizationmanagement-rolemenu',
- plain : true,
- border : true,
- region : 'center',
- autoScroll : true,
- initComponent : function() {
- var me = this;
- var menutreestore = Ext.create('Ext.data.TreeStore', {
- autoLoad : true,
- proxy : {
- type : 'ajax',
- url : appBaseUri + '/sys/authority/getAuthorizationList',
- reader : {
- type : 'json',
- root : 'children'
- }
- }
- });
- Ext.apply(this, {
- // title : '菜单权限',
- store : menutreestore,
- rootVisible : false,
- tbar : [ {
- xtype : 'button',
- iconCls : 'icon-save',
- text : '保存菜单权限',
- scope : this,
- handler : me.saveMenuPermission
- } ]
- });
- this.callParent(arguments);
- },
- saveMenuPermission : function() {
- var me = this;
- var roleId = Ext.getCmp('authorizationmanagement-sysusergrid').currentRole;
- if (!roleId) {
- globalObject.infoTip('请先选择角色!');
- return;
- };
- var s = me.getChecked();
- var ids = [];
- for (var i = 0, r; r = s[i]; i++) {
- if (r.get('id') != 'root')
- ids.push(r.get('id'));
- }
- me.setLoading('权限保存中...');
- Ext.Ajax.request({
- url : appBaseUri + '/sys/roleauthority/saveRoleAuthority',
- params : {
- ids : ids.join(','),
- role : roleId
- },
- success : function(response) {
- me.setLoading(false);
- var res = Ext.JSON.decode(response.responseText);
- if (res && !res.success) {
- Ext.Msg.alert('出错信息', res.msg);
- } else {
- globalObject.msgTip('保存成功!');
- }
- },
- failure : function(response, opts) {
- me.setLoading(false);
- Ext.Msg.alert('出错信息', '操作失败!');
- }
- });
- }
- });
源码有50多M(包括Jar包和SQL文件)