# 灌溉管理系统
**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类与方法
# 系统界面
+ 登陆

+ 后台首页

+ 界面

# 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 查询按钮 
+ W 清空查询按钮 
+ D 删除按钮 
+ C 增加按钮 
+ U 修改按钮 
+ I Excel导入按钮 
+ E Excel导出按钮 
+ 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

## 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}}' 容器名称)