# 灌溉管理系统 **Repository Path**: zrsr/irrigation-management-system ## Basic Information - **Project Name**: 灌溉管理系统 - **Description**: 云智能灌溉管理系统 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: v2 - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2021-08-03 - **Last Updated**: 2025-03-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 更新日志 ## 2020年1月8日 + 修复图像重叠问题(类里面的变量在整个类里都可以访问到,方法里的变量只能方法里能访问到,可见范围不一样。 如果是多线程的话,类里面的变量可能会引发线程安全的问题,而方法里的变量不会,因为方法里的变量是在线程栈上的,每个线程都是互相独立的。) ## 2020年1月2日 + 账户注册时邮件发送验证 ## 2019年12月30日 + TIS图片展示页面与js使用数据双向绑定方式,使用way.js ## 2019年12月28日 + 删除TIS沉淀功能 ## 2019年12月26日 + 列表展示页数table方式更改为:#set(aTh = ["名称","创建时间"],aTd = ["name","createAt"]),替换之前的名称 #define cardIndexTbody() #(x.name)#(x.createAt) #end # resources/config 配置文件介绍 + mail.setting 邮件发送配置 + host = smtp.exmail.qq.com 邮件服务器的SMTP地址 + port = 465 邮件服务器的SMTP端口 + from = ce@hjnsz.com 发件人(必须正确,否则发送失败) + user = ce@hjnsz.com 用户名(注意:如果使用foxmail邮箱,此处user为qq号) + pass = sA7xs78kkrscXez6 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助) + starttlsEnable = true 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。 + sslEnable = true 使用SSL安全连接 + socketFactoryClass = javax.net.ssl.SSLSocketFactory 指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 + socketFactoryFallback = true 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true + socketFactoryPort = 465 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口456 + timeout = 0 SMTP超时时长,单位毫秒,缺省值不超时 + connectionTimeout = 0 Socket连接超时值,单位毫秒,缺省值不超时 + cron.setting 任务调度配置 + [com.zr.jmis.sensor.equipment] 包路径 + EquipmentController.task=0/5 * * * * * EquipmentController.task类与方法 # 系统界面 + 登陆 ![](static/登陆.jpg) + 后台首页 ![](static/后台首页.jpg) + 界面 ![](static/界面.jpg) # JMIS系统开发 ## index.html 例子 ```html #@adminLayout() #define main() ###页面显示的按钮 C:增加按钮,R:查询按钮,U:修改按钮,D:删除按钮,W:清空查询按钮,I:Excel导入按钮,E:Excel导出按钮 #set(map={C:1,R:1,U:1,D:1,I:1,E:1},aTh = ["编号", "名称", "位置", "创建时间", "创建人" ],aTd = [ "code", "name", "position", "createAt", "createAc" ])
#@cardIndex("仓库设置管理","erp/erpwarehouse",map,aTh,aTd)
#end ###自定义按钮,不需要删除即可 #define cardBtn() #end ###条件模糊查询 不需要删除即可 #define cardQuery()
名称
#end ###自定义表格数据内容,如果使用目前方式,导出功能的数据需要自定义,不需要删除即可 #define cardIndexTbody #end ###表格上方自定义按钮 不需要删除即可 #define cardBtn() #end ###表格自定义按钮 不需要删除即可 #define cardIndexBtn() #end ``` ## index.html 注意CRUDEW:增加Create、读取Read、更新Update、删除Delete、导出export、擦wipe + 页面引用 @adminLayout() #end + 页面主体 #define main() + 顶部按钮 #set(map={C:1,R:1,U:1,D:1,I:1,E:1},aTh = ["名称","创建时间"],aTd = ["name","createAt"]) + R 查询按钮 ![](static/read.jpg) + W 清空查询按钮 ![](static/wipe.jpg) + D 删除按钮 ![](static/delete.jpg) + C 增加按钮 ![](static/create.jpg) + U 修改按钮 ![](static/update.jpg) + I Excel导入按钮 ![](static/import.jpg) + E Excel导出按钮 ![](static/export.jpg) + aTh 数据表格的头 + aTd 数据表格的数据 + 引用index的模板 #@cardIndex("角色管理","sys/role",map,aTh,aTd) + 角色管理 页面显示的信息 + sys/role 请求的路径 + 自定义按钮 #define cardBtn() #end + 查询字段 #define cardQuery() #end + 自定义操作中的按钮 #define cardIndexBtn() #end ## add_edit.html 例子 ```html #@adminLayout() #define main()
#@cardAddOrEdit("角色管理 / "+(model?"修改":"新增"),"sys/role")
#end #define cardCol()
名称
#@zTree("类别","erpMaterial.categoriesId","/admin/erp/erpcategories/queryCategories")
#end ``` ## add_edit.html 注意 + 页面引用 #@adminLayout() #end + 页面主体 #define main() + 页面信息显示 #@cardAddOrEdit("角色管理 / "+(model?"修改":"新增"),"sys/role") + 客户端管理 页面显示的名称 + sys/role 页面请求的路径 + 自定义添加或编辑的字段 #define cardCol() #end + zTree 树形选择三位参数,参数一:title,参数二:name,参数三:url ![](static/ztree.png) ## xxxAdminController.java 控制器 ```java package com.zr.jmis.erp.warehouse; import cn.hutool.core.date.DateUtil; import com.jfinal.aop.Before; import com.jfinal.aop.Inject; import com.jfinal.plugin.activerecord.Record; import com.zr.jmis.basic.base.BaseController; import com.zr.jmis.basic.kit.JmisKit; import com.zr.jmis.sys.permission.Notes; import com.zr.jmis.sys.permission.Remark; import java.util.Date; /** * 仓库设置管理控制器 * 描述: * * @author 冉志林 */ public class ErpWarehouseAdminController extends BaseController { @Inject ErpWarehouseAdminService srv; @Notes(value = "仓库设置管理") @Remark(value = "仓库设置列表") public void index() { ErpWarehouse mode = getModel(ErpWarehouse.class, "", true); kModel(mode, srv.paginate(getInt(PAGENUMBER, 1), getInt(PAGESIZE, 10), mode)); } @Remark(value = "仓库设置添加或编辑页") public void addOrEdit(Integer id) { kAddOrEdit(srv.findById(id)); } @Remark(value = "仓库设置保存或修改") @Before(ErpWarehouseAdminValidator.class) public void saveOrUpdate() { ErpWarehouse bean = getBean(ErpWarehouse.class); bean.setCreateAc(getLoginAccountId()); bean.setCreateAt(new Date()); renderJson(srv.saveOrUpdate(bean)); } @Remark(value = "仓库设置删除") public void deletes(String ids) { renderJson(srv.deletes(ids)); } @Remark(value = "仓库设置文件导入") public void importData() { Record record=new Record().set("createAt",new Date()).set("createAc",getLoginAccountId()); kImport(srv.getTable(),record); } @Remark(value = "仓库设置文件导出") public void exportData(String fileName, String aThs, String aTds, String ids) { kFile(srv.export(DateUtil.format(new Date(), "yyyyMMddHHmmss") + getLoginAccount().getFullName() + fileName, JmisKit.replaceBrackets(aThs), JmisKit.replaceBrackets(aTds), ids)); } @Remark(value = "仓库设置文件下载") public void download(String fileName) { kDownLoad(fileName); } } ``` ## xxxAdminService.java 业务处理 ```java package com.zr.jmis.erp.warehouse; import com.jfinal.plugin.activerecord.Model; import com.zr.jmis.basic.base.BaseService; /** * 仓库设置 管理 * 描述: * * @author 冉志林 */ public class ErpWarehouseAdminService extends BaseService { private ErpWarehouse dao = new ErpWarehouse().dao(); @Override public Model getDao() { return dao; } } ``` ## xxxAdminValidator.java 验证 ```java package com.zr.jmis.erp.warehouse; import com.jfinal.core.Controller; import com.zr.jmis.basic.base.BaseValidator; /** * ErpWarehouseAdminValidator 验证仓库设置功能表单 * * @author 冉志林 */ public class ErpWarehouseAdminValidator extends BaseValidator { @Override protected void validate(Controller c) { setShortCircuit(true); validateRequiredString("erpWarehouse.code", "msg", "编号不能为空"); validateRequiredString("erpWarehouse.name", "msg", "名称不能为空"); validateRequiredString("erpWarehouse.position", "msg", "位置不能为空"); } @Override protected void handleError(Controller c) { c.setAttr("state", "fail"); c.renderJson(); } } ``` ## xxxDirective 权限控制 ```java package com.zr.jmis.sys.sys.role; import com.jfinal.aop.Aop; import com.jfinal.template.Directive; import com.jfinal.template.Env; import com.jfinal.template.io.Writer; import com.jfinal.template.stat.Scope; import com.zr.jmis.basic.model.SysAccount; import com.zr.jmis.basic.sys.login.LoginService; import com.zr.jmis.sys.auth.AdminAuthService; /** * 界面上的权限控制功能 用来控制界面上的菜单、按钮等等元素的显示 * *

使用示例见模板文件: /_view/_admin/common/_menu.html 或者 /_view/_admin/permission/index.html * #role("权限管理员") ... #end */ public class RoleDirective extends Directive { static AdminAuthService adminAuthSrv = Aop.get(AdminAuthService.class); @Override public void exec(Env env, Scope scope, Writer writer) { SysAccount account = (SysAccount) scope.getRootData().get(LoginService.LOGIN_ACCOUNT_CACHE_NAME); if (account != null && account.isStatusOk()) { // 如果是超级管理员,或者拥有指定的角色则放行 if (adminAuthSrv.isSuperAdmin(account.getId()) || adminAuthSrv.hasRole(account.getId(), getRoleNameArray(scope))) { stat.exec(env, scope, writer); } } } /** * 从 #role 指令参数中获取角色名称数组 */ private String[] getRoleNameArray(Scope scope) { Object[] values = exprList.evalExprList(scope); String[] ret = new String[values.length]; for (int i = 0; i < values.length; i++) { if (values[i] instanceof String) { ret[i] = (String) values[i]; } else { throw new IllegalArgumentException("角色名只能为 String 类型"); } } return ret; } @Override public boolean hasEnd() { return true; } } ``` ## 树形table ```java package com.zr.jmis.erp.stocksort; import com.jfinal.aop.Before; import com.jfinal.aop.Inject; import com.jfinal.plugin.activerecord.Record; import com.zr.jmis.basic.base.BaseController; import com.zr.jmis.basic.kit.JmisKit; import com.zr.jmis.sys.permission.Notes; import com.zr.jmis.sys.permission.Remark; /** * 存货分类管理控制器 * 描述: * * @author 冉志林 */ public class ErpStockSortAdminController extends BaseController { @Inject ErpStockSortAdminService srv; @Notes(value = "存货分类管理") @Remark(value = "存货分类列表页") public void index(){ kIndex(); } @Remark(value = "存货分类数据") public void treeList(){ renderJson(srv.findAll()); } @Remark(value = "采购分类添加或编辑") @Before(ErpStockSortAdminValidator.class) public void saveOrUpdate(Integer pId,String name) { renderJson(srv.dbSaveOrUpdate(srv.getTable(), new Record().set("pId", pId).set("name", name))); } @Remark(value = "采购分类刪除") public void delete(int k){ JmisKit.removeTreeNodes(k,srv.getTable()); kSuccess(); } } ``` ## 树形table页面 ```html #@adminLayout() #define main() #set(aTh=["名称","操作"],aTd=["name","operate"]) #@cardTree("采购类别管理","erp/erppurchasesort",aTh,aTd) #end ``` ## docker发布程序 ### Docker 安装 + Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker + uname –r + 使用 root 权限登录 Centos。确保 yum 包更新到最新 + yum update + 卸载旧版本(如果安装过旧版本的话) + yum remove docker docker-common docker-selinux docker-engine + 安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的 + yum install -y yum-utils device-mapper-persistent-data lvm2y + 设置yum源 + yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo + 可以查看所有仓库中所有docker版本,并选择特定版本安装 + yum list docker-ce --showduplicates | sort -r + 安装docker + yum install docker-ce #由于repo中默认只开启stable仓库,故这里安装的是最新稳定版17.12.0 + yum install # 例如:sudo yum install docker-ce-17.12.0.ce + 启动并加入开机启动 + systemctl start docker + systemctl enable docker + https://4jm8bw1d.mirror.aliyuncs.com ### docker 安装mysql + 获取镜像docker pull mysql:5.6 + /home/docker下建立mysqlàconf/data/logs文件夹 + 启动容器docker run -p 3306:3306 --name mysql -v /home/docker/mysql/conf:/etc/mysql/conf.d -v /home/docker/mysql/logs:/logs -v /home/docker/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6 + 使用navicat工具连接mysql 账号:root 密码123456 + 上传自己项目需要的数据库 ### Jdk镜像创建 + docker pull unifreq/alpine-jre8 ### 安装程序镜像 + 创建镜像配置Dockerfile文件,touch Dockerfile创建文件 + Dockerfile文件内容: + ```html # Mirror containing JDK FROM unifreq/alpine-jre8 #  Author's signature MAINTAINER Ran Zhilin # item is the name of the custom image VOLUME ["/usr/project/item/"] RUN chmod -R 777 /usr/project/item/ WORKDIR /usr/project/item/ #  Execute the java-jar command (CMD: Execute this line only when the container is started. RUN: Execute this trip when you build the image # CMD ["/bin/bash","./jmis.sh"] CMD ["sh","jmis.sh","start"] #  Set the external port to 80 EXPOSE 80 + 创建镜像docker build -t item . + 在/home/docker下建立image文件夹 + 拷贝自己项目到image文件夹下,可是用xftp工具,当然自己的命令熟悉什么都可以只要能传文件 + 修改项目数据库连接地址:jdbcUrl = jdbc:mysql://127.0.0.1:3306/j_mis为jdbcUrl = jdbc:mysql:// docker_mysql:3306/j_mis + 启动容器docker run -d -i -t -p 65:80 -p 6789:6789 -p 5555:5555 --link mysql:docker_mysql --link emqx:docker_emqx -v /home/docker/item/jmis:/usr/project/item --name jmis item + 单个项目将端口8080改为80即可 + 如果需要有多个端口可使用-p 11:11 -p 22:22 需要多个连接地址使用 --link 容器名称1:别名 --link 容器名称2:别名 + 例如:发布项目需使用tio的6789端口以及mqtt服务:docker run -d -i -t -p 65:80 -p 6789:6789 --link mysql:docker_mysql --link emqx:docker_mqtt -v /home/docker/item/jmis4:/usr/project/item --name jmis4 item + 在修改mqtt的配置文件服务地址为:docker_mqtt ### emqx安装使用 + docker后台启动命令 + docker run --rm -d --name emqx -p 18083:18083 -p 1883:1883 emqx/emqx:latest + 进入emqtt docker命令 + docker exec -it emqx /bin/sh + 重启emqtt docker命令 + docker restart emqx ### 容器日志清空 + echo "" > $(docker inspect --format='{{.LogPath}}' 容器名称)