pom.xml
@@ -200,7 +200,7 @@ </dependencies> <build> <finalName>scwcs</finalName> <finalName>wcs</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> src/main/java/com/zy/system/controller/LicenseCreatorController.java
@@ -3,7 +3,7 @@ import com.core.common.Cools; import com.core.common.R; import com.zy.system.entity.license.*; import de.schlichtherle.license.LicenseContent; import com.zy.system.timer.LicenseTimer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; @@ -14,7 +14,6 @@ import java.io.File; import java.io.IOException; import java.util.Date; /** * @@ -26,10 +25,10 @@ @Value("${license.licensePath}") private String licensePath; @Autowired private LicenseCheckListener licenseCheckListener; @Autowired private LicenseTimer licenseTimer; /** * 获取服务器硬件信息 * @param osName 操作系统类型,如果为空则自动判断 @@ -48,7 +47,7 @@ if (osName.startsWith("windows")) { abstractServerInfos = new WindowsServerInfos(); } else if (osName.startsWith("linux")) { // abstractServerInfos = new LinuxServerInfos(); abstractServerInfos = new LinuxServerInfos(); }else{//其他服务器类型 abstractServerInfos = new WindowsServerInfos(); } @@ -61,19 +60,7 @@ */ @RequestMapping(value = "/getLicenseDays") public R getLicenseDays() { LicenseVerify licenseVerify = new LicenseVerify(); LicenseContent verifyInfo = licenseVerify.getVerifyInfo(); if (verifyInfo == null) { return R.error(); } Date start = new Date(); Date end = verifyInfo.getNotAfter(); Long starTime = start.getTime(); Long endTime = end.getTime(); Long num = endTime - starTime;//时间戳相差的毫秒数 int day = (int) (num / 24 / 60 / 60 / 1000); return R.ok().add(day); return R.ok(licenseTimer.getLicenseDays()); } @RequestMapping(value = "/updateLicense") @@ -109,4 +96,10 @@ return R.error("许可证更新失败"); } @RequestMapping(value = "/activate") public R activate() { licenseTimer.timer(); return R.ok(); } } src/main/java/com/zy/system/entity/LicenseInfos.java
New file @@ -0,0 +1,56 @@ package com.zy.system.entity; import com.core.common.Cools;import com.baomidou.mybatisplus.annotations.TableId; import com.baomidou.mybatisplus.enums.IdType; import java.text.SimpleDateFormat; import java.util.Date; import com.baomidou.mybatisplus.annotations.TableField; import org.springframework.format.annotation.DateTimeFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import com.baomidou.mybatisplus.annotations.TableName; import java.io.Serializable; @Data @TableName("sys_license_infos") public class LicenseInfos implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value= "") @TableId(value = "id", type = IdType.AUTO) private Integer id; @ApiModelProperty(value= "") private String license; @ApiModelProperty(value= "") private String licenseTime; @ApiModelProperty(value= "") @TableField("create_time") @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") private Date createTime; public LicenseInfos() {} public LicenseInfos(String license,Date createTime) { this.license = license; this.createTime = createTime; } // LicenseInfos licenseInfos = new LicenseInfos( // null, // // null // // ); public String getCreateTime$(){ if (Cools.isEmpty(this.createTime)){ return ""; } return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime); } } src/main/java/com/zy/system/entity/license/AbstractServerInfos.java
@@ -23,7 +23,7 @@ LicenseCheck result = new LicenseCheck(); try { result.setIpAddress(this.getIpAddress()); // result.setIpAddress(this.getIpAddress()); result.setMacAddress(this.getMacAddress()); result.setCpuSerial(this.getCPUSerial()); result.setMainBoardSerial(this.getMainBoardSerial()); src/main/java/com/zy/system/entity/license/CustomKeyStoreParam.java
@@ -2,7 +2,9 @@ import de.schlichtherle.license.AbstractKeyStoreParam; import java.io.*; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; /** * 自定义KeyStoreParam,用于将公私钥存储文件存放到其他磁盘位置而不是项目中 @@ -47,7 +49,7 @@ */ @Override public InputStream getStream() throws IOException { final InputStream in = new FileInputStream(new File(storePath)); final InputStream in = this.getClass().getClassLoader().getResourceAsStream(storePath); if (null == in) { throw new FileNotFoundException(storePath); } src/main/java/com/zy/system/entity/license/CustomLicenseManager.java
@@ -129,12 +129,12 @@ if(expectedCheckModel != null && serverCheckModel != null){ //校验IP地址 if(!checkIpAddress(expectedCheckModel.getIpAddress(),serverCheckModel.getIpAddress())){ //throw new LicenseContentException("当前服务器的IP没在授权范围内"); throw new LicenseContentException("当前服务器的IP没在授权范围内"); } //校验Mac地址 if(!checkIpAddress(expectedCheckModel.getMacAddress(),serverCheckModel.getMacAddress())){ //throw new LicenseContentException("当前服务器的Mac地址没在授权范围内"); throw new LicenseContentException("当前服务器的Mac地址没在授权范围内"); } //校验主板序列号 @@ -194,7 +194,7 @@ if (osName.startsWith("windows")) { abstractServerInfos = new WindowsServerInfos(); } else if (osName.startsWith("linux")) { // abstractServerInfos = new LinuxServerInfos(); abstractServerInfos = new LinuxServerInfos(); }else{//其他服务器类型 abstractServerInfos = new WindowsServerInfos(); } src/main/java/com/zy/system/entity/license/LicenseCheckListener.java
@@ -1,9 +1,13 @@ package com.zy.system.entity.license; import com.core.common.Cools; import com.zy.system.entity.LicenseInfos; import com.zy.system.service.LicenseInfosService; import com.zy.system.timer.LicenseTimer; import de.schlichtherle.license.LicenseContent; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; @@ -11,6 +15,7 @@ import org.springframework.stereotype.Component; import java.io.File; import java.util.Date; /** * 在项目启动时安装证书 @@ -48,6 +53,10 @@ */ @Value("${license.publicKeysStorePath}") private String publicKeysStorePath; @Autowired private LicenseTimer licenseTimer; @Autowired private LicenseInfosService licenseInfosService; @Override public void onApplicationEvent(ContextRefreshedEvent event) { @@ -64,31 +73,51 @@ logger.info("++++++++ 开始加载许可证 ++++++++"); try { String publicKeysStoreFileName = this.getClass().getClassLoader().getResource(publicKeysStorePath).getPath(); File publicKeysStoreFile = new File(publicKeysStoreFileName); licenseTimer.getRemoteLicense(); } catch (Exception e) { } String licensePathFileName = this.getClass().getClassLoader().getResource(licensePath).getPath(); File licensePathFile = new File(licensePathFileName); try { LicenseVerifyParam param = new LicenseVerifyParam(); param.setSubject(subject); param.setPublicAlias(publicAlias); param.setStorePass(storePass); param.setLicensePath(licensePathFile.getPath()); param.setPublicKeysStorePath(publicKeysStoreFile.getPath()); param.setLicensePath(licensePath); param.setPublicKeysStorePath(publicKeysStorePath); LicenseVerify licenseVerify = new LicenseVerify(); LicenseInfos latestLicense = licenseInfosService.getLatestLicense(); if (latestLicense == null) { logger.info("许可证不存在"); return false; } //安装证书 LicenseContent install = licenseVerify.install(param); LicenseContent install = licenseVerify.install(param, latestLicense.getLicense()); logger.info("++++++++ 许可证加载结束 ++++++++"); licenseTimer.setSystemSupport(install!=null); if (install != null) { Date start = new Date(); Date end = install.getNotAfter(); Long starTime = start.getTime(); Long endTime = end.getTime(); Long num = endTime - starTime;//时间戳相差的毫秒数 int day = (int) (num / 24 / 60 / 60 / 1000); licenseTimer.setLicenseDays(day); } return install != null; } catch (Exception e) { e.printStackTrace(); return false; } } licenseTimer.setSystemSupport(false); return false; } } src/main/java/com/zy/system/entity/license/LicenseVerify.java
@@ -5,9 +5,13 @@ import org.apache.logging.log4j.Logger; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.text.DateFormat; import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.Base64; import java.util.prefs.Preferences; /** @@ -19,19 +23,21 @@ /** * 安装License证书 */ public synchronized LicenseContent install(LicenseVerifyParam param){ public synchronized LicenseContent install(LicenseVerifyParam param, String license) { LicenseContent result = null; DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //1. 安装证书 try{ LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param)); try { LicenseParam licenseParam = initLicenseParam(param); LicenseManager licenseManager = LicenseManagerHolder.getInstance(licenseParam); licenseManager.uninstall(); result = licenseManager.install(new File(param.getLicensePath())); logger.info(MessageFormat.format("许可证加载成功,许可证有效期:{0} - {1}",format.format(result.getNotBefore()),format.format(result.getNotAfter()))); }catch (Exception e){ logger.error("许可证加载失败!",e); File tempFileFromBase64 = createTempFileFromBase64(license); result = licenseManager.install(tempFileFromBase64); logger.info(MessageFormat.format("许可证加载成功,许可证有效期:{0} - {1}", format.format(result.getNotBefore()), format.format(result.getNotAfter()))); } catch (Exception e) { logger.error("许可证加载失败!", e); } return result; @@ -44,11 +50,6 @@ try { LicenseManager licenseManager = LicenseManagerHolder.getInstance(null); DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); if (!updateSystemTime()) { //时间更新失败,系统时间被更改 return false; } LicenseContent licenseContent = licenseManager.verify(); logger.info(MessageFormat.format("许可证校验通过,许可证有效期:{0} - {1}",format.format(licenseContent.getNotBefore()),format.format(licenseContent.getNotAfter()))); @@ -64,11 +65,6 @@ */ public LicenseContent getVerifyInfo(){ LicenseManager licenseManager = LicenseManagerHolder.getInstance(null); if (!updateSystemTime()) { //时间更新失败,系统时间被更改 return null; } //校验证书 try { @@ -103,31 +99,28 @@ } /** * 更新时间到注册表中 * 将Base64字符串转换为临时文件 * @param base64String Base64编码的字符串 * @param filePrefix 文件名前缀(例如 "license_") * @param fileSuffix 文件后缀(例如 ".lic") * @return 生成的临时File对象(自动在JVM退出时删除) * @throws IOException */ private boolean updateSystemTime() { // 获取用户根节点 Preferences userRoot = Preferences.userRoot(); // 获取指定路径下的节点 Preferences node = userRoot.node("/zhongyang"); String key = "time"; // 读取注册表 String value = node.get(key, null); if (value != null) { long originTime = Long.parseLong(value); long now = System.currentTimeMillis(); long diff = now - originTime;//现在时间 - 源时间 = 时间差 if (diff > 0) { //时间差大于0才允许更新注册表时间 node.put(key, String.valueOf(System.currentTimeMillis())); return true; } }else { // 写入注册表 node.put(key, String.valueOf(System.currentTimeMillis())); return true; } return false; public File base64ToTempFile(String base64String, String filePrefix, String fileSuffix) throws IOException { // 解码Base64 byte[] decodedBytes = Base64.getDecoder().decode(base64String); // 创建临时文件 Path tempPath = Files.createTempFile(filePrefix, fileSuffix); // 写入内容 Files.write(tempPath, decodedBytes); // 设置JVM退出时自动删除 tempPath.toFile().deleteOnExit(); return tempPath.toFile(); } public File createTempFileFromBase64(String base64Data) throws IOException { return base64ToTempFile(base64Data, "temp_license_", ".bin"); } } src/main/java/com/zy/system/entity/license/LinuxServerInfos.java
New file @@ -0,0 +1,91 @@ package com.zy.system.entity.license; import com.core.common.Cools; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.InetAddress; import java.util.List; import java.util.stream.Collectors; /** * 用于获取客户Linux服务器的基本信息 */ public class LinuxServerInfos extends AbstractServerInfos { @Override protected List<String> getIpAddress() throws Exception { List<String> result = null; //获取所有网络接口 List<InetAddress> inetAddresses = getLocalAllInetAddress(); if (inetAddresses != null && inetAddresses.size() > 0) { result = inetAddresses.stream().map(InetAddress::getHostAddress).distinct().map(String::toLowerCase).collect(Collectors.toList()); } return result; } @Override protected List<String> getMacAddress() throws Exception { List<String> result = null; //1. 获取所有网络接口 List<InetAddress> inetAddresses = getLocalAllInetAddress(); if (inetAddresses != null && inetAddresses.size() > 0) { //2. 获取所有网络接口的Mac地址 result = inetAddresses.stream().map(this::getMacByInetAddress).distinct().collect(Collectors.toList()); } return result; } @Override protected String getCPUSerial() throws Exception { //序列号 String serialNumber = ""; //使用dmidecode命令获取CPU序列号 String[] shell = {"/bin/bash", "-c", "dmidecode -t processor | grep 'ID' | awk -F ':' '{print $2}' | head -n 1"}; Process process = Runtime.getRuntime().exec(shell); process.getOutputStream().close(); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); if (null == reader.readLine()) { return serialNumber; } String line = reader.readLine().trim(); if (!Cools.isEmpty(line)) { serialNumber = line; } reader.close(); return serialNumber; } @Override protected String getMainBoardSerial() throws Exception { //序列号 String serialNumber = ""; //使用dmidecode命令获取主板序列号 String[] shell = {"/bin/bash", "-c", "dmidecode | grep 'Serial Number' | awk -F ':' '{print $2}' | head -n 1"}; Process process = Runtime.getRuntime().exec(shell); process.getOutputStream().close(); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); if (null == reader.readLine()) { return serialNumber; } String line = reader.readLine().trim(); if (!Cools.isEmpty(line)) { serialNumber = line; } reader.close(); return serialNumber; } } src/main/java/com/zy/system/mapper/LicenseInfosMapper.java
New file @@ -0,0 +1,14 @@ package com.zy.system.mapper; import com.zy.system.entity.LicenseInfos; import com.baomidou.mybatisplus.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @Mapper @Repository public interface LicenseInfosMapper extends BaseMapper<LicenseInfos> { LicenseInfos getLatestLicense(); } src/main/java/com/zy/system/service/LicenseInfosService.java
New file @@ -0,0 +1,10 @@ package com.zy.system.service; import com.zy.system.entity.LicenseInfos; import com.baomidou.mybatisplus.service.IService; public interface LicenseInfosService extends IService<LicenseInfos> { LicenseInfos getLatestLicense(); } src/main/java/com/zy/system/service/impl/LicenseInfosServiceImpl.java
New file @@ -0,0 +1,16 @@ package com.zy.system.service.impl; import com.zy.system.mapper.LicenseInfosMapper; import com.zy.system.entity.LicenseInfos; import com.zy.system.service.LicenseInfosService; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import org.springframework.stereotype.Service; @Service("licenseInfosService") public class LicenseInfosServiceImpl extends ServiceImpl<LicenseInfosMapper, LicenseInfos> implements LicenseInfosService { @Override public LicenseInfos getLatestLicense() { return this.baseMapper.getLatestLicense(); } } src/main/java/com/zy/system/timer/LicenseTimer.java
New file @@ -0,0 +1,163 @@ package com.zy.system.timer; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.core.common.Cools; import com.zy.common.utils.HttpHandler; import com.zy.system.entity.LicenseInfos; import com.zy.system.entity.license.*; import com.zy.system.service.LicenseInfosService; import de.schlichtherle.license.LicenseContent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.Date; import java.util.HashMap; @Component public class LicenseTimer { private static boolean SYSTEM_SUPPORT = false;//系统激活状态,默认关闭 private static int LICENSE_DAYS = 0;//许可证天数 /** * 证书subject */ @Value("${license.subject}") private String subject; /** * 公钥别称 */ @Value("${license.publicAlias}") private String publicAlias; /** * 访问公钥库的密码 */ @Value("${license.storePass}") private String storePass; /** * 证书生成路径 */ @Value("${license.licensePath}") private String licensePath; /** * 密钥库存储路径 */ @Value("${license.publicKeysStorePath}") private String publicKeysStorePath; @Autowired private LicenseInfosService licenseInfosService; //每天晚上11点更新系统激活状态 @Scheduled(cron = "0 0 23 * * ? ") public void timer() { try { getRemoteLicense(); } catch (Exception e) { } try { verify(); } catch (Exception e) { } } public void getRemoteLicense() { try { AbstractServerInfos abstractServerInfos = null; String osName = System.getProperty("os.name"); //根据不同操作系统类型选择不同的数据获取方法 if (osName.startsWith("windows")) { abstractServerInfos = new WindowsServerInfos(); } else if (osName.startsWith("linux")) { abstractServerInfos = new LinuxServerInfos(); }else{//其他服务器类型 abstractServerInfos = new WindowsServerInfos(); } LicenseCheck serverInfos = abstractServerInfos.getServerInfos(); HashMap<String, Object> map = new HashMap<>(); map.put("subject", subject); map.put("licenseCheck", serverInfos); String response = new HttpHandler.Builder() .setUri("http://net.zoneyung.net:9999/license") .setPath("/remoteQueryLicense") .setJson(JSON.toJSONString(map)) .build() .doPost(); JSONObject jsonObject = JSON.parseObject(response); if (jsonObject.getString("result").equals("ok")) { LicenseInfos licenseInfos = new LicenseInfos(); licenseInfos.setLicense(jsonObject.getString("data")); licenseInfos.setCreateTime(new Date()); licenseInfos.setLicenseTime(jsonObject.getString("licenseTime")); licenseInfosService.insert(licenseInfos); } } catch (Exception e) { e.printStackTrace(); } } public void verify() { LicenseInfos latestLicense = licenseInfosService.getLatestLicense(); if (latestLicense == null) { setLicenseDays(0); setSystemSupport(false); return; } LicenseVerifyParam param = new LicenseVerifyParam(); param.setSubject(subject); param.setPublicAlias(publicAlias); param.setStorePass(storePass); param.setLicensePath(licensePath); param.setPublicKeysStorePath(publicKeysStorePath); //验证许可证是否有效 LicenseVerify licenseVerify = new LicenseVerify(); //安装证书 LicenseContent install = licenseVerify.install(param, latestLicense.getLicense()); if (install != null) { Date start = new Date(); Date end = install.getNotAfter(); Long starTime = start.getTime(); Long endTime = end.getTime(); long num = endTime - starTime;//时间戳相差的毫秒数 int day = (int) (num / 24 / 60 / 60 / 1000); setLicenseDays(day); setSystemSupport(true); }else { setLicenseDays(0); setSystemSupport(false); } } public boolean getSystemSupport() { return SYSTEM_SUPPORT; } public void setSystemSupport(boolean systemSupport) { SYSTEM_SUPPORT = systemSupport; } public int getLicenseDays() { return LICENSE_DAYS; } public void setLicenseDays(int licenseDays) { LICENSE_DAYS = licenseDays; } } src/main/resources/application-prod.yml
@@ -1,6 +1,6 @@ wcs-slave: doubleDeep: true #双深 doubleLocs: 5,8 #双深库位排号 1,4 doubleLocs: 1,4 #双深库位排号 1,4 groupCount: 4 #一个堆垛机负责的货架排数 crn[0]: #堆垛机1 id: 1 @@ -28,134 +28,14 @@ row: 1 bay: 59 lev: 11 devpPlcId: ${wcs-slave.devp[1].id} devpPlcId: ${wcs-slave.devp[0].id} crnInStn[1]: #堆垛机入库站点--2F输送线 取货口 staNo: 2003 row: 2 bay: 59 lev: 11 backSta: 102 devpPlcId: ${wcs-slave.devp[1].id} crn[1]: #堆垛机2 id: 2 ip: 192.168.110.90 slot: 0 demo: false rack: 0 offset: 2 #偏移量,当堆垛机站点列号=1时,偏移量=2 port: 102 crnOutStn[0]: #堆垛机出库站点--1F输送线 放货口 staNo: 1006 row: 3 bay: 1 lev: 1 devpPlcId: ${wcs-slave.devp[0].id} crnInStn[0]: #堆垛机入库站点1--1F输送线 取货口 staNo: 1008 row: 4 bay: 1 lev: 1 backSta: 106 devpPlcId: ${wcs-slave.devp[0].id} crnOutStn[1]: #堆垛机出库站点--2F输送线 放货口 staNo: 2013 row: 4 bay: 59 lev: 11 devpPlcId: ${wcs-slave.devp[1].id} crnInStn[1]: #堆垛机入库站点1--2F输送线 取货口 staNo: 2012 row: 3 bay: 59 lev: 11 backSta: 106 devpPlcId: ${wcs-slave.devp[1].id} crn[2]: #堆垛机3 id: 3 ip: 192.168.110.10 slot: 0 demo: false rack: 0 offset: 2 #偏移量,当堆垛机站点列号=1时,偏移量=2 port: 102 crnOutStn[0]: #堆垛机出库站点--1F输送线 放货口 staNo: 1056 row: 7 bay: 1 lev: 1 devpPlcId: ${wcs-slave.devp[2].id} crnInStn[0]: #堆垛机入库站点1--1F输送线 取货口 staNo: 1058 row: 6 bay: 1 lev: 1 backSta: 106 devpPlcId: ${wcs-slave.devp[2].id} crnOutStn[1]: #堆垛机出库站点--2F输送线 放货口 staNo: 2057 row: 7 bay: 1 lev: 13 devpPlcId: ${wcs-slave.devp[3].id} crnInStn[1]: #堆垛机入库站点1--2F输送线 取货口 staNo: 2057 row: 7 bay: 1 lev: 13 backSta: 106 devpPlcId: ${wcs-slave.devp[3].id} crnOutStn[2]: #堆垛机出库站点--2F输送线 放货口 staNo: 2058 row: 6 bay: 1 lev: 13 devpPlcId: ${wcs-slave.devp[3].id} crnInStn[2]: #堆垛机入库站点1--2F输送线 取货口 staNo: 2058 row: 6 bay: 1 lev: 13 backSta: 106 devpPlcId: ${wcs-slave.devp[3].id} crnOutStn[3]: #堆垛机出库站点--2F输送线 放货口 staNo: 2051 row: 7 bay: 13 lev: 13 devpPlcId: ${wcs-slave.devp[3].id} crnInStn[3]: #堆垛机入库站点1--2F输送线 取货口 staNo: 2051 row: 7 bay: 13 lev: 13 backSta: 106 devpPlcId: ${wcs-slave.devp[3].id} crnOutStn[4]: #堆垛机出库站点--2F输送线 放货口 staNo: 2052 row: 7 bay: 10 lev: 13 devpPlcId: ${wcs-slave.devp[3].id} crnInStn[4]: #堆垛机入库站点1--2F输送线 取货口 staNo: 2052 row: 7 bay: 10 lev: 13 backSta: 106 devpPlcId: ${wcs-slave.devp[3].id} crnOutStn[5]: #堆垛机出库站点--2F输送线 放货口 staNo: 2054 row: 7 bay: 4 lev: 13 devpPlcId: ${wcs-slave.devp[3].id} crnInStn[5]: #堆垛机入库站点1--2F输送线 取货口 staNo: 2056 row: 7 bay: 2 lev: 13 backSta: 106 devpPlcId: ${wcs-slave.devp[3].id} devp[0]: #输送线--半成品1F id: 1 ip: 192.168.110.50 @@ -168,192 +48,51 @@ staNo: 1014 backSta: 1015 barcode: ${wcs-slave.barcode[0].id} led: ${wcs-slave.led[2].id} scale: ${wcs-slave.scale[0].id} led: ${wcs-slave.led[0].id} # scale: ${wcs-slave.scale[0].id} outSta[0]: #出库口1 staNo: 1019 outSta[1]: #出库口2 staNo: 1010 outSta[2]: #出库口2 staNo: 1020 devp[1]: #输送线--半成品2F id: 2 ip: 192.168.110.70 rack: 0 port: 102 slot: 0 emptyInSta[0]: #空板入库口0 staNo: 2007 inSta[0]: #入库口1 staNo: 2007 backSta: 2006 barcode: ${wcs-slave.barcode[1].id} led: ${wcs-slave.led[8].id} scale: ${wcs-slave.scale[1].id} outSta[0]: #出库口1 staNo: 2001 outSta[1]: #出库口2 staNo: 2019 devp[2]: #输送线--成品1F id: 3 ip: 192.168.110.30 rack: 0 port: 102 slot: 0 inSta[0]: #入库口1 staNo: 1052 backSta: 1051 barcode: ${wcs-slave.barcode[2].id} led: ${wcs-slave.led[0].id} scale: ${wcs-slave.scale[2].id} inSta[1]: #空板入库口0 staNo: 1058 outSta[0]: #出库口1 staNo: 1053 devp[3]: #输送线--成品2F id: 4 ip: 192.168.110.40 rack: 0 port: 102 slot: 0 emptyInSta[0]: #空板入库口0 staNo: 2056 led: ${wcs-slave.led[3].id} inSta[0]: #入库口1 staNo: 2056 backSta: 2055 barcode: ${wcs-slave.barcode[3].id} led: ${wcs-slave.led[4].id} scale: ${wcs-slave.scale[3].id} outSta[0]: #出库口1 staNo: 1053 outSta[1]: #出库口1 staNo: 251 outSta[2]: #出库口1 staNo: 252 outSta[3]: #出库口1 staNo: 257 outSta[4]: #出库口1 staNo: 258 # 拣料入库口1 pickSta[0]: staNo: 2051 led: ${wcs-slave.led[6].id} # 拣料入库口2 pickSta[1]: staNo: 2052 # 拣料入库口3 pickSta[2]: staNo: 2057 led: ${wcs-slave.led[3].id} # 拣料入库口4 pickSta[3]: staNo: 2058 barcode[0]: #条码扫描仪 port: 51236 ip: 172.17.91.39 id: 1 barcode[1]: #条码扫描仪 port: 51236 ip: 172.17.91.39 id: 2 barcode[2]: #条码扫描仪 port: 51236 ip: 172.17.91.39 id: 3 barcode[3]: #条码扫描仪 port: 51236 ip: 172.17.91.39 id: 4 # LED1 成品库1F # LED1 led[0]: id: 1 ip: 192.168.110.210 port: 5005 devpPlcId: ${wcs-slave.devp[2].id} devpPlcId: ${wcs-slave.devp[0].id} staArr: 1052 # LED2 成品库1F # LED2 led[1]: id: 2 ip: 192.168.110.211 port: 5005 devpPlcId: ${wcs-slave.devp[2].id} staArr: 1051 # LED3 半成品库1F led[2]: id: 3 ip: 192.168.110.212 port: 5005 devpPlcId: ${wcs-slave.devp[0].id} staArr: 1014,1015 # LED4 成品库2F led[3]: id: 4 ip: 192.168.110.213 port: 5005 devpPlcId: ${wcs-slave.devp[3].id} staArr: 2057 # LED5 成品库2F led[4]: id: 5 ip: 192.168.110.214 port: 5005 devpPlcId: ${wcs-slave.devp[3].id} staArr: 2056 # LED6 成品库2F led[5]: id: 6 ip: 192.168.110.215 port: 5005 devpPlcId: ${wcs-slave.devp[3].id} staArr: 2054 # LED7 成品库2F led[6]: id: 7 ip: 192.168.110.216 port: 5005 devpPlcId: ${wcs-slave.devp[3].id} staArr: 2051 # LED8 半成品库2F led[7]: id: 8 ip: 192.168.110.217 port: 5005 devpPlcId: ${wcs-slave.devp[1].id} staArr: 2002 # LED9 半成品库2F led[8]: id: 9 ip: 192.168.110.218 port: 5005 devpPlcId: ${wcs-slave.devp[1].id} staArr: 2007 # LED10 半成品库2F led[9]: id: 10 ip: 192.168.110.219 port: 5005 devpPlcId: ${wcs-slave.devp[1].id} staArr: 2018 staArr: 1051 # 磅秤 半成品一楼 192.168.110.24 scale[0]: id: 1 ip: 192.168.110.24 port: 5005 # scale[0]: # id: 1 # ip: 192.168.110.24 # port: 5005 # 磅秤 半成品2楼 192.168.110.23 scale[1]: id: 2 ip: 192.168.110.23 port: 5005 # scale[1]: # id: 2 # ip: 192.168.110.23 # port: 5005 # 磅秤 成品库一楼192.168.110.21 scale[2]: id: 3 ip: 192.168.110.21 port: 5005 # scale[2]: # id: 3 # ip: 192.168.110.21 # port: 5005 # 磅秤 成品库2楼 192.168.110.22 scale[3]: id: 4 ip: 192.168.110.22 port: 5005 # scale[3]: # id: 4 # ip: 192.168.110.22 # port: 5005 src/main/resources/application.yml
@@ -1,5 +1,5 @@ server: port: 8080 port: 9090 servlet: context-path: /@pom.build.finalName@ @@ -37,7 +37,7 @@ #License相关配置 license: subject: scwcs subject: yrwcs publicAlias: publicCert storePass: public_zhongyang_123456789 licensePath: license.lic src/main/resources/mapper/LicenseInfosMapper.xml
New file @@ -0,0 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.zy.system.mapper.LicenseInfosMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.zy.system.entity.LicenseInfos"> <id column="id" property="id" /> <result column="license" property="license" /> <result column="license_time" property="licenseTime" /> <result column="create_time" property="createTime" /> </resultMap> <select id="getLatestLicense" resultMap="BaseResultMap"> select top 1 * from sys_license_infos order by create_time desc </select> </mapper> src/main/webapp/static/wcs/js/common.js
@@ -1,4 +1,4 @@ var baseUrl = "/scwcs"; var baseUrl = "/wcs"; // 赋值 function setVal(el, val) { src/main/webapp/static/wcs/js/console.map.js
@@ -1,5 +1,5 @@ mapInfo = { "mapName": "scwcs", "mapName": "wcs", "rackCount": 13, "crnCount": 4, "stbCount": 4, src/main/webapp/static/wcs/js/console1.map.js
@@ -1,5 +1,5 @@ mapInfo = { "mapName": "scwcs", "mapName": "wcs", "rackCount": 13, "crnCount": 4, "stbCount": 4, src/main/webapp/static/wcs/js/console2.map.js
@@ -1,5 +1,5 @@ mapInfo = { "mapName": "scwcs", "mapName": "wcs", "rackCount": 13, "crnCount": 4, "stbCount": 4, src/main/webapp/static/wcs/js/console3.map.js
@@ -1,5 +1,5 @@ mapInfo = { "mapName": "scwcs", "mapName": "wcs", "rackCount": 13, "crnCount": 4, "stbCount": 4, src/main/webapp/views/index.html
@@ -2,15 +2,14 @@ <html lang="en"> <head> <meta charset="utf-8"> <title>自动化立体仓库 - wcs</title> <title>中扬 - 自动化立体仓库 - AS / RS</title> <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0"> <link rel="stylesheet" href="../static/wms/layui/css/layui.css" media="all"> <link rel="stylesheet" href="../static/wms/css/admin.css?v=318" media="all"> <link rel="stylesheet" href="../static/wms/css/loader.css" media="all"> <link rel="stylesheet" href="../static/wcs/css/layx.min.css" type="text/css" /> <script src="../static/wcs/js/tools/layx.min.js"></script> <link rel="icon" type="image/x-icon" href="../static/image/favicon.ico" /> <link rel="stylesheet" href="../static/layui/css/layui.css" media="all"> <link rel="stylesheet" href="../static/css/admin.css?v=318" media="all"> <link rel="stylesheet" href="../static/css/loader.css" media="all"> <style> .layui-logo img { width: 25px; @@ -20,27 +19,6 @@ font-weight: 400; /*margin-left: 5px;*/ } /* 弹窗样式 */ .popup { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); display: none; justify-content: center; align-items: center; z-index: 9999; } .popup-content { background-color: #fff; padding: 20px; border-radius: 5px; box-shadow: 0px 0px 20px rgba(0,0,0,0.3); text-align: center; } </style> </head> <body class="layui-layout-body"> @@ -48,10 +26,10 @@ <!-- 头部 --> <div class="layui-header"> <div class="layui-logo"> <img class="loginLogo" src="../static/wms/image/logo.png" style="display: inline-block; width: 60%;height: auto"> <!-- <span style="margin-top: 0; letter-spacing: 10px">wcs</span>--> <!-- <img src="../static/wms/image/logo.svg"/>--> <!-- <cite>wcs - 自动化立体仓库</cite>--> <img src="../static/image/zy_logo_dark_color.png" style="display: inline-block; width: 40%;height: auto"> <!-- <span style="margin-top: 0; letter-spacing: 10px">中扬立库</span>--> <!-- <img src="../static/image/logo.svg"/>--> <!-- <cite>中扬 - Zoneyung</cite>--> </div> <ul class="layui-nav layui-layout-left"> @@ -63,11 +41,8 @@ </li> </ul> <ul class="layui-nav layui-layout-right"> <!-- <li class="layui-nav-item" lay-unselect>--> <!-- <a ew-event="note" title="便签"><i class="layui-icon layui-icon-note"></i></a>--> <!-- </li>--> <li class="layui-nav-item" lay-unselect id="licenseShow" style="display: none;user-select: none;"> <div style="color: red;">仓储系统许可有效期:<span id="licenseDays">29</span>天</div> <div style="color: red;">临时许可证有效期:<span id="licenseDays">29</span>天</div> </li> <li class="layui-nav-item layui-hide-xs" lay-unselect> <a ew-event="fullScreen" title="全屏"><i class="layui-icon layui-icon-screen-full"></i></a> @@ -100,7 +75,7 @@ <div class="layui-body"></div> <!-- 底部 --> <div class="layui-footer layui-text"> <!-- <span class="copyright-text">copyright © 2023 wcs all rights reserved.</span>--> copyright © 2022 <a href="https://www.superton.cn/" target="_blank">浙江中扬立库有限公司</a> all rights reserved. <span class="pull-right">Version 1.0.0</span> </div> @@ -110,65 +85,13 @@ <div class="layuimini-loader"> <div class="layuimini-loader-inner"></div> </div> <!-- 弹窗内容 --> <div class="popup" id="popup"> <div class="popup-content"> <h2 style="font-size: 28px;margin-bottom: 10px;">许可证即将过期</h2> <div id="popup-text" style="font-size: 28px;color: red"></div> <button style="background-color: #007bff;color: #fff;border: none;padding: 10px 20px;border-radius: 5px;cursor: pointer;font-size: 16px;" onclick="hidePopup()">关闭</button> </div> </div> <script> // 显示弹窗 function showPopup(res) { document.getElementById('popup').style.display = 'block'; // 获取弹出窗口内容的容器元素 var popupText = document.getElementById('popup-text'); // 假设后台返回的字符串为 responseString if (res!==""){ // 获取当前日期 const currentDate = new Date(); // 创建新日期对象并添加天数 const newDate = new Date(); newDate.setDate(currentDate.getDate() + res + 1); // 将字符串设置为弹窗内容的文本 popupText.textContent = "许可证将于" + new Intl.DateTimeFormat('zh-CN').format(newDate) + "过期,剩余有效期:" + res + "天!"; }else { document.getElementById('popup').style.display = 'none'; } } // 隐藏弹窗 function hidePopup() { document.getElementById('popup').style.display = 'none'; } </script> <script type="text/javascript" src="../static/wms/js/jquery/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="../static/wms/layui/layui.js"></script> <script type="text/javascript" src="../static/wms/js/handlebars/handlebars-v4.5.3.js"></script> <script type="text/javascript" src="../static/wms/js/common.js"></script> <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="../static/layui/layui.js"></script> <script type="text/javascript" src="../static/js/handlebars/handlebars-v4.5.3.js"></script> <script type="text/javascript" src="../static/js/common.js"></script> <script> f() function f() { $.ajax({ url: baseUrl + "/license/getLicenseDays", headers: {'token': localStorage.getItem('token')}, method: 'POST', success: function (res) { if (res.code == 200) { let days = res.data if (days <= 15) { showPopup(res.data) } else { showPopup(""); } } } }); } </script> <script> console.log('%c wcs %c 1.0.0','background-color:rgb(53,73,94);color: #fff;border-radius:2px 0 0 2px;padding:2px 4px;','background-color:rgb(25,190,107);color: #fff;border-radius:0 2px 2px 0;padding:2px 4px;font: 9pt "Apercu Regular", Georgia, "Times New Roman", Times, serif;'); console.log('%c 中扬立库平台 %c 1.0.0','background-color:rgb(53,73,94);color: #fff;border-radius:2px 0 0 2px;padding:2px 4px;','background-color:rgb(25,190,107);color: #fff;border-radius:0 2px 2px 0;padding:2px 4px;font: 9pt "Apercu Regular", Georgia, "Times New Roman", Times, serif;'); $(function () { if ("" === localStorage.getItem('token')) { top.location.href = baseUrl + "/login"; @@ -176,7 +99,7 @@ }); layui.config({ base: baseUrl + "/static/wms/layui/lay/modules/" base: baseUrl + "/static/layui/lay/modules/" }).extend({ notice: 'notice/notice', }).use(['index', 'element', 'layer', 'admin', 'notice'], function () { @@ -209,29 +132,11 @@ var html = template(res); $("#menu-main").html(html); element.init(); $("#a-30519").attr({"href":$("#a-30519").attr("lay-href"),"target":"_blank"}) $("#a-30519").attr({"lay-href":""}) $("#a-30520").attr({"href":$("#a-30520").attr("lay-href"),"target":"_blank"}) $("#a-30520").attr({"lay-href":""}) $("#a-30522").attr({"href":$("#a-30522").attr("lay-href"),"target":"_blank"}) $("#a-30522").attr({"lay-href":""}) } else if (res.code === 403) { top.location.href = baseUrl + "/login"; } else { layer.msg(res.msg, {icon: 2}); } } }); $.ajax({ url: baseUrl+"/loginInformation", data: {}, method: 'GET', success: function (res) { var data = res.data $(".copyright-text").text(data.loginCopyrightText); $(".loginLogo").attr("src", data.loginLogo); } }); @@ -243,22 +148,9 @@ if (res.code == 200) { let days = res.data if (days <= 30) { // 弹出一个简单的提示框 layer.alert(` <div style="font-size: 100px; text-align: center; line-height: 1.8; color: red"> 许可证有效期为:${days} </div> `, { area: ['1000px', '800px'], btn: '确定', btnAlign: 'c', // 按钮居中(默认是右对齐) yes: function(index) { layer.msg('请联系立库公司商务续约'); layer.close(index); } }); $("#licenseShow").show() $("#licenseDays").html(days) alert("临时许可有效期:" + days + "天") } }else { top.location.href = baseUrl + "/login"; @@ -268,7 +160,7 @@ // 默认加载主页 index.loadHome({ menuPath: baseUrl+'/views/home/console.html', menuPath: baseUrl+'/views/home/navigation.html', menuName: '<i class="layui-icon layui-icon-home"></i>' }); @@ -294,7 +186,7 @@ <a><i class="layui-icon {{this.menuIcon}}"></i> <cite>{{this.menu}}</cite></a> <dl class="layui-nav-child"> {{#each this.subMenu}} <dd><a lay-href="{{this.code}}?resourceId={{this.id}}" id="a-{{this.id}}">{{this.name}}</a></dd> <dd><a lay-href="{{this.code}}?resourceId={{this.id}}">{{this.name}}</a></dd> {{/each}} </dl> </li>