| | |
| | | <artifactId>okhttp</artifactId> |
| | | <version>3.10.0</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>de.schlichtherle.truelicense</groupId> |
| | | <artifactId>truelicense-core</artifactId> |
| | | <version>1.33</version> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | <build> |
| | |
| | | package com.zy.asrs.controller; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.baomidou.mybatisplus.mapper.Wrapper; |
| | |
| | | import com.zy.common.model.LocDto; |
| | | import com.zy.common.model.TaskDto; |
| | | import com.zy.common.model.WrkDto; |
| | | import com.zy.common.utils.HttpHandler; |
| | | import com.zy.common.web.BaseController; |
| | | import com.zy.system.entity.Config; |
| | | import com.zy.system.service.ConfigService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * 移动端接口控制器 |
| | | * Created by vincent on 2020/6/10 |
| | | */ |
| | | @Slf4j |
| | | @RestController |
| | | @RequestMapping("mobile") |
| | | public class MobileController extends BaseController { |
| | |
| | | @Autowired |
| | | private ManLocDetlMapper manLocDetlMapper; |
| | | |
| | | @Autowired |
| | | private ApiLogService apiLogService; |
| | | |
| | | @Resource |
| | | private StaDescService staDescService; |
| | | |
| | | @Value("${rcs.address.URL}") |
| | | private String url; |
| | | @Value("${rcs.address.reportTask}") |
| | | private String attrcs; |
| | | @Value("${rcs.address.siteBindAndUnbing}") |
| | | private String siteBindAndUnbing; |
| | | @Autowired |
| | | private ConfigService configService; |
| | | |
| | | // 商品上架 |
| | | @RequestMapping("/mat/onSale/auth") |
| | |
| | | for (WrkDto dto : dtos) { |
| | | WrkMast wrkMast = wrkMastService.selectById(dto.getWrkNo()); |
| | | if (wrkMast != null) { |
| | | // 101 |
| | | if (wrkMast.getIoType() == 101) { |
| | | for (WrkDetl wrkDetl : dto.getWrkDetls()) { |
| | | wrkDetlService.updateInspect(wrkDetl.getWrkNo(), wrkDetl.getMatnr(), wrkDetl.getBatch()); |
| | | } |
| | | for (WrkDetl wrkDetl : dto.getWrkDetls()) { |
| | | wrkDetlService.updateInspect(wrkDetl.getWrkNo(), wrkDetl.getMatnr(), wrkDetl.getBatch()); |
| | | } |
| | | // 103 |
| | | if (wrkMast.getIoType() == 103) { |
| | | if (!wrkDetlService.delete(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo()))) { |
| | | throw new CoolException("拣料出库确认失败"); |
| | | } |
| | | for (WrkDetl wrkDetl : dto.getWrkDetls()) { |
| | | wrkDetl.setInspect(1); |
| | | if (!wrkDetlService.insert(wrkDetl)) { |
| | | throw new CoolException("拣料出库确认失败"); |
| | | } |
| | | } |
| | | if(wrkMast.getIoType() == 103 || wrkMast.getIoType() == 107) { |
| | | wrkMast.setWrkSts(16L);//下架完成等待回库 |
| | | }else { |
| | | wrkMast.setWrkSts(15L); |
| | | } |
| | | wrkMastService.updateById(wrkMast); |
| | | } |
| | | |
| | | } |
| | | |
| | | for (Integer wrkNo : wrkNos) { |
| | | WrkMast wrkMast = wrkMastService.selectById(wrkNo); |
| | | if (wrkMast.getWrkSts() == 14 && (Cools.isEmpty(wrkMast.getInvWh()) || wrkMast.getInvWh().equals("N"))) { |
| | | List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(wrkNo); |
| | | boolean complete = true; |
| | | for (WrkDetl wrkDetl : wrkDetls) { |
| | | if (wrkDetl.getInspect() == null || wrkDetl.getInspect() == 0) { |
| | | complete = false; |
| | | break; |
| | | } |
| | | } |
| | | if (complete) { |
| | | wrkMast.setInvWh("Y"); |
| | | wrkMast.setModiTime(new Date()); |
| | | if (!wrkMastService.updateById(wrkMast)) { |
| | | throw new CoolException("修改工作档" + wrkNo + "失败"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // for (Integer wrkNo : wrkNos) { |
| | | // WrkMast wrkMast = wrkMastService.selectById(wrkNo); |
| | | // if (wrkMast.getWrkSts() == 15 && (Cools.isEmpty(wrkMast.getInvWh()) || wrkMast.getInvWh().equals("N"))) { |
| | | // List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(wrkNo); |
| | | // boolean complete = true; |
| | | // for (WrkDetl wrkDetl : wrkDetls) { |
| | | // if (wrkDetl.getInspect() == null || wrkDetl.getInspect() == 0) { |
| | | // complete = false; |
| | | // break; |
| | | // } |
| | | // } |
| | | // if (complete) { |
| | | // wrkMast.setInvWh("Y"); |
| | | // wrkMast.setModiTime(new Date()); |
| | | // if (!wrkMastService.updateById(wrkMast)) { |
| | | // throw new CoolException("修改工作档" + wrkNo + "失败"); |
| | | // } |
| | | // } |
| | | // } |
| | | // } |
| | | return R.ok("完成确认"); |
| | | } |
| | | |
| | |
| | | |
| | | @RequestMapping("/checkDetl/auth") |
| | | @ManagerAuth |
| | | public R getCheckDetl(@RequestParam(required = false) Integer staNo) { |
| | | public synchronized R getCheckDetl(@RequestParam(required = false) Integer staNo) { |
| | | if (null == staNo || staNo == 0) { |
| | | return R.ok(); |
| | | } |
| | |
| | | return R.ok("出库成功"); |
| | | } |
| | | |
| | | //------------------------------------------------------------------------------agv调度-------------------------------------------------- |
| | | |
| | | /** |
| | | * 补空板 区域到点 |
| | | * @param locNo 目标站点 |
| | | * @param size 托盘大小 1:小托盘 2:大托盘 |
| | | * @return |
| | | */ |
| | | @RequestMapping("/FillEmptyPallets") |
| | | public synchronized R FillEmptyPallets(@RequestParam(required = false) String locNo |
| | | ,@RequestParam(required = false) String size){ |
| | | if (Cools.isEmpty(locNo) || Cools.isEmpty(size)) { |
| | | return R.error("站点或者大小不能为空"); |
| | | |
| | | } |
| | | //空托盘缓冲区 小:E8 大:E9 |
| | | String rStaNo ="E8"; |
| | | if(size.equals("2")){ |
| | | rStaNo = "E9"; |
| | | } |
| | | LinkedHashMap<String,Object> rcsParam=new LinkedHashMap<>(); |
| | | rcsParam.put("taskType", "PF-FMR-COMMON"); |
| | | List<LinkedHashMap<String,Object>> targetRoutes=new ArrayList<>(); |
| | | LinkedHashMap<String,Object> t1=new LinkedHashMap<>(); |
| | | LinkedHashMap<String,Object> t2=new LinkedHashMap<>(); |
| | | t1.put("seq", 0); |
| | | t1.put("type","ZONE"); |
| | | t1.put("code", rStaNo); |
| | | t1.put("autoStart",0); |
| | | t1.put("operation","COLLECT"); |
| | | |
| | | t2.put("seq", 0); |
| | | t2.put("type","SITE"); |
| | | t2.put("code", locNo); |
| | | t2.put("autoStart",0); |
| | | t2.put("operation","DELIVERY"); |
| | | |
| | | targetRoutes.add(t1); |
| | | targetRoutes.add(t2); |
| | | rcsParam.put("targetRoute", targetRoutes); |
| | | rcsParam.put("initPriority", 100); |
| | | |
| | | |
| | | String response =""; |
| | | Boolean bool =false; |
| | | String msg = ""; |
| | | HashMap<String,Object> map = new HashMap<>(); |
| | | Date date = new Date(); |
| | | String time = date.getTime()+""; |
| | | |
| | | map.put("X-LR-REQUEST-ID", time); |
| | | try { |
| | | log.info("wms派发搬运任务给AGV搬运={}", rcsParam); |
| | | response = new HttpHandler.Builder() |
| | | .setHeaders(map) |
| | | .setUri(url) |
| | | .setHttps(true) |
| | | .setPath(attrcs) |
| | | .setJson(JSON.toJSONString(rcsParam)) |
| | | .build() |
| | | .doPostCloseSSL(); |
| | | JSONObject jsonObject = JSON.parseObject(response); |
| | | if(jsonObject.getString("code").equals("SUCCESS")){ |
| | | bool = true; |
| | | }else{ |
| | | msg=jsonObject.getString("message"); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error("wms派发搬运任务给AGV搬运失败返回值={}", response); |
| | | } finally { |
| | | apiLogService.save("wms派发搬运任务给AGV搬运" |
| | | , url + attrcs |
| | | , null |
| | | , "127.0.0.1" |
| | | , JSON.toJSONString(rcsParam) |
| | | , response |
| | | , bool |
| | | ); |
| | | } |
| | | |
| | | if(bool){ |
| | | return R.ok(); |
| | | }else { |
| | | return R.error(msg); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 空托盘回库 |
| | | * @param sourceStaNo 原站点 |
| | | * @param barcode 托盘大小 1:小托盘 2:大托盘 目标区或者巷道 |
| | | * @return |
| | | */ |
| | | @RequestMapping("/FillEmptyPalletsStack") |
| | | public synchronized R FillEmptyPalletsStack(@RequestParam(required = false) String sourceStaNo |
| | | ,@RequestParam(required = false) String barcode){ |
| | | if (Cools.isEmpty(sourceStaNo) || Cools.isEmpty(barcode)) { |
| | | return R.error("站点或者大小不能为空"); |
| | | |
| | | } |
| | | //空托盘缓冲区 小:E8 大:E9 |
| | | String rStaNo ="E8"; |
| | | if(barcode.substring(0,1).equals("9")){ |
| | | rStaNo = "E9"; |
| | | } |
| | | String type ="ZONE"; //区域 |
| | | Config config = configService.selectOne(new EntityWrapper<Config>().eq("code", "autoE").eq("status", "1")); |
| | | if (config != null) { |
| | | type ="STACK"; //巷道 |
| | | if (Cools.isEmpty(config.getValue())) { |
| | | rStaNo = rStaNo + "01"; |
| | | config.setValue("2"); |
| | | }else if (config.getValue().equals("1")) { |
| | | rStaNo = rStaNo + "01"; |
| | | config.setValue("2"); |
| | | }else if (config.getValue().equals("2")) { |
| | | rStaNo = rStaNo + "02"; |
| | | config.setValue("3"); |
| | | }else if (config.getValue().equals("3")) { |
| | | rStaNo = rStaNo + "03"; |
| | | config.setValue("1"); |
| | | } |
| | | configService.updateById(config); |
| | | } |
| | | |
| | | LinkedHashMap<String,Object> rcsParam=new LinkedHashMap<>(); |
| | | rcsParam.put("taskType", "PF-FMR-COMMON"); |
| | | List<LinkedHashMap<String,Object>> targetRoutes=new ArrayList<>(); |
| | | LinkedHashMap<String,Object> t1=new LinkedHashMap<>(); |
| | | LinkedHashMap<String,Object> t2=new LinkedHashMap<>(); |
| | | t1.put("seq", 0); |
| | | t1.put("type","SITE"); |
| | | t1.put("code", sourceStaNo); |
| | | t1.put("autoStart",0); |
| | | t1.put("operation","COLLECT"); |
| | | |
| | | t2.put("seq", 0); |
| | | t2.put("type",type); |
| | | t2.put("code", rStaNo); |
| | | t2.put("autoStart",0); |
| | | t2.put("operation","DELIVERY"); |
| | | |
| | | targetRoutes.add(t1); |
| | | targetRoutes.add(t2); |
| | | rcsParam.put("targetRoute", targetRoutes); |
| | | rcsParam.put("initPriority", 100); |
| | | |
| | | |
| | | String response =""; |
| | | Boolean bool =false; |
| | | String msg = ""; |
| | | HashMap<String,Object> map = new HashMap<>(); |
| | | Date date = new Date(); |
| | | String time = date.getTime()+""; |
| | | |
| | | map.put("X-LR-REQUEST-ID", time); |
| | | try { |
| | | log.info("wms派发搬运任务给AGV搬运={}", rcsParam); |
| | | response = new HttpHandler.Builder() |
| | | .setHeaders(map) |
| | | .setUri(url) |
| | | .setHttps(true) |
| | | .setPath(attrcs) |
| | | .setJson(JSON.toJSONString(rcsParam)) |
| | | .build() |
| | | .doPostCloseSSL(); |
| | | JSONObject jsonObject = JSON.parseObject(response); |
| | | if(jsonObject.getString("code").equals("SUCCESS")){ |
| | | bool = true; |
| | | }else{ |
| | | msg=jsonObject.getString("message"); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error("wms派发搬运任务给AGV搬运失败返回值={}", response); |
| | | } finally { |
| | | apiLogService.save("wms派发搬运任务给AGV搬运" |
| | | , url + attrcs |
| | | , null |
| | | , "127.0.0.1" |
| | | , JSON.toJSONString(rcsParam) |
| | | , response |
| | | , bool |
| | | ); |
| | | } |
| | | |
| | | if(bool){ |
| | | return R.ok(); |
| | | }else { |
| | | return R.error(msg); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 执行移库任务--点到点 |
| | | * @param sourceStaNo |
| | | * @param staNo |
| | | * @return |
| | | */ |
| | | @RequestMapping("/SITESITEAGVMove") |
| | | public synchronized R SITESITEAGVMove(@RequestParam(required = false) String sourceStaNo |
| | | ,@RequestParam(required = false) String staNo |
| | | ,@RequestParam(required = false) String taskNo){ |
| | | if (Cools.isEmpty(sourceStaNo) || Cools.isEmpty(staNo)) { |
| | | return R.error("源站点和目标站点不能为空"); |
| | | |
| | | } |
| | | |
| | | LinkedHashMap<String,Object> rcsParam=new LinkedHashMap<>(); |
| | | rcsParam.put("taskType", "PF-FMR-COMMON"); |
| | | if(!Cools.isEmpty(taskNo)){ |
| | | rcsParam.put("robotTaskCode", taskNo); |
| | | } |
| | | |
| | | List<LinkedHashMap<String,Object>> targetRoutes=new ArrayList<>(); |
| | | LinkedHashMap<String,Object> t1=new LinkedHashMap<>(); |
| | | LinkedHashMap<String,Object> t2=new LinkedHashMap<>(); |
| | | t1.put("seq", 0); |
| | | t1.put("type","SITE"); |
| | | t1.put("code", sourceStaNo); |
| | | t1.put("autoStart",0); |
| | | t1.put("operation","COLLECT"); |
| | | |
| | | t2.put("seq", 0); |
| | | t2.put("type","SITE"); |
| | | t2.put("code", staNo); |
| | | t2.put("autoStart",0); |
| | | t2.put("operation","DELIVERY"); |
| | | |
| | | targetRoutes.add(t1); |
| | | targetRoutes.add(t2); |
| | | rcsParam.put("targetRoute", targetRoutes); |
| | | rcsParam.put("initPriority", 100); |
| | | |
| | | |
| | | String response =""; |
| | | Boolean bool =false; |
| | | String msg = ""; |
| | | HashMap<String,Object> map = new HashMap<>(); |
| | | Date date = new Date(); |
| | | String time = date.getTime()+""; |
| | | |
| | | map.put("X-LR-REQUEST-ID", time); |
| | | try { |
| | | log.info("wms派发点到点搬运任务给AGV搬运={}", rcsParam); |
| | | response = new HttpHandler.Builder() |
| | | .setHeaders(map) |
| | | .setUri(url) |
| | | .setHttps(true) |
| | | .setPath(attrcs) |
| | | .setJson(JSON.toJSONString(rcsParam)) |
| | | .build() |
| | | .doPostCloseSSL(); |
| | | JSONObject jsonObject = JSON.parseObject(response); |
| | | if(jsonObject.getString("code").equals("SUCCESS")){ |
| | | bool = true; |
| | | }else{ |
| | | msg=jsonObject.getString("message"); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error("wms派发点到点搬运任务给AGV搬运失败返回值={}", response); |
| | | } finally { |
| | | apiLogService.save("wms派发点到点搬运任务给AGV搬运" |
| | | , url + attrcs |
| | | , null |
| | | , "127.0.0.1" |
| | | , JSON.toJSONString(rcsParam) |
| | | , response |
| | | , bool |
| | | ); |
| | | } |
| | | |
| | | if(bool){ |
| | | return R.ok(); |
| | | }else { |
| | | return R.error(msg); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 执行移库任务--点到区域 |
| | | * @param sourceStaNo |
| | | * @param staNo |
| | | * @return |
| | | */ |
| | | @RequestMapping("/SITEZONEAGVMove") |
| | | public synchronized R SITEZONEAGVMove(@RequestParam(required = false) String sourceStaNo |
| | | ,@RequestParam(required = false) String staNo |
| | | ,@RequestParam(required = false) String taskNo){ |
| | | if (Cools.isEmpty(sourceStaNo) || Cools.isEmpty(staNo)) { |
| | | return R.error("源站点和目标站点不能为空"); |
| | | |
| | | } |
| | | LinkedHashMap<String,Object> rcsParam=new LinkedHashMap<>(); |
| | | rcsParam.put("taskType", "PF-FMR-COMMON"); |
| | | if(!Cools.isEmpty(taskNo)){ |
| | | rcsParam.put("robotTaskCode", taskNo); |
| | | } |
| | | |
| | | List<LinkedHashMap<String,Object>> targetRoutes=new ArrayList<>(); |
| | | LinkedHashMap<String,Object> t1=new LinkedHashMap<>(); |
| | | LinkedHashMap<String,Object> t2=new LinkedHashMap<>(); |
| | | t1.put("seq", 0); |
| | | t1.put("type","SITE"); |
| | | t1.put("code", sourceStaNo); |
| | | t1.put("autoStart",0); |
| | | t1.put("operation","COLLECT"); |
| | | |
| | | t2.put("seq", 0); |
| | | t2.put("type","ZONE"); |
| | | t2.put("code", staNo); |
| | | t2.put("autoStart",0); |
| | | t2.put("operation","DELIVERY"); |
| | | |
| | | targetRoutes.add(t1); |
| | | targetRoutes.add(t2); |
| | | rcsParam.put("targetRoute", targetRoutes); |
| | | rcsParam.put("initPriority", 100); |
| | | |
| | | |
| | | String response =""; |
| | | Boolean bool =false; |
| | | String msg = ""; |
| | | HashMap<String,Object> map = new HashMap<>(); |
| | | Date date = new Date(); |
| | | String time = date.getTime()+""; |
| | | |
| | | map.put("X-LR-REQUEST-ID", time); |
| | | try { |
| | | log.info("wms派发点到区域搬运任务给AGV搬运={}", rcsParam); |
| | | response = new HttpHandler.Builder() |
| | | .setHeaders(map) |
| | | .setUri(url) |
| | | .setHttps(true) |
| | | .setPath(attrcs) |
| | | .setJson(JSON.toJSONString(rcsParam)) |
| | | .build() |
| | | .doPostCloseSSL(); |
| | | JSONObject jsonObject = JSON.parseObject(response); |
| | | if(jsonObject.getString("code").equals("SUCCESS")){ |
| | | bool = true; |
| | | }else{ |
| | | msg=jsonObject.getString("message"); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error("wms派发点到区域搬运任务给AGV搬运失败返回值={}", response); |
| | | } finally { |
| | | apiLogService.save("wms派发点到区域搬运任务给AGV搬运" |
| | | , url + attrcs |
| | | , null |
| | | , "127.0.0.1" |
| | | , JSON.toJSONString(rcsParam) |
| | | , response |
| | | , bool |
| | | ); |
| | | } |
| | | |
| | | if(bool){ |
| | | return R.ok(); |
| | | }else { |
| | | return R.error(msg); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 执行移库任务--区域到点 |
| | | * @param sourceStaNo |
| | | * @param staNo |
| | | * @return |
| | | */ |
| | | @RequestMapping("/ZONESITEAGVMove") |
| | | public synchronized R ZONESITEAGVMove(@RequestParam(required = false) String sourceStaNo |
| | | ,@RequestParam(required = false) String staNo |
| | | ,@RequestParam(required = false) String taskNo){ |
| | | if (Cools.isEmpty(sourceStaNo) || Cools.isEmpty(staNo)) { |
| | | return R.error("源站点和目标站点不能为空"); |
| | | |
| | | } |
| | | LinkedHashMap<String,Object> rcsParam=new LinkedHashMap<>(); |
| | | rcsParam.put("taskType", "PF-FMR-COMMON"); |
| | | if(!Cools.isEmpty(taskNo)){ |
| | | rcsParam.put("robotTaskCode", taskNo); |
| | | } |
| | | |
| | | List<LinkedHashMap<String,Object>> targetRoutes=new ArrayList<>(); |
| | | LinkedHashMap<String,Object> t1=new LinkedHashMap<>(); |
| | | LinkedHashMap<String,Object> t2=new LinkedHashMap<>(); |
| | | t1.put("seq", 0); |
| | | t1.put("type","ZONE"); |
| | | t1.put("code", sourceStaNo); |
| | | t1.put("autoStart",0); |
| | | t1.put("operation","COLLECT"); |
| | | |
| | | t2.put("seq", 0); |
| | | t2.put("type","SITE"); |
| | | t2.put("code", staNo); |
| | | t2.put("autoStart",0); |
| | | t2.put("operation","DELIVERY"); |
| | | |
| | | targetRoutes.add(t1); |
| | | targetRoutes.add(t2); |
| | | rcsParam.put("targetRoute", targetRoutes); |
| | | rcsParam.put("initPriority", 100); |
| | | |
| | | |
| | | String response =""; |
| | | Boolean bool =false; |
| | | String msg = ""; |
| | | HashMap<String,Object> map = new HashMap<>(); |
| | | Date date = new Date(); |
| | | String time = date.getTime()+""; |
| | | |
| | | map.put("X-LR-REQUEST-ID", time); |
| | | try { |
| | | log.info("wms派发点到区域搬运任务给AGV搬运={}", rcsParam); |
| | | response = new HttpHandler.Builder() |
| | | .setHeaders(map) |
| | | .setUri(url) |
| | | .setHttps(true) |
| | | .setPath(attrcs) |
| | | .setJson(JSON.toJSONString(rcsParam)) |
| | | .build() |
| | | .doPostCloseSSL(); |
| | | JSONObject jsonObject = JSON.parseObject(response); |
| | | if(jsonObject.getString("code").equals("SUCCESS")){ |
| | | bool = true; |
| | | }else{ |
| | | msg=jsonObject.getString("message"); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error("wms派发点到区域搬运任务给AGV搬运失败返回值={}", response); |
| | | } finally { |
| | | apiLogService.save("wms派发点到区域搬运任务给AGV搬运" |
| | | , url + attrcs |
| | | , null |
| | | , "127.0.0.1" |
| | | , JSON.toJSONString(rcsParam) |
| | | , response |
| | | , bool |
| | | ); |
| | | } |
| | | |
| | | if(bool){ |
| | | return R.ok(); |
| | | }else { |
| | | return R.error(msg); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * AGV站点绑定和解绑 |
| | | * @param sourceStaNo //站点 |
| | | * @param barcodeType //托盘码 |
| | | * @param invoke //BIND为绑定 UNBIND为解绑 |
| | | * @return |
| | | */ |
| | | @RequestMapping("/siteBindAndUnbind") |
| | | public synchronized R siteBindAndUnbind(@RequestParam(required = false) String sourceStaNo |
| | | ,@RequestParam(required = false) String barcodeType |
| | | ,@RequestParam(required = false) String invoke){ |
| | | if (Cools.isEmpty(sourceStaNo) || Cools.isEmpty(barcodeType)) { |
| | | return R.error("站点和托盘类型不能为空"); |
| | | |
| | | } |
| | | if(barcodeType.substring(0,1).equals("8")){ |
| | | barcodeType="11"; |
| | | }else if(barcodeType.substring(0,1).equals("9")){ |
| | | barcodeType="21"; |
| | | } |
| | | LinkedHashMap<String,Object> rcsParam=new LinkedHashMap<>(); |
| | | rcsParam.put("slotCategory", "SITE"); |
| | | rcsParam.put("slotCode", sourceStaNo); |
| | | rcsParam.put("carrierCategory", "PALLET"); |
| | | rcsParam.put("carrierType", barcodeType);//11为小托盘 21为大托盘 |
| | | |
| | | rcsParam.put("carrierDir",sourceStaNo.equals("101")? "0":"180"); |
| | | rcsParam.put("temporary", ""); |
| | | rcsParam.put("invoke", invoke); |
| | | |
| | | |
| | | String response =""; |
| | | Boolean bool =false; |
| | | String msg = ""; |
| | | HashMap<String,Object> map = new HashMap<>(); |
| | | Date date = new Date(); |
| | | String time = date.getTime()+""; |
| | | |
| | | map.put("X-LR-REQUEST-ID", time); |
| | | try { |
| | | log.info("WMS完成"+invoke+"agv站点={},上报参数为={}",sourceStaNo,rcsParam); |
| | | response = new HttpHandler.Builder() |
| | | .setHeaders(map) |
| | | .setUri(url) |
| | | .setHttps(true) |
| | | .setPath(siteBindAndUnbing) |
| | | .setJson(JSON.toJSONString(rcsParam)) |
| | | .build() |
| | | .doPostCloseSSL(); |
| | | JSONObject jsonObject = JSON.parseObject(response); |
| | | if(jsonObject.getString("code").equals("SUCCESS")){ |
| | | bool = true; |
| | | }else{ |
| | | msg=jsonObject.getString("message"); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error("WMS完成"+invoke+"agv站点失败={}", response); |
| | | } finally { |
| | | apiLogService.save("WMS完成"+invoke+"agv站点"+sourceStaNo |
| | | , url + siteBindAndUnbing |
| | | , null |
| | | , "127.0.0.1" |
| | | , JSON.toJSONString(rcsParam) |
| | | , response |
| | | , bool |
| | | ); |
| | | } |
| | | |
| | | if(bool){ |
| | | return R.ok(); |
| | | }else { |
| | | return R.error(msg); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 空板回库或者拣料回库 |
| | | * @param sourceStaNo |
| | | * @param staNo |
| | | * @return |
| | | */ |
| | | @RequestMapping("/AGVStartReturn") |
| | | public synchronized R AGVStartReturn(@RequestParam(required = false) String sourceStaNo |
| | | ,@RequestParam(required = false) String staNo |
| | | ,@RequestParam(required = false) String taskNo){ |
| | | if (Cools.isEmpty(sourceStaNo) || Cools.isEmpty(staNo)) { |
| | | return R.error("源站点和托盘码不能为空"); |
| | | |
| | | } |
| | | |
| | | R r=R.ok(); |
| | | |
| | | WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("barcode", staNo).in("io_type",103,105,107)); |
| | | if (wrkMast == null) { |
| | | r=FillEmptyPalletsStack(sourceStaNo,staNo); |
| | | }else { |
| | | if (wrkMast.getWrkSts()>30){ |
| | | return R.error("该托盘={},没有下架,请下架后再回库!!!"); |
| | | } |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| | | String format = sdf.format(new Date()); |
| | | String s = format+"-" + wrkMast.getWrkNo() + "-" + wrkMast.getBarcode(); |
| | | r=SITESITEAGVMove(sourceStaNo,wrkMast.getStaNo$(),s); |
| | | if (r.get("code").equals(200)) { |
| | | wrkMast.setPdcType(s); |
| | | /** |
| | | * inv_wh |
| | | * 拣料回库输送线出发 |
| | | * 0等待agv放货完成 |
| | | * 1等待输送线入库 |
| | | * 2输送线入库任务下发成功 |
| | | */ |
| | | wrkMast.setInvWh("0"); |
| | | wrkMastService.updateById(wrkMast); |
| | | } |
| | | } |
| | | |
| | | return r; |
| | | } |
| | | |
| | | /** |
| | | * 获取仓库 |
| | | * @return |
| | | */ |
| | | @RequestMapping("/ck") |
| | | @PostMapping |
| | | public R AGVStartReturn(){ |
| | | List<String> list=new ArrayList<>(); |
| | | list.add("半成品仓库"); |
| | | list.add("成品仓库"); |
| | | return R.ok(list); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | package com.zy.asrs.controller; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.annotations.AppAuth; |
| | | import com.core.common.*; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.entity.WaitPakin; |
| | | import com.zy.asrs.entity.WrkMast; |
| | | import com.zy.asrs.entity.param.*; |
| | | import com.zy.asrs.entity.result.RobotTaskMessage; |
| | | import com.zy.asrs.service.OpenService; |
| | | import com.zy.asrs.service.WaitPakinService; |
| | | import com.zy.asrs.service.WrkMastService; |
| | | import com.zy.common.model.DetlDto; |
| | | import com.zy.common.web.BaseController; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | |
| | | @Autowired |
| | | private OpenService openService; |
| | | @Autowired |
| | | private WaitPakinService waitPakinService; |
| | | @Autowired |
| | | private WrkMastService wrkMastService; |
| | | |
| | | /** |
| | | * RGV任务反馈 |
| | | * 1:任务开始 |
| | | * 2:取到载具 |
| | | * 3:离开起点 |
| | | * 4:任务完成 |
| | | */ |
| | | @RequestMapping(value = "/api/robot/reporter/task") |
| | | public HashMap<String, Object> RGVtask(@RequestBody RobotTaskMessage robotTaskMessage) { |
| | | HashMap<String, Object> map = new HashMap<>(); |
| | | RobotTaskMessage.Extra extra = robotTaskMessage.getExtra(); |
| | | RobotTaskMessage.Values values = extra.getValues(); |
| | | int method = values.getMethod(); |
| | | log.info("agv任务反馈AGV任务号={}任务状态为={}",robotTaskMessage.getRobotTaskCode(),method); |
| | | if(method == 4){ |
| | | WaitPakin waitPakin = waitPakinService.selectOne(new EntityWrapper<WaitPakin>() |
| | | .eq("supp", robotTaskMessage.getRobotTaskCode()) |
| | | .eq("be_batch",2)); |
| | | if(!Cools.isEmpty(waitPakin)){ |
| | | /** |
| | | * agv状态 |
| | | * be_batch |
| | | * 0:无需调用AGV |
| | | * 1:等待调用AGV |
| | | * 2:AGV任务下发成功 |
| | | * 3:AGV任务完成 |
| | | * 4:给输送线下发入库指令完成 |
| | | */ |
| | | waitPakin.setBeBatch(3); |
| | | waitPakinService.update(waitPakin,new EntityWrapper<WaitPakin>().eq("supp_code",waitPakin.getSuppCode())); |
| | | } |
| | | |
| | | //拣料回库,agv搬运货物到输送线入库口--》修改inv_wh状态等待输送线入库--》wcs下发入库指令 |
| | | WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>() |
| | | .in("wrk_sts", 16L)//16.下架完成等待回库 |
| | | .eq("inv_wh","0") |
| | | .eq("pdc_type", robotTaskMessage.getRobotTaskCode()));//AGV出库搬运任务号 |
| | | if(!Cools.isEmpty(wrkMast)){ |
| | | /** |
| | | * inv_wh |
| | | * 拣料回库输送线出发 |
| | | * 0等待agv放货完成 |
| | | * 1等待输送线入库 |
| | | * 2输送线入库任务下发成功 |
| | | */ |
| | | wrkMast.setInvWh("1"); |
| | | wrkMast.setModiTime(new Date()); |
| | | wrkMastService.updateById(wrkMast); |
| | | } |
| | | |
| | | } |
| | | if(method == 3 || method == 4){ |
| | | /** |
| | | * wrk_sts |
| | | * 30.等待给AGV下发出库任务 |
| | | * 31.AGV出库任务下发成功 |
| | | * 32.AGV已搬离 |
| | | * 33.等待下架 |
| | | */ |
| | | WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>() |
| | | .in("wrk_sts", 31L)//31.AGV出库任务下发成功 |
| | | .eq("Pdc_type", robotTaskMessage.getRobotTaskCode()));//AGV出库搬运任务号 |
| | | if(!Cools.isEmpty(wrkMast)){ |
| | | wrkMast.setWrkSts(32L);//31.AGV出库任务下发成功---->32.AGV已搬离 32后移交给wcs系统,对站点信息进行清除 |
| | | wrkMast.setModiTime(new Date()); |
| | | wrkMastService.updateById(wrkMast); |
| | | } |
| | | } |
| | | map.put("code", "SUCCESS"); |
| | | map.put("message", "成功"); |
| | | return map; |
| | | } |
| | | |
| | | @PostMapping("/order/matSync/default/v1") |
| | | @AppAuth(memo = "商品信息同步接口") |
| | |
| | | if (issued > 0) { |
| | | LocDto locDto = new LocDto(locDetl.getLocNo(), locDetl.getMatnr(), locDetl.getMaktx(), locDetl.getBatch(), orderDetl.getOrderNo(), |
| | | issued >= locDetl.getAnfme() ? locDetl.getAnfme() : issued); |
| | | List<Integer> staNos = staDescService.queryOutStaNosByLocNo(locDetl.getLocNo(), issued >= locDetl.getAnfme() ? 101 : 103); |
| | | List<String> staNos = new ArrayList<>(); |
| | | staNos.add("C1"); |
| | | staNos.add("C2"); |
| | | staNos.add("C3"); |
| | | locDto.setStaNos(staNos); |
| | | locDtos.add(locDto); |
| | | exist.add(locDetl.getLocNo()); |
| | |
| | | } |
| | | // ----------------------------------------------------------------------------------------------- |
| | | for (TaskDto taskDto : taskDtos) { |
| | | BasDevp staNo = basDevpService.checkSiteStatus(taskDto.getStaNo()); |
| | | workService.stockOut(staNo, taskDto, getUserId()); |
| | | workService.stockOut(null, taskDto, getUserId(), taskDto.getStaNo()); |
| | | } |
| | | return R.ok(); |
| | | } |
| | |
| | | package com.zy.asrs.controller; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | |
| | | return R.ok(); |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | @ManagerAuth() |
| | | public R availableTakeSite(){ |
| | | List<Map<String, Object>> result = new ArrayList<>(); |
| | | List<Integer> outSite = basDevpService.getAvailableOutSite(101); |
| | | for (Integer siteId : outSite) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("siteId", siteId); |
| | | map.put("desc", siteId + "(全板出库口)"); |
| | | result.add(map); |
| | | } |
| | | List<Integer> pickOutSite = basDevpService.getAvailableOutSite(103); |
| | | for (Integer siteId : pickOutSite) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("siteId", siteId); |
| | | map.put("desc", siteId + "(拣料出库口)"); |
| | | result.add(map); |
| | | } |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("siteId", "C1"); |
| | | map.put("desc", "C1" + "(出库口1)"); |
| | | result.add(map); |
| | | Map<String, Object> map1 = new HashMap<>(); |
| | | map1.put("siteId", "C2"); |
| | | map1.put("desc", "C2" + "(出库口2)"); |
| | | result.add(map1); |
| | | Map<String, Object> map2 = new HashMap<>(); |
| | | map2.put("siteId", "C3"); |
| | | map2.put("desc", "C3" + "(出库口3)"); |
| | | result.add(map2); |
| | | return R.ok().add(result); |
| | | } |
| | | |
| | |
| | | @ApiModelProperty(value= "批号") |
| | | private String batch; |
| | | |
| | | /** |
| | | * 该字段是组托入库自动出发补空托盘标记 |
| | | * item_num |
| | | * 0:不需要补空托盘 |
| | | * 1:小托盘 |
| | | * 2:大托盘 |
| | | * 10:小托盘AGV任务下发成功 |
| | | * 20:大托盘AGV任务下发成功 |
| | | * 100:小托盘放货完成 |
| | | * 200:大托盘放货完成 |
| | | */ |
| | | @ApiModelProperty(value= "大小托盘") |
| | | @TableField("item_num") |
| | | private String itemNum; |
| | | /** |
| | | * agv状态 |
| | | * be_batch |
| | | * 0:无需调用AGV |
| | | * 1:等待调用AGV |
| | | * 2:AGV任务下发成功 |
| | | * 3:AGV任务完成 |
| | | * 4:给输送线下发入库指令完成 |
| | | */ |
| | | |
| | | @ApiModelProperty(value= "agv状态") |
| | | @TableField("be_batch") |
| | | private Integer beBatch = 0; |
| | | |
| | | /** |
| | | * 目标站 |
| | | */ |
| | | @ApiModelProperty(value= "目标站") |
| | | private String sku; |
| | | |
| | | |
| | | |
| | | @ApiModelProperty(value= "发给AGV的任务号") |
| | | private String supp; |
| | | |
| | | @ApiModelProperty(value= "仓库") |
| | | private String brand; |
| | | |
| | | @ApiModelProperty(value= "唯一码") |
| | | @TableField("supp_code") |
| | | private String suppCode; |
| | | |
| | | @ApiModelProperty(value= "单据编号") |
| | | @TableField("order_no") |
| | | private String orderNo; |
| | |
| | | @ApiModelProperty(value= "颜色") |
| | | private String color; |
| | | |
| | | @ApiModelProperty(value= "品牌") |
| | | private String brand; |
| | | |
| | | @ApiModelProperty(value= "单位") |
| | | private String unit; |
| | | |
| | | @ApiModelProperty(value= "单价") |
| | | private Double price; |
| | | |
| | | @ApiModelProperty(value= "sku") |
| | | private String sku; |
| | | |
| | | @ApiModelProperty(value= "单位量") |
| | | private Double units; |
| | |
| | | @TableField("manu_date") |
| | | private String manuDate; |
| | | |
| | | @ApiModelProperty(value= "品项数") |
| | | @TableField("item_num") |
| | | private String itemNum; |
| | | |
| | | @ApiModelProperty(value= "安全库存量") |
| | | @TableField("safe_qty") |
| | | private Double safeQty; |
| | |
| | | @ApiModelProperty(value= "三方编码") |
| | | @TableField("three_code") |
| | | private String threeCode; |
| | | |
| | | @ApiModelProperty(value= "供应商") |
| | | private String supp; |
| | | |
| | | @ApiModelProperty(value= "供应商编码") |
| | | @TableField("supp_code") |
| | | private String suppCode; |
| | | |
| | | @ApiModelProperty(value= "是否批次 1: 是 0: 否 ") |
| | | @TableField("be_batch") |
| | | private Integer beBatch; |
| | | |
| | | @ApiModelProperty(value= "保质期") |
| | | @TableField("dead_time") |
| | |
| | | @TableField("wrk_no") |
| | | private Integer wrkNo; |
| | | |
| | | @ApiModelProperty(value= "") |
| | | // AGV下发的出库任务 |
| | | @ApiModelProperty(value= "AGV下发的出库任务") |
| | | @TableField("Pdc_type") |
| | | private String PdcType; |
| | | |
| | | @ApiModelProperty(value= "1:任务AGV入库站点解绑") |
| | | @TableField("ctn_kind") |
| | | private Integer ctnKind; |
| | | |
| | | /** |
| | | * inv_wh |
| | | * 拣料回库输送线出发 |
| | | * 0等待agv放货完成 |
| | | * 1等待输送线入库 |
| | | * 2输送线入库任务下发成功 |
| | | */ |
| | | @ApiModelProperty(value= "拣料回库输送线入库触发") |
| | | @TableField("inv_wh") |
| | | private String invWh; |
| | | |
| | |
| | | |
| | | /** |
| | | * 工作状态 |
| | | * 30:等待agv取货 |
| | | */ |
| | | @ApiModelProperty(value= "工作状态") |
| | | @TableField("wrk_sts") |
| | |
| | | private String errorMemo; |
| | | |
| | | @ApiModelProperty(value= "") |
| | | @TableField("ctn_kind") |
| | | private Integer ctnKind; |
| | | |
| | | @ApiModelProperty(value= "") |
| | | @TableField("manu_type") |
| | | private String manuType; |
| | | |
| | |
| | | */ |
| | | @ApiModelProperty(value= "条码") |
| | | private String barcode; |
| | | |
| | | // Y:销售订单出库任务 |
| | | @ApiModelProperty(value= "") |
| | | @TableField("Pdc_type") |
| | | private String PdcType; |
| | | |
| | | @ApiModelProperty(value= "") |
| | | @TableField("ctn_no") |
| | |
| | | // 库位编号 |
| | | private String locno; |
| | | |
| | | //源站点 |
| | | private String rsta; |
| | | |
| | | //大小托盘 |
| | | private String barcodeSize; |
| | | |
| | | private String ck; |
| | | |
| | | //agv状态 |
| | | /** |
| | | * 0:无需调用AGV |
| | | * 1:等待调用AGV |
| | | * 2:AGV任务下发成功 |
| | | * 3:AGV任务完成 |
| | | * 4:给输送线下发入库指令 |
| | | */ |
| | | private Integer beBatch = 0; |
| | | |
| | | private List<CombMat> combMats; |
| | | |
| | | @Data |
| | |
| | | public class StockOutParam { |
| | | |
| | | // 出站口 |
| | | private Integer outSite; |
| | | private String outSite; |
| | | |
| | | // 物料编号集合 |
| | | private List<LocDetl> locDetls; |
| New file |
| | |
| | | package com.zy.asrs.entity.result; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class RobotTaskMessage { |
| | | private int currentSeq; |
| | | private Extra extra; |
| | | private String robotTaskCode; |
| | | private String singleRobotCode; |
| | | |
| | | @Data |
| | | public static class Extra { |
| | | private int async; |
| | | private Values values; |
| | | } |
| | | |
| | | @Data |
| | | public static class Values { |
| | | private String mapCode; |
| | | private String slotCategory; |
| | | private String slotCode; |
| | | private String slotName; |
| | | private double x; |
| | | private double y; |
| | | private int method; |
| | | private String carrierCategory; |
| | | private int carrierType; |
| | | private String carrierCode; |
| | | private int pileCount; |
| | | private String zoneCode; |
| | | private String amrCategory; |
| | | private int amrType; |
| | | private String amrCode; |
| | | private String carrierName; |
| | | private int layerNo; |
| | | } |
| | | } |
| | |
| | | * @param locDetls 待出库物料 |
| | | * @param ioType 入出库类型 |
| | | */ |
| | | void stockOut(BasDevp staNo, List<LocDetlDto> locDetls, IoWorkType ioWorkType, Long userId); |
| | | void stockOut(BasDevp staNo, List<LocDetlDto> locDetls, IoWorkType ioWorkType, Long userId,String agvStaNo); |
| | | |
| | | void stockOut(BasDevp staNo, TaskDto taskDto, Long userId); |
| | | void stockOut(BasDevp staNo, TaskDto taskDto, Long userId,String agvStaNo); |
| | | |
| | | /** |
| | | * 空板入库 |
| | |
| | | if (locMast == null) { |
| | | return false; |
| | | } |
| | | return this.baseMapper.selectEmptyLocCount(locMast.getLocType1(), locMast.getCrnNo()) > 1; |
| | | return this.baseMapper.selectEmptyLocCount(locMast.getLocType1(), locMast.getCrnNo()) > 5; |
| | | } |
| | | |
| | | @Override |
| | |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * 移动端服务核心类 |
| | |
| | | |
| | | Date now = new Date(); |
| | | |
| | | Set<String> batchs=new HashSet<>(); |
| | | |
| | | for(CombParam.CombMat mat : param.getCombMats()){ |
| | | if(Cools.isEmpty(mat.getBatch())){ |
| | | throw new CoolException("物料批号不能为空"); |
| | | } |
| | | batchs.add(mat.getBatch()); |
| | | } |
| | | if(batchs.size()<param.getCombMats().size()){ |
| | | throw new CoolException("有重复的物料批号"); |
| | | } |
| | | int i =1; |
| | | // 无单组托 |
| | | if (Cools.isEmpty(param.getOrderNo())) { |
| | | |
| | |
| | | waitPakin.setAppeTime(now); |
| | | waitPakin.setModiUser(userId); |
| | | waitPakin.setModiTime(now); |
| | | if (!waitPakinService.insert(waitPakin)) { |
| | | waitPakin.setBrand(param.getCk());//仓库 |
| | | if(i==1){ |
| | | // 0:不需要补空托盘 |
| | | // 1:小托盘 |
| | | // 2:大托盘 |
| | | waitPakin.setItemNum(param.getBarcodeSize()); |
| | | waitPakin.setMemo(Cools.isEmpty(param.getRsta()) ? "" : param.getRsta());//源站点 |
| | | /** |
| | | * agv状态 |
| | | * 0:无需调用AGV |
| | | * 1:等待调用AGV |
| | | * 2:AGV任务下发成功 |
| | | * 3:AGV任务完成 |
| | | * 4:给输送线下发入库指令 |
| | | */ |
| | | waitPakin.setBeBatch(param.getBeBatch()); |
| | | waitPakin.setSuppCode(param.getBarcode()); |
| | | } |
| | | i++; |
| | | if (!waitPakinService.insert(waitPakin)) { |
| | | throw new CoolException("保存入库通知档失败"); |
| | | } |
| | | } |
| | |
| | | waitPakin.setAppeTime(now); |
| | | waitPakin.setModiUser(userId); |
| | | waitPakin.setModiTime(now); |
| | | if(i==1){ |
| | | // 0:不需要补空托盘 |
| | | // 1:小托盘 |
| | | // 2:大托盘 |
| | | waitPakin.setItemNum(param.getBarcodeSize()); |
| | | waitPakin.setMemo(Cools.isEmpty(param.getRsta()) ? "" : param.getRsta());//源站点 |
| | | /** |
| | | * agv状态 |
| | | * 0:无需调用AGV |
| | | * 1:等待调用AGV |
| | | * 2:AGV任务下发成功 |
| | | * 3:AGV任务完成 |
| | | * 4:给输送线下发入库指令 |
| | | */ |
| | | waitPakin.setBeBatch(param.getBeBatch()); |
| | | waitPakin.setSuppCode(param.getBarcode()); |
| | | } |
| | | i++; |
| | | if (!waitPakinService.insert(waitPakin)) { |
| | | throw new CoolException("保存入库通知档失败"); |
| | | } |
| | |
| | | @Override |
| | | @Transactional |
| | | public void startupFullTakeStore(StockOutParam param, Long userId) { |
| | | // 目标站点状态检测 |
| | | BasDevp staNo = basDevpService.checkSiteStatus(param.getOutSite()); |
| | | String agvStaNo = param.getOutSite(); |
| | | // 获取库位明细 |
| | | List<LocDetlDto> locDetlDtos = new ArrayList<>(); |
| | | for (StockOutParam.LocDetl paramLocDetl : param.getLocDetls()) { |
| | |
| | | } |
| | | } |
| | | if (!locDetlDtos.isEmpty()) { |
| | | |
| | | // 启动出库开始 101.出库 |
| | | stockOut(staNo, locDetlDtos, null, userId); |
| | | stockOut(null, locDetlDtos, null, userId,agvStaNo); |
| | | } else { |
| | | throw new CoolException("库存不存在"); |
| | | } |
| | |
| | | |
| | | @Override |
| | | @Transactional |
| | | public void stockOut(BasDevp staNo, List<LocDetlDto> locDetlDtos, IoWorkType ioWorkType, Long userId) { |
| | | public void stockOut(BasDevp staNo, List<LocDetlDto> locDetlDtos, IoWorkType ioWorkType, Long userId,String agvStaNo) { |
| | | Date now = new Date(); |
| | | // 合并同类项 |
| | | Set<String> locNos = new HashSet<>(); |
| | |
| | | if(!locMast.getLocSts().equals("F")){ |
| | | throw new CoolException(dto.getLocNo()+"托盘非在库状态"); |
| | | } |
| | | Integer outSta = 0; |
| | | if(locMast.getCrnNo()==1){ |
| | | outSta = 105; |
| | | }else if(locMast.getCrnNo()==2){ |
| | | outSta = 103; |
| | | }else if(locMast.getCrnNo()==3){ |
| | | outSta = 101; |
| | | } |
| | | |
| | | Integer outSta = staNo.getDevNo(); |
| | | //2号堆垛机全板出库站指定为204站,拣料站指定为202 |
| | | // if(locMast.getCrnNo()==2){ |
| | | // outSta = ioType == 101 ? 204 : 202; |
| | |
| | | wrkMast.setAppeTime(now); |
| | | wrkMast.setModiUser(userId); |
| | | wrkMast.setModiTime(now); |
| | | wrkMast.setMemo(Cools.isEmpty(agvStaNo) ? "" : agvStaNo); |
| | | if (!wrkMastService.insert(wrkMast)) { |
| | | throw new CoolException("保存工作档失败,出库库位号:"+dto.getLocNo()); |
| | | } |
| | |
| | | |
| | | @Override |
| | | @Transactional |
| | | public void stockOut(BasDevp staNo, TaskDto taskDto, Long userId) { |
| | | public void stockOut(BasDevp staNo, TaskDto taskDto, Long userId,String agvStaNo) { |
| | | Date now = new Date(); |
| | | List<LocDto> locDtos = taskDto.getLocDtos(); |
| | | for (LocDto locDto : locDtos) { |
| | |
| | | LocMast locMast = locMastService.selectById(taskDto.getLocNo()); |
| | | // 获取路径 |
| | | int ioType = taskDto.isAll() ? 101 : 103; |
| | | StaDesc staDesc = staDescService.queryCrnStnAuto(ioType, locMast.getCrnNo(), staNo.getDevNo()); |
| | | Integer outSta = 0; |
| | | if(locMast.getCrnNo()==1){ |
| | | outSta = 106; |
| | | }else if(locMast.getCrnNo()==2){ |
| | | outSta = 104; |
| | | }else if(locMast.getCrnNo()==3){ |
| | | outSta = 102; |
| | | } |
| | | |
| | | StaDesc staDesc = staDescService.queryCrnStnAuto(ioType, locMast.getCrnNo(),outSta); |
| | | // 生成工作号 |
| | | int workNo = commonService.getWorkNo(WorkNoType.getWorkNoType(ioType)); |
| | | // 生成工作档 |
| | |
| | | wrkMast.setAppeTime(now); |
| | | wrkMast.setModiUser(userId); |
| | | wrkMast.setModiTime(now); |
| | | wrkMast.setMemo(Cools.isEmpty(agvStaNo) ? "" : agvStaNo); |
| | | if (!wrkMastService.insert(wrkMast)) { |
| | | throw new CoolException("保存工作档失败,出库库位号:"+taskDto.getLocNo()); |
| | | } |
| | |
| | | @Override |
| | | @Transactional |
| | | public void locCheckOut(StockOutParam param, Long userId) { |
| | | // 目标站点状态检测 |
| | | BasDevp staNo = basDevpService.checkSiteStatus(param.getOutSite()); |
| | | |
| | | // 获取库位明细 |
| | | List<LocDetlDto> locDetlDtos = new ArrayList<>(); |
| | | for (StockOutParam.LocDetl paramLocDetl : param.getLocDetls()) { |
| | |
| | | } |
| | | if (!locDetlDtos.isEmpty()) { |
| | | // 启动出库开始 107.盘点出库 |
| | | stockOut(staNo, locDetlDtos, IoWorkType.CHECK_OUT, userId); |
| | | stockOut(null, locDetlDtos, IoWorkType.CHECK_OUT, userId,null); |
| | | } else { |
| | | throw new CoolException("库位物料不存在"); |
| | | } |
| New file |
| | |
| | | package com.zy.asrs.task; |
| | | |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.common.Cools; |
| | | import com.core.common.R; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.controller.MobileController; |
| | | import com.zy.asrs.entity.BasDevp; |
| | | import com.zy.asrs.entity.RowLastno; |
| | | import com.zy.asrs.entity.WaitPakin; |
| | | import com.zy.asrs.entity.WrkMast; |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.asrs.task.core.ReturnT; |
| | | import com.zy.common.service.CommonService; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDate; |
| | | import java.util.Date; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * 自动派发任务给AGV |
| | | */ |
| | | @Component |
| | | public class AutoAssignAGVTasks { |
| | | private static final Logger log = LoggerFactory.getLogger(WorkMastScheduler.class); |
| | | |
| | | @Autowired |
| | | private WaitPakinService waitPakinService; |
| | | @Autowired |
| | | private MobileController mobileController; |
| | | @Autowired |
| | | private RowLastnoService rowLastnoService; |
| | | @Autowired |
| | | private BasCrnpService basCrnpService; |
| | | @Autowired |
| | | private CommonService commonService; |
| | | @Autowired |
| | | private WrkMastService wrkMastService; |
| | | @Autowired |
| | | private BasDevpService basDevpService; |
| | | |
| | | /** |
| | | * 自动派发入库任务给AGV |
| | | */ |
| | | @Scheduled(cron = "0/3 * * * * ? ") |
| | | private synchronized void execute(){ |
| | | /** |
| | | * agv状态 |
| | | * be_batch |
| | | * 0:无需调用AGV |
| | | * 1:等待调用AGV |
| | | * 2:AGV任务下发成功 |
| | | * 3:AGV任务完成 |
| | | * 4:给输送线下发入库指令 |
| | | */ |
| | | List<WaitPakin> beBatchs = waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("be_batch", 1).orderBy("zpallet ASC")); |
| | | if (beBatchs.isEmpty()) { |
| | | return; |
| | | } |
| | | List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().in("io_type", 101, 103, 110, 107).le("wrk_sts",14)); |
| | | if(!Cools.isEmpty(wrkMasts)){ |
| | | log.info("当前有出库任务数={},正在进行无法呼叫agv入库",wrkMasts.size()); |
| | | return; |
| | | } |
| | | //对相同托盘号进行跳过 |
| | | String zpallet=""; |
| | | for (WaitPakin waitPakin : beBatchs) { |
| | | if(Cools.isEmpty(zpallet)){ |
| | | zpallet=waitPakin.getZpallet(); |
| | | }else if(zpallet.equals(waitPakin.getZpallet())){ |
| | | continue; |
| | | } |
| | | |
| | | if(Cools.isEmpty(waitPakin.getMemo())){ |
| | | log.error("入库通知档托盘码={},源站点[memo]为空",waitPakin.getZpallet()); |
| | | continue; |
| | | } |
| | | String i= waitPakin.getZpallet().substring(0,1); |
| | | String staNo = ""; |
| | | //大托盘入库目标站点105 |
| | | if(i.equals("9")){ |
| | | staNo = "105"; |
| | | }else { |
| | | //小托盘入库则按入库规则交替入库 |
| | | //将堆垛机排序 |
| | | //检测堆垛机是否正常,跳过不正常的堆垛机 |
| | | Integer[] crns=new Integer[2]; |
| | | RowLastno wrkMk = rowLastnoService.selectOne(new EntityWrapper<RowLastno>().eq("wrk_mk", "1")); |
| | | if(Cools.isEmpty(wrkMk)){ |
| | | RowLastno whsType = rowLastnoService.selectOne(new EntityWrapper<RowLastno>().eq("whs_type", "2")); |
| | | whsType.setWrkMk("1"); |
| | | rowLastnoService.updateById(whsType); |
| | | crns[0]=2; |
| | | crns[1]=3; |
| | | }else { |
| | | if(wrkMk.getWhsType()==2){ |
| | | crns[0]=2; |
| | | crns[1]=3; |
| | | wrkMk.setWrkMk("0"); |
| | | rowLastnoService.updateById(wrkMk); |
| | | RowLastno whsType = rowLastnoService.selectOne(new EntityWrapper<RowLastno>().eq("whs_type", "3")); |
| | | whsType.setWrkMk("1"); |
| | | rowLastnoService.updateById(whsType); |
| | | }else { |
| | | crns[0]=3; |
| | | crns[1]=2; |
| | | wrkMk.setWrkMk("0"); |
| | | rowLastnoService.updateById(wrkMk); |
| | | RowLastno whsType = rowLastnoService.selectOne(new EntityWrapper<RowLastno>().eq("whs_type", "2")); |
| | | whsType.setWrkMk("1"); |
| | | rowLastnoService.updateById(whsType); |
| | | } |
| | | //检测堆垛机是否正常 |
| | | for(int j=0;j<crns.length;j++){ |
| | | boolean b = basCrnpService.checkSiteError(crns[j], false); |
| | | if(b){ |
| | | if(crns[j]==2){ |
| | | staNo = "103"; |
| | | }else { |
| | | staNo = "101"; |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | if (Cools.isEmpty(staNo)) { |
| | | return; |
| | | } |
| | | //AGV目标站点已经在做任务时跳过 |
| | | WaitPakin waitPakin1 = waitPakinService.selectOne(new EntityWrapper<WaitPakin>().eq("sku", staNo).in("be_batch", 2,3)); |
| | | if (!Cools.isEmpty(waitPakin1)) { |
| | | continue; |
| | | } |
| | | |
| | | int workNo = commonService.getWorkNo(0); |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| | | String format = sdf.format(new Date()); |
| | | String s = format+"-" + workNo; |
| | | log.info("给agv下发入库搬运任务={}",waitPakin); |
| | | R r = mobileController.SITESITEAGVMove(waitPakin.getMemo(), staNo,s); |
| | | if (r.get("code").equals(200)) { |
| | | waitPakin.setSupp(s);//发给agv的任务号 |
| | | waitPakin.setSku(staNo);//目标站点 |
| | | waitPakin.setBeBatch(2);//2:AGV任务下发成功 |
| | | waitPakinService.update(waitPakin,new EntityWrapper<WaitPakin>().eq("supp_code",waitPakin.getSuppCode())); |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 自动派发补空板任务给AGV |
| | | */ |
| | | @Scheduled(cron = "0/3 * * * * ? ") |
| | | private synchronized void autoFillEmptyPallets(){ |
| | | /** |
| | | * 该字段是组托入库自动出发补空托盘标记 |
| | | * item_num |
| | | * 0:不需要补空托盘 |
| | | * 1:小托盘 |
| | | * 2:大托盘 |
| | | * 10:小托盘AGV任务下发成功 |
| | | * 20:大托盘AGV任务下发成功 |
| | | * ---------------------------------------------------------------------- |
| | | * 下面的暂时用不到 |
| | | * 100:小托盘放货完成 |
| | | * 200:大托盘放货完成 |
| | | */ |
| | | List<WaitPakin> waitPakins = waitPakinService.selectList(new EntityWrapper<WaitPakin>() |
| | | .in("item_num", 1,2) |
| | | .ge("be_batch",3) |
| | | .orderBy("zpallet ASC")); |
| | | if (waitPakins.isEmpty()) { |
| | | return; |
| | | } |
| | | String zpallet=""; |
| | | for (WaitPakin waitPakin : waitPakins) { |
| | | if(Cools.isEmpty(zpallet)){ |
| | | zpallet=waitPakin.getZpallet(); |
| | | }else if(zpallet.equals(waitPakin.getZpallet())){ |
| | | continue; |
| | | } |
| | | if (Cools.isEmpty(waitPakin.getMemo())) { |
| | | log.error("入库通知档托盘码={},源站点[memo]为空",waitPakin.getZpallet()); |
| | | continue; |
| | | } |
| | | log.info("WMS自动下发给AGV下发补空托盘任务={}",waitPakin); |
| | | R r = mobileController.FillEmptyPallets(waitPakin.getMemo(), waitPakin.getItemNum()); |
| | | if (r.get("code").equals(200)) { |
| | | waitPakin.setItemNum(waitPakin.getItemNum().equals("1")?"10":"20"); |
| | | waitPakinService.update(waitPakin,new EntityWrapper<WaitPakin>().eq("supp_code",waitPakin.getSuppCode())); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 出库时绑定agv站点 |
| | | * 自动派发出库任务给agv搬运 |
| | | */ |
| | | @Scheduled(cron = "0/3 * * * * ? ") |
| | | private synchronized void autoOut(){ |
| | | List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("wrk_sts", 30)); |
| | | if (wrkMasts.isEmpty()) { |
| | | return; |
| | | } |
| | | for (WrkMast wrkMast : wrkMasts) { |
| | | BasDevp basDevp = basDevpService.selectOne(new EntityWrapper<BasDevp>() |
| | | .eq("wrk_no", wrkMast.getWrkNo()) |
| | | .eq("dev_no", wrkMast.getStaNo()) |
| | | .eq("autoing", "Y") |
| | | .eq("loading","Y")); |
| | | if(Cools.isEmpty(basDevp)){ |
| | | continue; |
| | | } |
| | | if (Cools.isEmpty(wrkMast.getMemo())) { |
| | | log.error("入库通知档托盘码={},源站点[memo]为空",wrkMast.getBarcode()); |
| | | continue; |
| | | } |
| | | log.info("WMS自动下发给AGV下发出库任务={}",wrkMast); |
| | | log.info("WMS开始自动绑定agv站点={},任务号为={}",wrkMast.getStaNo(),wrkMast.getWrkNo()); |
| | | |
| | | R bind = mobileController.siteBindAndUnbind(wrkMast.getStaNo() + "",wrkMast.getBarcode(), "BIND"); |
| | | if (bind.get("code").equals(200)) { |
| | | }else { |
| | | log.info("WMS绑定agv站点={},任务号为={}------------失败",wrkMast.getStaNo(),wrkMast.getWrkNo()); |
| | | } |
| | | //生成agv工作号 |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| | | String format = sdf.format(new Date()); |
| | | String s = format+"-" + wrkMast.getWrkNo(); |
| | | log.info("WMS完成绑定agv站点={},AGV任务号为={}",wrkMast.getStaNo(),s); |
| | | R r = mobileController.SITEZONEAGVMove(wrkMast.getStaNo()+"", wrkMast.getMemo(),s); |
| | | if (r.get("code").equals(200)) { |
| | | wrkMast.setPdcType(s); |
| | | wrkMast.setWrkSts(31L); //从30等待给AGV下发出库任务-----》31AGV出库任务下发成功 |
| | | wrkMast.setModiTime(new Date()); |
| | | wrkMastService.updateById(wrkMast); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 入库任务自动解绑agv站点 |
| | | */ |
| | | @Scheduled(cron = "0/3 * * * * ? ") |
| | | private synchronized void UnbindTheSite(){ |
| | | List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() |
| | | .in("io_type",1,53) |
| | | .ge("wrk_sts", 2) |
| | | .isNull("ctn_kind")); |
| | | if (wrkMasts.isEmpty()) { |
| | | return; |
| | | } |
| | | for (WrkMast wrkMast : wrkMasts) { |
| | | String staNo=""; |
| | | if(wrkMast.getSourceStaNo()==102){ |
| | | staNo="101"; |
| | | }else if(wrkMast.getSourceStaNo()==104){ |
| | | staNo="103"; |
| | | }else if(wrkMast.getSourceStaNo()==106){ |
| | | staNo="105"; |
| | | } |
| | | log.info("WMS入库解绑AGV站点={},托盘码为={}",staNo,wrkMast.getBarcode()); |
| | | R r = mobileController.siteBindAndUnbind(staNo,wrkMast.getBarcode(),"UNBIND"); |
| | | if (r.get("code").equals(200)) { |
| | | wrkMast.setCtnKind(1);//任务解绑标记 |
| | | wrkMastService.updateById(wrkMast); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | package com.zy.asrs.task; |
| | | |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.zy.asrs.entity.WrkMast; |
| | | import com.zy.asrs.service.WrkMastService; |
| | | import com.zy.asrs.task.core.ReturnT; |
| | |
| | | } |
| | | } |
| | | |
| | | //拣料任务处理 |
| | | @Scheduled(cron = "0/3 * * * * ? ") |
| | | private void jl(){ |
| | | List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() |
| | | .eq("io_type",103) |
| | | .eq("wrk_sts",14L) |
| | | .isNotNull("memo")); |
| | | if (wrkMasts.isEmpty()) { |
| | | return; |
| | | } |
| | | for (WrkMast wrkMast : wrkMasts) { |
| | | ReturnT<String> returnT = workMastHandler.start(wrkMast); |
| | | if (!returnT.isSuccess()) { |
| | | wrkMast.setUpdMk("X"); |
| | | wrkMast.setErrorMemo(returnT.getMsg()); |
| | | wrkMast.setErrorTime(new Date()); |
| | | if (!wrkMastService.updateById(wrkMast)) { |
| | | log.error("工作档[workNo={}]标记待处理失败", wrkMast.getWrkNo()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | default: |
| | | break; |
| | | } |
| | | // 修改工作主档状态 |
| | | wrkMast.setWrkSts(15L); |
| | | if(Cools.isEmpty(wrkMast.getMemo())){ |
| | | // 修改工作主档状态 |
| | | wrkMast.setWrkSts(15L); |
| | | }else { |
| | | wrkMast.setWrkSts(30L); |
| | | } |
| | | |
| | | wrkMast.setModiTime(now); |
| | | if (!wrkMastService.updateById(wrkMast)) { |
| | | // exceptionHandle("更新出库完成状态失败;[workNo={0}]", wrkMast.getWrkNo()); |
| | |
| | | String USER_10002 = "10002-账号已被禁用"; |
| | | String USER_10003 = "10003-密码错误"; |
| | | |
| | | String SYSTEM_20001 = "20001-许可证已失效"; |
| | | |
| | | String EXIST_500 = "500-工作档/库存条码数据已存在"; |
| | | String PICK_600 = "600-拣料任务"; |
| | | String NO_COMB_700 = "700-请先组托"; |
| | |
| | | String deToken = Cools.deTokn(token, superPwd); |
| | | if (deToken!=null){ |
| | | long timestamp = Long.parseLong(deToken.substring(0, 13)); |
| | | // 1天后过期 |
| | | if (System.currentTimeMillis() - timestamp > 86400000){ |
| | | // 半小时后过期 |
| | | if (System.currentTimeMillis() - timestamp > 1000 * 60 * 30){ |
| | | Http.response(response, BaseRes.DENIED); |
| | | return false; |
| | | } |
| | |
| | | private boolean lack = false; |
| | | |
| | | //目标站点 |
| | | private List<Integer> staNos; |
| | | private List<String> staNos; |
| | | |
| | | private Integer staNo; |
| | | private String staNo; |
| | | |
| | | |
| | | public LocDto() { |
| | |
| | | return this.matnr + "(" + this.maktx + ")"; |
| | | } |
| | | |
| | | public void setStaNos(List<Integer> staNos) { |
| | | public void setStaNos(List<String> staNos) { |
| | | this.staNos = staNos; |
| | | if (!Cools.isEmpty(staNos)) { |
| | | this.staNo = staNos.get(0); |
| | |
| | | |
| | | private String locNo; |
| | | |
| | | private Integer staNo; |
| | | private String staNo; |
| | | |
| | | private List<LocDto> locDtos; |
| | | |
| | |
| | | locDtos = new ArrayList<>(); |
| | | } |
| | | |
| | | public TaskDto(String locNo, Integer staNo) { |
| | | public TaskDto(String locNo, String staNo) { |
| | | this.locNo = locNo; |
| | | this.staNo = staNo; |
| | | } |
| | | |
| | | public TaskDto(String locNo, Integer staNo, LocDto locDto) { |
| | | public TaskDto(String locNo, String staNo, LocDto locDto) { |
| | | this.locNo = locNo; |
| | | this.staNo = staNo; |
| | | this.locDtos.add(locDto); |
| | | } |
| | | |
| | | public TaskDto(String locNo, Integer staNo, List<LocDto> locDtos) { |
| | | public TaskDto(String locNo, String staNo, List<LocDto> locDtos) { |
| | | this.locNo = locNo; |
| | | this.staNo = staNo; |
| | | this.locDtos = locDtos; |
| | |
| | | } |
| | | } |
| | | |
| | | // 如果没有相近物料,则按规则轮询货架 |
| | | if (null == locMast) { |
| | | if(crnNo>1) { |
| | | curRow = curRow -2; |
| | | } |
| | | Shelves shelves = new Shelves(rowCount, crn_qty); |
| | | int divides = (int) Arith.divides(1, curRow - 1, 4); |
| | | curRow = (int) Arith.remainder(curRow, 4); |
| | | if (curRow == 0) { |
| | | curRow = 4; |
| | | } |
| | | for (int i = 0; i < shelves.group; i ++) { |
| | | curRow = shelves.start(curRow); |
| | | if (curRow < 0) { |
| | | throw new CoolException("检索库位失败,请联系管理员"); |
| | | } |
| | | if (basCrnpService.checkSiteError(crnNo, true)) { |
| | | curRow = curRow + divides*4; |
| | | break; |
| | | } |
| | | } |
| | | if(crnNo>1) { |
| | | curRow = curRow +2; |
| | | } |
| | | } |
| | | |
| | | if (crnNo == 0) { |
| | | throw new CoolException("没有可用的堆垛机"); |
| | | } |
| | | // // 如果没有相近物料,则按规则轮询货架 |
| | | // if (null == locMast) { |
| | | // if(crnNo>1) { |
| | | // curRow = curRow -2; |
| | | // } |
| | | // Shelves shelves = new Shelves(rowCount, crn_qty); |
| | | // int divides = (int) Arith.divides(1, curRow - 1, 4); |
| | | // curRow = (int) Arith.remainder(curRow, 4); |
| | | // if (curRow == 0) { |
| | | // curRow = 4; |
| | | // } |
| | | // for (int i = 0; i < shelves.group; i ++) { |
| | | // curRow = shelves.start(curRow); |
| | | // if (curRow < 0) { |
| | | // throw new CoolException("检索库位失败,请联系管理员"); |
| | | // } |
| | | // if (basCrnpService.checkSiteError(crnNo, true)) { |
| | | // curRow = curRow + divides*4; |
| | | // break; |
| | | // } |
| | | // } |
| | | // if(crnNo>1) { |
| | | // curRow = curRow +2; |
| | | // } |
| | | // } |
| | | // |
| | | // if (crnNo == 0) { |
| | | // throw new CoolException("没有可用的堆垛机"); |
| | | // } |
| | | // 获取目标站 |
| | | Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>() |
| | | .eq("type_no", staDescId) |
| | |
| | | if (!staNo.getAutoing().equals("Y")) { |
| | | throw new CoolException("目标站"+staDesc.getCrnStn()+"不可用"); |
| | | } |
| | | |
| | | if(curRow==1){ |
| | | curRow=2; |
| | | }else if(curRow==2){ |
| | | curRow=1; |
| | | }else if(curRow==3){ |
| | | curRow=6; |
| | | }else if(curRow==6){ |
| | | curRow=3; |
| | | }else if(curRow==7){ |
| | | curRow=10; |
| | | }else if(curRow==10){ |
| | | curRow=7; |
| | | } |
| | | // 更新库位排号 |
| | | rowLastno.setCurrentRow(curRow); |
| | | rowLastnoService.updateById(rowLastno); |
| | |
| | | if (times < rowCount) { |
| | | times = times + 1; |
| | | return getLocNo(1, staDescId, sourceStaNo, matNos, locTypeDto, times); |
| | | }else if (times == rowCount) { |
| | | |
| | | LocMast locMast1 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("crn_no", crnNo) |
| | | .eq("loc_sts", "O") |
| | | .orderBy("lev1")); |
| | | if(Cools.isEmpty(locMast1)){ |
| | | throw new CoolException("堆垛机="+crnNo+"没有空库位"); |
| | | } |
| | | if(!locMastService.checkEmptyCount(locMast1)){ |
| | | throw new CoolException("堆垛机="+crnNo+"没有空库位"); |
| | | } |
| | | } |
| | | |
| | | // 轻货物找轻库位为空时,可以去找重库位仓 |
| | |
| | | |
| | | import okhttp3.*; |
| | | |
| | | import javax.net.ssl.*; |
| | | import java.io.IOException; |
| | | import java.security.SecureRandom; |
| | | import java.security.cert.X509Certificate; |
| | | import java.util.Map; |
| | | import java.util.Optional; |
| | | import java.util.concurrent.TimeUnit; |
| | |
| | | */ |
| | | public class HttpHandler { |
| | | |
| | | private static final Integer DEFAULT_TIMEOUT_SECONDS = 5; |
| | | private static final Integer DEFAULT_TIMEOUT_SECONDS = 10; |
| | | private static final MediaType MEDIA_TYPE = MediaType.parse("application/json;charset=utf-8"); |
| | | |
| | | private String uri; |
| | |
| | | * POST请求执行 |
| | | * @return the HttpHandler response |
| | | */ |
| | | public String doPostCloseSSL() throws IOException { |
| | | Request request; |
| | | Request.Builder headerBuilder = new Request.Builder(); |
| | | if (headers != null && headers.size()>0){ |
| | | for (Map.Entry<String, Object> entry : headers.entrySet()){ |
| | | headerBuilder.addHeader(entry.getKey(), String.valueOf(entry.getValue())); |
| | | } |
| | | } |
| | | if (json == null || "".equals(json)){ |
| | | FormBody.Builder builder = new FormBody.Builder(); |
| | | for (Map.Entry<String, Object> entry : params.entrySet()){ |
| | | builder.add(entry.getKey(), String.valueOf(entry.getValue())); |
| | | } |
| | | FormBody body = builder.build(); |
| | | request = headerBuilder |
| | | .url((https?"https://":"http://")+uri+path) |
| | | .post(body) |
| | | .build(); |
| | | } else { |
| | | RequestBody body = RequestBody.create(MEDIA_TYPE, json); |
| | | Request.Builder builder = headerBuilder.url((https?"https://":"http://")+uri+path); |
| | | builder.header("Content-Type", "application/json;charset=UTF-8"); |
| | | request = builder.post(body).build(); |
| | | |
| | | } |
| | | Call call = getClientCloseSSL(timeout, timeUnit).newCall(request); |
| | | Response response = call.execute(); |
| | | return response.body().string(); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * GET请求执行 |
| | | * @return the HttpHandler response |
| | | */ |
| | | public String doGetCloseSSL() throws IOException { |
| | | String url = paramsToUrl(uri, path, params, https); |
| | | Request.Builder headerBuilder = new Request.Builder(); |
| | | if (headers != null && headers.size()>0){ |
| | | for (Map.Entry<String, Object> entry : headers.entrySet()){ |
| | | headerBuilder.addHeader(entry.getKey(), String.valueOf(entry.getValue())); |
| | | } |
| | | } |
| | | Request request = headerBuilder.url(url).build(); |
| | | Response response = getClientCloseSSL(timeout, timeUnit).newCall(request).execute(); |
| | | return response.isSuccessful() ? response.body().string() : null; |
| | | } |
| | | |
| | | /** |
| | | * POST请求执行 |
| | | * @return the HttpHandler response |
| | | */ |
| | | public String doPost() throws IOException { |
| | | Request request; |
| | | Request.Builder headerBuilder = new Request.Builder(); |
| | |
| | | request = builder.post(body).build(); |
| | | |
| | | } |
| | | Call call = getClient(timeout, timeUnit).newCall(request); |
| | | Call call = getClientCloseSSL(timeout, timeUnit).newCall(request); |
| | | Response response = call.execute(); |
| | | return response.body().string(); |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 获取 okHttpClient |
| | | * @return the HttpHandler instance |
| | | */ |
| | | private OkHttpClient getClientCloseSSL(Integer timeout, TimeUnit timeUnit){ |
| | | return new OkHttpClient |
| | | .Builder() |
| | | .sslSocketFactory(getSSLSocketFactory()) |
| | | .hostnameVerifier(getHostnameVerifier()) |
| | | .connectTimeout(timeout, timeUnit) |
| | | .readTimeout(timeout, timeUnit) |
| | | .build(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * description 忽略https证书验证 |
| | | * |
| | | * @author yanzy |
| | | * @version 1.0 |
| | | * @date 2021/9/8 14:42 |
| | | */ |
| | | private static TrustManager[] getTrustManager() { |
| | | TrustManager[] trustAllCerts = new TrustManager[]{ |
| | | new X509TrustManager() { |
| | | @Override |
| | | public void checkClientTrusted(X509Certificate[] chain, String authType) { |
| | | } |
| | | |
| | | @Override |
| | | public void checkServerTrusted(X509Certificate[] chain, String authType) { |
| | | } |
| | | |
| | | @Override |
| | | public X509Certificate[] getAcceptedIssuers() { |
| | | return new X509Certificate[]{}; |
| | | } |
| | | } |
| | | }; |
| | | return trustAllCerts; |
| | | } |
| | | /** |
| | | * description 忽略https证书验证 |
| | | * |
| | | * @author yanzy |
| | | * @version 1.0 |
| | | * @date 2021/9/8 14:42 |
| | | */ |
| | | public static HostnameVerifier getHostnameVerifier() { |
| | | HostnameVerifier hostnameVerifier = new HostnameVerifier() { |
| | | @Override |
| | | public boolean verify(String s, SSLSession sslSession) { |
| | | return true; |
| | | } |
| | | }; |
| | | return hostnameVerifier; |
| | | } |
| | | |
| | | /** |
| | | * description 忽略https证书验证 |
| | | *`在这里插入代码片` |
| | | * @author yanzy |
| | | * @version 1.0 |
| | | * @date 2021/9/8 14:42 |
| | | */ |
| | | public static SSLSocketFactory getSSLSocketFactory() { |
| | | try { |
| | | SSLContext sslContext = SSLContext.getInstance("SSL"); |
| | | sslContext.init(null, getTrustManager(), new SecureRandom()); |
| | | return sslContext.getSocketFactory(); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | /** |
| | | * Http协议报文建造者 |
| | | */ |
| | | public static class Builder { |
| | |
| | | import com.zy.common.utils.RandomValidateCodeUtil; |
| | | import com.zy.system.entity.*; |
| | | import com.zy.system.service.*; |
| | | import com.zy.system.timer.LicenseTimer; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | private PermissionService permissionService; |
| | | @Autowired |
| | | private RolePermissionService rolePermissionService; |
| | | |
| | | @Autowired |
| | | private LicenseTimer licenseTimer; |
| | | @RequestMapping("/login.action") |
| | | @ManagerAuth(value = ManagerAuth.Auth.NONE, memo = "登录") |
| | | public R loginAction(String username, String password){ |
| | | //验证许可证是否有效 |
| | | if (!licenseTimer.getSystemSupport()){ |
| | | return R.parse(CodeRes.SYSTEM_20001); |
| | | } |
| | | if (username.equals("super") && password.equals(Cools.md5(superPwd))) { |
| | | Map<String, Object> res = new HashMap<>(); |
| | | res.put("username", username); |
| New file |
| | |
| | | package com.zy.system.controller; |
| | | |
| | | import com.core.common.Cools; |
| | | import com.core.common.R; |
| | | import com.zy.system.entity.license.*; |
| | | 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; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | | * |
| | | * 用于生成证书文件,不能放在给客户部署的代码里 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/license") |
| | | public class LicenseCreatorController { |
| | | |
| | | @Value("${license.licensePath}") |
| | | private String licensePath; |
| | | @Autowired |
| | | private LicenseCheckListener licenseCheckListener; |
| | | @Autowired |
| | | private LicenseTimer licenseTimer; |
| | | /** |
| | | * 获取服务器硬件信息 |
| | | * @param osName 操作系统类型,如果为空则自动判断 |
| | | */ |
| | | @RequestMapping(value = "/getServerInfos",produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}) |
| | | public LicenseCheck getServerInfos(@RequestParam(value = "osName",required = false) String osName) { |
| | | //操作系统类型 |
| | | if(Cools.isEmpty(osName)){ |
| | | osName = System.getProperty("os.name"); |
| | | } |
| | | osName = osName.toLowerCase(); |
| | | |
| | | AbstractServerInfos abstractServerInfos = null; |
| | | |
| | | //根据不同操作系统类型选择不同的数据获取方法 |
| | | if (osName.startsWith("windows")) { |
| | | abstractServerInfos = new WindowsServerInfos(); |
| | | } else if (osName.startsWith("linux")) { |
| | | abstractServerInfos = new LinuxServerInfos(); |
| | | }else{//其他服务器类型 |
| | | abstractServerInfos = new WindowsServerInfos(); |
| | | } |
| | | |
| | | return abstractServerInfos.getServerInfos(); |
| | | } |
| | | |
| | | /** |
| | | * 获取许可证有效期天数 |
| | | */ |
| | | @RequestMapping(value = "/getLicenseDays") |
| | | public R getLicenseDays() { |
| | | return R.ok(licenseTimer.getLicenseDays()); |
| | | } |
| | | |
| | | @RequestMapping(value = "/updateLicense") |
| | | public R updateLicense(@RequestParam("file") MultipartFile[] files){ |
| | | MultipartFile file = files[0]; |
| | | |
| | | String licensePathFileName = this.getClass().getClassLoader().getResource(licensePath).getPath(); |
| | | File licensePathFile = new File(licensePathFileName); |
| | | //服务器端保存的文件对象 |
| | | File serverFile = new File(licensePathFile.getPath()); |
| | | if (serverFile.exists()) { |
| | | try { |
| | | serverFile.delete();//存在文件,删除 |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | try { |
| | | //创建文件 |
| | | serverFile.createNewFile(); |
| | | //将上传的文件写入到服务器端文件内 |
| | | file.transferTo(serverFile); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | //重新加载许可证 |
| | | boolean loadedLicense = licenseCheckListener.loadLicense(); |
| | | if (loadedLicense) { |
| | | return R.ok(); |
| | | } |
| | | return R.error("许可证更新失败"); |
| | | } |
| | | |
| | | @RequestMapping(value = "/activate") |
| | | public R activate() { |
| | | licenseTimer.timer(); |
| | | return R.ok(); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.system.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotations.TableField; |
| | | import com.baomidou.mybatisplus.annotations.TableId; |
| | | import com.baomidou.mybatisplus.annotations.TableName; |
| | | import com.baomidou.mybatisplus.enums.IdType; |
| | | import com.core.common.Cools; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.io.Serializable; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | |
| | | @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); |
| | | } |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import org.apache.logging.log4j.LogManager; |
| | | import org.apache.logging.log4j.Logger; |
| | | |
| | | import java.net.InetAddress; |
| | | import java.net.NetworkInterface; |
| | | import java.net.SocketException; |
| | | import java.util.ArrayList; |
| | | import java.util.Enumeration; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 用于获取客户服务器的基本信息,如:IP、Mac地址、CPU序列号、主板序列号等 |
| | | */ |
| | | public abstract class AbstractServerInfos { |
| | | private static Logger logger = LogManager.getLogger(AbstractServerInfos.class); |
| | | |
| | | /** |
| | | * 组装需要额外校验的License参数 |
| | | */ |
| | | public LicenseCheck getServerInfos(){ |
| | | LicenseCheck result = new LicenseCheck(); |
| | | |
| | | try { |
| | | // result.setIpAddress(this.getIpAddress()); |
| | | result.setMacAddress(this.getMacAddress()); |
| | | result.setCpuSerial(this.getCPUSerial()); |
| | | result.setMainBoardSerial(this.getMainBoardSerial()); |
| | | }catch (Exception e){ |
| | | logger.error("获取服务器硬件信息失败",e); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 获取IP地址 |
| | | */ |
| | | protected abstract List<String> getIpAddress() throws Exception; |
| | | |
| | | /** |
| | | * 获取Mac地址 |
| | | */ |
| | | protected abstract List<String> getMacAddress() throws Exception; |
| | | |
| | | /** |
| | | * 获取CPU序列号 |
| | | */ |
| | | protected abstract String getCPUSerial() throws Exception; |
| | | |
| | | /** |
| | | * 获取主板序列号 |
| | | */ |
| | | protected abstract String getMainBoardSerial() throws Exception; |
| | | |
| | | /** |
| | | * 获取当前服务器所有符合条件的InetAddress |
| | | */ |
| | | protected List<InetAddress> getLocalAllInetAddress() throws Exception { |
| | | List<InetAddress> result = new ArrayList<>(4); |
| | | |
| | | // 遍历所有的网络接口 |
| | | for (Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); networkInterfaces.hasMoreElements(); ) { |
| | | NetworkInterface iface = (NetworkInterface) networkInterfaces.nextElement(); |
| | | // 在所有的接口下再遍历IP |
| | | for (Enumeration inetAddresses = iface.getInetAddresses(); inetAddresses.hasMoreElements(); ) { |
| | | InetAddress inetAddr = (InetAddress) inetAddresses.nextElement(); |
| | | |
| | | //排除LoopbackAddress、SiteLocalAddress、LinkLocalAddress、MulticastAddress类型的IP地址 |
| | | if(!inetAddr.isLoopbackAddress() /*&& !inetAddr.isSiteLocalAddress()*/ |
| | | && !inetAddr.isLinkLocalAddress() && !inetAddr.isMulticastAddress()){ |
| | | result.add(inetAddr); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 获取某个网络接口的Mac地址 |
| | | */ |
| | | protected String getMacByInetAddress(InetAddress inetAddr){ |
| | | try { |
| | | byte[] mac = NetworkInterface.getByInetAddress(inetAddr).getHardwareAddress(); |
| | | StringBuffer stringBuffer = new StringBuffer(); |
| | | |
| | | for(int i=0;i<mac.length;i++){ |
| | | if(i != 0) { |
| | | stringBuffer.append("-"); |
| | | } |
| | | |
| | | //将十六进制byte转化为字符串 |
| | | String temp = Integer.toHexString(mac[i] & 0xff); |
| | | if(temp.length() == 1){ |
| | | stringBuffer.append("0" + temp); |
| | | }else{ |
| | | stringBuffer.append(temp); |
| | | } |
| | | } |
| | | |
| | | return stringBuffer.toString().toUpperCase(); |
| | | } catch (SocketException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import de.schlichtherle.license.AbstractKeyStoreParam; |
| | | |
| | | import java.io.FileNotFoundException; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | |
| | | /** |
| | | * 自定义KeyStoreParam,用于将公私钥存储文件存放到其他磁盘位置而不是项目中 |
| | | */ |
| | | public class CustomKeyStoreParam extends AbstractKeyStoreParam { |
| | | |
| | | /** |
| | | * 公钥/私钥在磁盘上的存储路径 |
| | | */ |
| | | private String storePath; |
| | | private String alias; |
| | | private String storePwd; |
| | | private String keyPwd; |
| | | |
| | | public CustomKeyStoreParam(Class clazz, String resource, String alias, String storePwd, String keyPwd) { |
| | | super(clazz, resource); |
| | | this.storePath = resource; |
| | | this.alias = alias; |
| | | this.storePwd = storePwd; |
| | | this.keyPwd = keyPwd; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public String getAlias() { |
| | | return alias; |
| | | } |
| | | |
| | | @Override |
| | | public String getStorePwd() { |
| | | return storePwd; |
| | | } |
| | | |
| | | @Override |
| | | public String getKeyPwd() { |
| | | return keyPwd; |
| | | } |
| | | |
| | | /** |
| | | * 复写de.schlichtherle.license.AbstractKeyStoreParam的getStream()方法<br/> |
| | | * 用于将公私钥存储文件存放到其他磁盘位置而不是项目中 |
| | | */ |
| | | @Override |
| | | public InputStream getStream() throws IOException { |
| | | final InputStream in = this.getClass().getClassLoader().getResourceAsStream(storePath); |
| | | if (null == in) { |
| | | throw new FileNotFoundException(storePath); |
| | | } |
| | | |
| | | return in; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import com.core.common.Cools; |
| | | import de.schlichtherle.license.*; |
| | | import de.schlichtherle.xml.GenericCertificate; |
| | | import org.apache.logging.log4j.LogManager; |
| | | import org.apache.logging.log4j.Logger; |
| | | |
| | | import java.beans.XMLDecoder; |
| | | import java.io.BufferedInputStream; |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 自定义LicenseManager,用于增加额外的服务器硬件信息校验 |
| | | */ |
| | | public class CustomLicenseManager extends LicenseManager{ |
| | | private static Logger logger = LogManager.getLogger(CustomLicenseManager.class); |
| | | |
| | | //XML编码 |
| | | private static final String XML_CHARSET = "UTF-8"; |
| | | //默认BUFSIZE |
| | | private static final int DEFAULT_BUFSIZE = 8 * 1024; |
| | | |
| | | public CustomLicenseManager() { |
| | | |
| | | } |
| | | |
| | | public CustomLicenseManager(LicenseParam param) { |
| | | super(param); |
| | | } |
| | | |
| | | /** |
| | | * 复写create方法 |
| | | */ |
| | | @Override |
| | | protected synchronized byte[] create( |
| | | LicenseContent content, |
| | | LicenseNotary notary) |
| | | throws Exception { |
| | | initialize(content); |
| | | this.validateCreate(content); |
| | | final GenericCertificate certificate = notary.sign(content); |
| | | return getPrivacyGuard().cert2key(certificate); |
| | | } |
| | | |
| | | /** |
| | | * 复写install方法,其中validate方法调用本类中的validate方法,校验IP地址、Mac地址等其他信息 |
| | | */ |
| | | @Override |
| | | protected synchronized LicenseContent install( |
| | | final byte[] key, |
| | | final LicenseNotary notary) |
| | | throws Exception { |
| | | final GenericCertificate certificate = getPrivacyGuard().key2cert(key); |
| | | |
| | | notary.verify(certificate); |
| | | final LicenseContent content = (LicenseContent)this.load(certificate.getEncoded()); |
| | | this.validate(content); |
| | | setLicenseKey(key); |
| | | setCertificate(certificate); |
| | | |
| | | return content; |
| | | } |
| | | |
| | | /** |
| | | * 复写verify方法,调用本类中的validate方法,校验IP地址、Mac地址等其他信息 |
| | | */ |
| | | @Override |
| | | protected synchronized LicenseContent verify(final LicenseNotary notary) |
| | | throws Exception { |
| | | GenericCertificate certificate = getCertificate(); |
| | | |
| | | // Load license key from preferences, |
| | | final byte[] key = getLicenseKey(); |
| | | if (null == key){ |
| | | throw new NoLicenseInstalledException(getLicenseParam().getSubject()); |
| | | } |
| | | |
| | | certificate = getPrivacyGuard().key2cert(key); |
| | | notary.verify(certificate); |
| | | final LicenseContent content = (LicenseContent)this.load(certificate.getEncoded()); |
| | | this.validate(content); |
| | | setCertificate(certificate); |
| | | |
| | | return content; |
| | | } |
| | | |
| | | /** |
| | | * 校验生成证书的参数信息 |
| | | */ |
| | | protected synchronized void validateCreate(final LicenseContent content) |
| | | throws LicenseContentException { |
| | | final LicenseParam param = getLicenseParam(); |
| | | |
| | | final Date now = new Date(); |
| | | final Date notBefore = content.getNotBefore(); |
| | | final Date notAfter = content.getNotAfter(); |
| | | if (null != notAfter && now.after(notAfter)){ |
| | | throw new LicenseContentException("证书失效时间不能早于当前时间"); |
| | | } |
| | | if (null != notBefore && null != notAfter && notAfter.before(notBefore)){ |
| | | throw new LicenseContentException("证书生效时间不能晚于证书失效时间"); |
| | | } |
| | | final String consumerType = content.getConsumerType(); |
| | | if (null == consumerType){ |
| | | throw new LicenseContentException("用户类型不能为空"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 复写validate方法,增加IP地址、Mac地址等其他信息校验 |
| | | */ |
| | | @Override |
| | | protected synchronized void validate(final LicenseContent content) |
| | | throws LicenseContentException { |
| | | //1. 首先调用父类的validate方法 |
| | | super.validate(content); |
| | | |
| | | //2. 然后校验自定义的License参数 |
| | | //License中可被允许的参数信息 |
| | | LicenseCheck expectedCheckModel = (LicenseCheck) content.getExtra(); |
| | | //当前服务器真实的参数信息 |
| | | LicenseCheck serverCheckModel = getServerInfos(); |
| | | |
| | | if(expectedCheckModel != null && serverCheckModel != null){ |
| | | //校验IP地址 |
| | | if(!checkIpAddress(expectedCheckModel.getIpAddress(),serverCheckModel.getIpAddress())){ |
| | | throw new LicenseContentException("当前服务器的IP没在授权范围内"); |
| | | } |
| | | |
| | | //校验Mac地址 |
| | | if(!checkIpAddress(expectedCheckModel.getMacAddress(),serverCheckModel.getMacAddress())){ |
| | | throw new LicenseContentException("当前服务器的Mac地址没在授权范围内"); |
| | | } |
| | | |
| | | //校验主板序列号 |
| | | if(!checkSerial(expectedCheckModel.getMainBoardSerial(),serverCheckModel.getMainBoardSerial())){ |
| | | throw new LicenseContentException("当前服务器的主板序列号没在授权范围内"); |
| | | } |
| | | |
| | | //校验CPU序列号 |
| | | if(!checkSerial(expectedCheckModel.getCpuSerial(),serverCheckModel.getCpuSerial())){ |
| | | throw new LicenseContentException("当前服务器的CPU序列号没在授权范围内"); |
| | | } |
| | | }else{ |
| | | throw new LicenseContentException("不能获取服务器硬件信息"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 重写XMLDecoder解析XML |
| | | */ |
| | | private Object load(String encoded){ |
| | | BufferedInputStream inputStream = null; |
| | | XMLDecoder decoder = null; |
| | | try { |
| | | inputStream = new BufferedInputStream(new ByteArrayInputStream(encoded.getBytes(XML_CHARSET))); |
| | | |
| | | decoder = new XMLDecoder(new BufferedInputStream(inputStream, DEFAULT_BUFSIZE),null,null); |
| | | |
| | | return decoder.readObject(); |
| | | } catch (UnsupportedEncodingException e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | try { |
| | | if(decoder != null){ |
| | | decoder.close(); |
| | | } |
| | | if(inputStream != null){ |
| | | inputStream.close(); |
| | | } |
| | | } catch (Exception e) { |
| | | logger.error("XMLDecoder解析XML失败",e); |
| | | } |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 获取当前服务器需要额外校验的License参数 |
| | | */ |
| | | private LicenseCheck getServerInfos(){ |
| | | //操作系统类型 |
| | | String osName = System.getProperty("os.name").toLowerCase(); |
| | | AbstractServerInfos abstractServerInfos = null; |
| | | |
| | | //根据不同操作系统类型选择不同的数据获取方法 |
| | | if (osName.startsWith("windows")) { |
| | | abstractServerInfos = new WindowsServerInfos(); |
| | | } else if (osName.startsWith("linux")) { |
| | | abstractServerInfos = new LinuxServerInfos(); |
| | | }else{//其他服务器类型 |
| | | abstractServerInfos = new WindowsServerInfos(); |
| | | } |
| | | |
| | | return abstractServerInfos.getServerInfos(); |
| | | } |
| | | |
| | | /** |
| | | * 校验当前服务器的IP/Mac地址是否在可被允许的IP范围内<br/> |
| | | * 如果存在IP在可被允许的IP/Mac地址范围内,则返回true |
| | | */ |
| | | private boolean checkIpAddress(List<String> expectedList,List<String> serverList){ |
| | | if(expectedList != null && expectedList.size() > 0){ |
| | | if(serverList != null && serverList.size() > 0){ |
| | | for(String expected : expectedList){ |
| | | if(serverList.contains(expected.trim())){ |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | }else { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 校验当前服务器硬件(主板、CPU等)序列号是否在可允许范围内 |
| | | */ |
| | | private boolean checkSerial(String expectedSerial,String serverSerial){ |
| | | if(!Cools.isEmpty(expectedSerial)){ |
| | | if(!Cools.isEmpty(serverSerial)){ |
| | | if(expectedSerial.equals(serverSerial)){ |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | }else{ |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 自定义需要校验的License参数 |
| | | */ |
| | | @Data |
| | | public class LicenseCheck implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 8600137500316662317L; |
| | | /** |
| | | * 可被允许的IP地址 |
| | | */ |
| | | private List<String> ipAddress; |
| | | |
| | | /** |
| | | * 可被允许的MAC地址 |
| | | */ |
| | | private List<String> macAddress; |
| | | |
| | | /** |
| | | * 可被允许的CPU序列号 |
| | | */ |
| | | private String cpuSerial; |
| | | |
| | | /** |
| | | * 可被允许的主板序列号 |
| | | */ |
| | | private String mainBoardSerial; |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "LicenseCheckModel{" + |
| | | "ipAddress=" + ipAddress + |
| | | ", macAddress=" + macAddress + |
| | | ", cpuSerial='" + cpuSerial + '\'' + |
| | | ", mainBoardSerial='" + mainBoardSerial + '\'' + |
| | | '}'; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | 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; |
| | | import org.springframework.context.event.ContextRefreshedEvent; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 在项目启动时安装证书 |
| | | */ |
| | | @Component |
| | | public class LicenseCheckListener implements ApplicationListener<ContextRefreshedEvent> { |
| | | private static Logger logger = LogManager.getLogger(LicenseCheckListener.class); |
| | | |
| | | /** |
| | | * 证书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 LicenseTimer licenseTimer; |
| | | @Autowired |
| | | private LicenseInfosService licenseInfosService; |
| | | |
| | | @Override |
| | | public void onApplicationEvent(ContextRefreshedEvent event) { |
| | | //root application context 没有parent |
| | | ApplicationContext context = event.getApplicationContext().getParent(); |
| | | if(context == null){ |
| | | loadLicense(); |
| | | } |
| | | } |
| | | |
| | | //加载证书 |
| | | public boolean loadLicense() { |
| | | if(!Cools.isEmpty(licensePath)){ |
| | | logger.info("++++++++ 开始加载许可证 ++++++++"); |
| | | |
| | | try { |
| | | licenseTimer.getRemoteLicense(); |
| | | } catch (Exception e) { |
| | | } |
| | | |
| | | try { |
| | | LicenseVerifyParam param = new LicenseVerifyParam(); |
| | | param.setSubject(subject); |
| | | param.setPublicAlias(publicAlias); |
| | | param.setStorePass(storePass); |
| | | 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, 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; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import de.schlichtherle.license.*; |
| | | import org.apache.logging.log4j.LogManager; |
| | | import org.apache.logging.log4j.Logger; |
| | | |
| | | import javax.security.auth.x500.X500Principal; |
| | | import java.io.File; |
| | | import java.text.MessageFormat; |
| | | import java.util.prefs.Preferences; |
| | | |
| | | /** |
| | | * License生成类 |
| | | */ |
| | | public class LicenseCreator { |
| | | private static Logger logger = LogManager.getLogger(LicenseCreator.class); |
| | | private final static X500Principal DEFAULT_HOLDER_AND_ISSUER = new X500Principal("CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN"); |
| | | private LicenseCreatorParam param; |
| | | |
| | | public LicenseCreator(LicenseCreatorParam param) { |
| | | this.param = param; |
| | | } |
| | | |
| | | /** |
| | | * 生成License证书 |
| | | */ |
| | | public boolean generateLicense(){ |
| | | try { |
| | | LicenseManager licenseManager = new CustomLicenseManager(initLicenseParam()); |
| | | LicenseContent licenseContent = initLicenseContent(); |
| | | |
| | | licenseManager.store(licenseContent,new File(param.getLicensePath())); |
| | | |
| | | return true; |
| | | }catch (Exception e){ |
| | | logger.error(MessageFormat.format("证书生成失败:{0}",param),e); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 初始化证书生成参数 |
| | | */ |
| | | private LicenseParam initLicenseParam(){ |
| | | Preferences preferences = Preferences.userNodeForPackage(LicenseCreator.class); |
| | | |
| | | //设置对证书内容加密的秘钥 |
| | | CipherParam cipherParam = new DefaultCipherParam(param.getStorePass()); |
| | | |
| | | KeyStoreParam privateStoreParam = new CustomKeyStoreParam(LicenseCreator.class |
| | | ,param.getPrivateKeysStorePath() |
| | | ,param.getPrivateAlias() |
| | | ,param.getStorePass() |
| | | ,param.getKeyPass()); |
| | | |
| | | LicenseParam licenseParam = new DefaultLicenseParam(param.getSubject() |
| | | ,preferences |
| | | ,privateStoreParam |
| | | ,cipherParam); |
| | | |
| | | return licenseParam; |
| | | } |
| | | |
| | | /** |
| | | * 设置证书生成正文信息 |
| | | */ |
| | | private LicenseContent initLicenseContent(){ |
| | | LicenseContent licenseContent = new LicenseContent(); |
| | | licenseContent.setHolder(DEFAULT_HOLDER_AND_ISSUER); |
| | | licenseContent.setIssuer(DEFAULT_HOLDER_AND_ISSUER); |
| | | |
| | | licenseContent.setSubject(param.getSubject()); |
| | | licenseContent.setIssued(param.getIssuedTime()); |
| | | licenseContent.setNotBefore(param.getIssuedTime()); |
| | | licenseContent.setNotAfter(param.getExpiryTime()); |
| | | licenseContent.setConsumerType(param.getConsumerType()); |
| | | licenseContent.setConsumerAmount(param.getConsumerAmount()); |
| | | licenseContent.setInfo(param.getDescription()); |
| | | |
| | | //扩展校验服务器硬件信息 |
| | | licenseContent.setExtra(param.getLicenseCheck()); |
| | | |
| | | return licenseContent; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * License生成类需要的参数 |
| | | */ |
| | | @Data |
| | | public class LicenseCreatorParam implements Serializable { |
| | | |
| | | private static final long serialVersionUID = -7793154252684580872L; |
| | | /** |
| | | * 证书subject |
| | | */ |
| | | private String subject; |
| | | |
| | | /** |
| | | * 密钥别称 |
| | | */ |
| | | private String privateAlias; |
| | | |
| | | /** |
| | | * 密钥密码(需要妥善保管,不能让使用者知道) |
| | | */ |
| | | private String keyPass; |
| | | |
| | | /** |
| | | * 访问秘钥库的密码 |
| | | */ |
| | | private String storePass; |
| | | |
| | | /** |
| | | * 证书生成路径 |
| | | */ |
| | | private String licensePath; |
| | | |
| | | /** |
| | | * 密钥库存储路径 |
| | | */ |
| | | private String privateKeysStorePath; |
| | | |
| | | /** |
| | | * 证书生效时间 |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | private Date issuedTime = new Date(); |
| | | |
| | | /** |
| | | * 证书失效时间 |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | private Date expiryTime; |
| | | |
| | | /** |
| | | * 用户类型 |
| | | */ |
| | | private String consumerType = "user"; |
| | | |
| | | /** |
| | | * 用户数量 |
| | | */ |
| | | private Integer consumerAmount = 1; |
| | | |
| | | /** |
| | | * 描述信息 |
| | | */ |
| | | private String description = ""; |
| | | |
| | | /** |
| | | * 额外的服务器硬件校验信息 |
| | | */ |
| | | private LicenseCheck licenseCheck; |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "LicenseCreatorParam{" + |
| | | "subject='" + subject + '\'' + |
| | | ", privateAlias='" + privateAlias + '\'' + |
| | | ", keyPass='" + keyPass + '\'' + |
| | | ", storePass='" + storePass + '\'' + |
| | | ", licensePath='" + licensePath + '\'' + |
| | | ", privateKeysStorePath='" + privateKeysStorePath + '\'' + |
| | | ", issuedTime=" + issuedTime + |
| | | ", expiryTime=" + expiryTime + |
| | | ", consumerType='" + consumerType + '\'' + |
| | | ", consumerAmount=" + consumerAmount + |
| | | ", description='" + description + '\'' + |
| | | ", licenseCheck=" + licenseCheck + |
| | | '}'; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import de.schlichtherle.license.LicenseManager; |
| | | import de.schlichtherle.license.LicenseParam; |
| | | |
| | | public class LicenseManagerHolder { |
| | | |
| | | private static volatile LicenseManager LICENSE_MANAGER; |
| | | |
| | | public static LicenseManager getInstance(LicenseParam param) { |
| | | if (LICENSE_MANAGER == null) { |
| | | synchronized (LicenseManagerHolder.class) { |
| | | if (LICENSE_MANAGER == null) { |
| | | LICENSE_MANAGER = new CustomLicenseManager(param); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return LICENSE_MANAGER; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import de.schlichtherle.license.*; |
| | | import org.apache.logging.log4j.LogManager; |
| | | 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; |
| | | |
| | | /** |
| | | * License校验类 |
| | | */ |
| | | public class LicenseVerify { |
| | | private static Logger logger = LogManager.getLogger(LicenseVerify.class); |
| | | |
| | | /** |
| | | * 安装License证书 |
| | | */ |
| | | public synchronized LicenseContent install(LicenseVerifyParam param, String license) { |
| | | LicenseContent result = null; |
| | | DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | |
| | | //1. 安装证书 |
| | | try { |
| | | LicenseParam licenseParam = initLicenseParam(param); |
| | | LicenseManager licenseManager = LicenseManagerHolder.getInstance(licenseParam); |
| | | licenseManager.uninstall(); |
| | | |
| | | 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; |
| | | } |
| | | |
| | | /** |
| | | * 校验License证书 |
| | | */ |
| | | public boolean verify(){ |
| | | try { |
| | | LicenseManager licenseManager = LicenseManagerHolder.getInstance(null); |
| | | DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | |
| | | LicenseContent licenseContent = licenseManager.verify(); |
| | | logger.info(MessageFormat.format("许可证校验通过,许可证有效期:{0} - {1}",format.format(licenseContent.getNotBefore()),format.format(licenseContent.getNotAfter()))); |
| | | return true; |
| | | }catch (Exception e){ |
| | | logger.error("许可证校验失败!",e); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 校验License证书并获取证书信息 |
| | | */ |
| | | public LicenseContent getVerifyInfo(){ |
| | | LicenseManager licenseManager = LicenseManagerHolder.getInstance(null); |
| | | |
| | | //校验证书 |
| | | try { |
| | | LicenseContent licenseContent = licenseManager.verify(); |
| | | return licenseContent; |
| | | }catch (Exception e){ |
| | | logger.error("许可证校验失败!",e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 初始化证书生成参数 |
| | | * @param param License校验类需要的参数 |
| | | * @return de.schlichtherle.license.LicenseParam |
| | | */ |
| | | private LicenseParam initLicenseParam(LicenseVerifyParam param){ |
| | | Preferences preferences = Preferences.userNodeForPackage(LicenseVerify.class); |
| | | |
| | | CipherParam cipherParam = new DefaultCipherParam(param.getStorePass()); |
| | | |
| | | KeyStoreParam publicStoreParam = new CustomKeyStoreParam(LicenseVerify.class |
| | | ,param.getPublicKeysStorePath() |
| | | ,param.getPublicAlias() |
| | | ,param.getStorePass() |
| | | ,null); |
| | | |
| | | return new DefaultLicenseParam(param.getSubject() |
| | | ,preferences |
| | | ,publicStoreParam |
| | | ,cipherParam); |
| | | } |
| | | |
| | | /** |
| | | * 将Base64字符串转换为临时文件 |
| | | * @param base64String Base64编码的字符串 |
| | | * @param filePrefix 文件名前缀(例如 "license_") |
| | | * @param fileSuffix 文件后缀(例如 ".lic") |
| | | * @return 生成的临时File对象(自动在JVM退出时删除) |
| | | * @throws IOException |
| | | */ |
| | | 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"); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * 校验签名文件 |
| | | */ |
| | | @Data |
| | | public class LicenseVerifyParam { |
| | | |
| | | /** |
| | | * 证书subject |
| | | */ |
| | | private String subject; |
| | | |
| | | /** |
| | | * 公钥别称 |
| | | */ |
| | | private String publicAlias; |
| | | |
| | | /** |
| | | * 访问公钥库的密码 |
| | | */ |
| | | private String storePass; |
| | | |
| | | /** |
| | | * 证书生成路径 |
| | | */ |
| | | private String licensePath; |
| | | |
| | | /** |
| | | * 密钥库存储路径 |
| | | */ |
| | | private String publicKeysStorePath; |
| | | |
| | | public LicenseVerifyParam() { |
| | | |
| | | } |
| | | |
| | | public LicenseVerifyParam(String subject, String publicAlias, String storePass, String licensePath, String publicKeysStorePath) { |
| | | this.subject = subject; |
| | | this.publicAlias = publicAlias; |
| | | this.storePass = storePass; |
| | | this.licensePath = licensePath; |
| | | this.publicKeysStorePath = publicKeysStorePath; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | 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; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.system.entity.license; |
| | | |
| | | import java.net.InetAddress; |
| | | import java.util.List; |
| | | import java.util.Scanner; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 用于获取客户Windows服务器的基本信息 |
| | | */ |
| | | public class WindowsServerInfos 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 = ""; |
| | | |
| | | //使用WMIC获取CPU序列号 |
| | | Process process = Runtime.getRuntime().exec("wmic cpu get processorid"); |
| | | process.getOutputStream().close(); |
| | | Scanner scanner = new Scanner(process.getInputStream()); |
| | | |
| | | if(scanner.hasNext()){ |
| | | scanner.next(); |
| | | } |
| | | |
| | | if(scanner.hasNext()){ |
| | | serialNumber = scanner.next().trim(); |
| | | } |
| | | |
| | | scanner.close(); |
| | | return serialNumber; |
| | | } |
| | | |
| | | @Override |
| | | protected String getMainBoardSerial() throws Exception { |
| | | //序列号 |
| | | String serialNumber = ""; |
| | | |
| | | //使用WMIC获取主板序列号 |
| | | Process process = Runtime.getRuntime().exec("wmic baseboard get serialnumber"); |
| | | process.getOutputStream().close(); |
| | | Scanner scanner = new Scanner(process.getInputStream()); |
| | | |
| | | if(scanner.hasNext()){ |
| | | scanner.next(); |
| | | } |
| | | |
| | | if(scanner.hasNext()){ |
| | | serialNumber = scanner.next().trim(); |
| | | } |
| | | |
| | | scanner.close(); |
| | | return serialNumber; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.system.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.mapper.BaseMapper; |
| | | import com.zy.system.entity.LicenseInfos; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.springframework.stereotype.Repository; |
| | | |
| | | @Mapper |
| | | @Repository |
| | | public interface LicenseInfosMapper extends BaseMapper<LicenseInfos> { |
| | | |
| | | LicenseInfos getLatestLicense(); |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.system.service; |
| | | |
| | | import com.baomidou.mybatisplus.service.IService; |
| | | import com.zy.system.entity.LicenseInfos; |
| | | |
| | | public interface LicenseInfosService extends IService<LicenseInfos> { |
| | | |
| | | LicenseInfos getLatestLicense(); |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.system.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.service.impl.ServiceImpl; |
| | | import com.zy.system.entity.LicenseInfos; |
| | | import com.zy.system.mapper.LicenseInfosMapper; |
| | | import com.zy.system.service.LicenseInfosService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | @Service("licenseInfosService") |
| | | public class LicenseInfosServiceImpl extends ServiceImpl<LicenseInfosMapper, LicenseInfos> implements LicenseInfosService { |
| | | |
| | | @Override |
| | | public LicenseInfos getLatestLicense() { |
| | | return this.baseMapper.getLatestLicense(); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.system.timer; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | 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; |
| | | } |
| | | |
| | | } |
| | |
| | | enabled: false |
| | | datasource: |
| | | driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver |
| | | # url: jdbc:sqlserver://172.17.3.20:1433;databasename=ycawdasrs |
| | | url: jdbc:sqlserver://127.0.0.1:1433;databasename=ycawdasrs |
| | | username: sa |
| | | password: sa@123 |
| | |
| | | swagger: |
| | | enable: false |
| | | |
| | | #License相关配置 |
| | | license: |
| | | subject: awdasrs |
| | | publicAlias: publicCert |
| | | storePass: public_zhongyang_123456789 |
| | | licensePath: license.lic |
| | | publicKeysStorePath: publicCerts.keystore |
| | | |
| | | # 下位机配置 |
| | | wcs-slave: |
| | | # 双深 |
| | |
| | | acctID: "67af18a2bc317c" |
| | | username: "立库" |
| | | password: "123456" |
| | | lcid: 2052 |
| | | lcid: 2052 |
| | | |
| | | rcs: |
| | | # 地址 |
| | | address: |
| | | URL: https://172.17.3.120 |
| | | #任务下发接口 |
| | | reportTask: rcs/rtas/api/robot/controller/task/submit |
| | | #站点绑定和解绑 |
| | | siteBindAndUnbing: rcs/rtas/api/robot/controller/site/bind |
| New file |
| | |
| | | ¸!´;Ér-C>?ÍF=î°0+¢åxµ¬¨Zâ[ö¤±¼9}½ |
| | | ÑÅöıV]Aw"öcÚ{|Á=
&Y<±Æ¼û'W~à®í;\$Ì/H$ ÈB};
.º,X:YÒQc:æg&JªGf°Ö^½:6ÊKç¨\ß-Ì©ü78|ÃqÇoQÙcapÙxQUÆûÄP¤öoø$ü k¤|+js¾Vs)vz!áQÆ¥©ÍV³_uÂMùb"Õx±ú Îæ¾×lë-ÿ©M¬9MÚþÎeA]¤±*-cnµQRO5ÕkJBö¢¸´5Íñ _)£éöjQCú¢*liz©mN`}Þíìg$(ÿ¡?ë1òT}ïjÃÇP½±im½Ûò\¸Y«NÚþm(ÊÙ"d³BXc¿EÀÛB>ß[!QI:àº2Øt+Ykmdðîk^ôÁ.øôÑÀÆcHß¿:mU$,ýlÜQeqcµº¤µÖqåZ*òVØæ©$!BÖã}ÿY#NQ~ÜÈO6åïBƾo[&sC uDìw(È<VÀmå¡Qä^eÂðw{ø8ò{þqÛïû<¼¾;L×û±Yô_ôСW½b`=`ýÇÆwÒ.Ô¿ÓTløôÒßèÑ7QØËË |
| | | Y8¶òÒ[Yá
M.w8GÕéhÓwìèo
~óÎ^Û%Úe¼Ý^Ûéÿ)P
º,t»«f>°ºDD1t³,WmééhæÒU!ÚÁ;½´àTW |
| New file |
| | |
| | | <?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 dbo.sys_license_infos order by create_time desc |
| | | </select> |
| | | |
| | | </mapper> |
| New file |
| | |
| | | /*! |
| | | * file : layx.css |
| | | * gitee : https://gitee.com/monksoul/LayX |
| | | * github : https://github.com/MonkSoul/Layx/ |
| | | * author : 百小僧/MonkSoul |
| | | * version : v2.5.4 |
| | | * create time : 2018.05.11 |
| | | * update time : 2018.11.03 |
| | | */ |
| | | *[class^="layx-"]{box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;margin:0;padding:0;outline:none;border:none;background-color:transparent}.layx-flexbox{display:-webkit-box;display:-ms-flexbox;display:flex;display:-webkit-flex}.layx-flex-vertical{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-align-items:center;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;-webkit-justify-content:flex-start}.layx-flex-center{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-justify-content:center}.layx-flexauto{flex:1;-webkit-box-flex:1;-moz-box-flex:1;-webkit-flex:1;-ms-flex:1}.layx-shade,#layx-window-move{position:fixed;top:0;right:0;bottom:0;left:0;width:100%;height:100%;background-color:transparent}body.ilayx-body{overflow:hidden !important}.layx-window{position:fixed;overflow:visible !important;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;color:#000;-webkit-tap-highlight-color:rgba(0,0,0,0);visibility:visible;border:none}.layx-window.layx-flicker{animation-name:layx-flicker;-webkit-animation-name:layx-flicker;-moz-animation-name:layx-flicker;animation-duration:.12s;-webkit-animation-duration:.12s;-moz-animation-duration:.12s;animation-iteration-count:8;-webkit-animation-iteration-count:8;-moz-animation-iteration-count:8}.layx-window.layx-max-statu,.layx-window.layx-max-statu .layx-control-bar,.layx-window.layx-max-statu .layx-main,.layx-window.layx-max-statu .layx-statu-bar{border-radius:0 !important;-webkit-border-radius:0 !important;-moz-border-radius:0 !important}.layx-window.layx-min-statu{min-height:0 !important;overflow:hidden !important;min-width:0 !important}.layx-window.layx-min-statu .layx-title{overflow:hidden !important}.layx-window.layx-min-statu .layx-inlay-menus .layx-stick-menu,.layx-window.layx-min-statu .layx-inlay-menus .layx-debug-menu{display:none}.layx-window.layx-bubble-type{overflow:visible !important;position:absolute !important}.layx-window.layx-hide-statu{display:none !important}.layx-control-bar{min-height:30px;overflow:hidden;width:100%;padding-left:5px}.layx-iconfont{width:1em;height:1em;vertical-align:-.15em;fill:currentColor;overflow:hidden;font-size:14px;line-height:normal;display:block;line-height:normal}.layx-icon{text-align:center}.layx-icon *{pointer-events:none}.layx-left-bar{margin-right:5px}.layx-window-icon{-webkit-tap-highlight-color:rgba(0,0,0,0)}.layx-window-icon .layx-iconfont{font-size:16px}.layx-title,.layx-group-tab{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;margin-right:5px;min-width:0;-ms-touch-action:none;touch-action:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.layx-title{-webkit-app-region:drag}.layx-group-tab{-webkit-app-region:no-drag}.layx-title .layx-label,.layx-group-title .layx-label{line-height:normal;font-size:14px;max-width:100%;-webkit-line-clamp:1;-webkit-box-orient:vertical;word-wrap:break-word;overflow:hidden;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;display:inline-block;pointer-events:none;visibility:visible;position:relative;top:-1px;top:0px\0}.layx-group-tab .layx-label{line-height:28px}.layx-group-tab.layx-type-group{overflow:visible;margin-right:0;border-bottom:1px solid #ddd}.layx-control-bar.layx-type-group{overflow:visible;border-bottom:1px solid #ddd}.layx-group-title{height:27px;line-height:25px;max-width:150px;width:150px;padding:0 8px;background-color:#f5f5f5;border:1px solid #ddd;border-width:1px 1px 0 0;position:relative;color:#666;white-space:nowrap;min-width:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}.layx-title.layx-type-group .layx-group-title{height:30px;line-height:34px}.layx-title.layx-type-group{overflow:visible}.layx-title.layx-type-group .layx-group-title:first-child{border-left:1px solid #ddd}.layx-group-title[data-enable="1"]{background-color:#fff;color:#000}.layx-group-title[data-enable="1"]::after{position:absolute;top:0;right:0;bottom:0;left:0;height:100%;width:100%;content:'';border-bottom:1px solid #fff}.layx-inlay-menus{height:100%;height:30px;line-height:30px;position:relative;max-height:30px;z-index:2}.layx-inlay-menus .layx-icon{width:45px;-webkit-tap-highlight-color:rgba(0,0,0,0)}.layx-inlay-menus .layx-icon:hover{background-color:#e5e5e5}.layx-inlay-menus .layx-icon.layx-destroy-menu:hover{background-color:#e81123 !important;color:#fff !important}.layx-inlay-menus .layx-icon.layx-stick-menu[data-enable='1']{color:#f00}.layx-main{overflow:auto;position:relative;clear:both;-webkit-overflow-scrolling:touch;-webkit-transform:translate3d(0,0,0);-webkit-app-region:no-drag}.layx-readonly{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;background:transparent;z-index:199205270356}.layx-group-main{position:absolute;top:0;right:0;bottom:0;left:0;height:100%;width:100%;z-index:0;visibility:hidden;overflow:auto;-webkit-overflow-scrolling:touch;-webkit-transform:translate3d(0,0,0)}.layx-group-main[data-enable="1"]{z-index:1;visibility:visible}.layx-mouse-preventDefault{position:absolute;z-index:3;height:100%;width:100%;left:0;top:0;right:0;bottom:0;overflow:hidden;background-color:transparent}.layx-content-shade{position:absolute;z-index:2;width:100%;height:100%;left:0;right:0;bottom:0;top:0;overflow:hidden;background-color:#fff}.layx-html{width:100%;height:100%;position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;-webkit-overflow-scrolling:touch;-webkit-transform:translate3d(0,0,0);overflow:auto}.layx-dialog-icon{margin-right:10px;position:relative;top:-5px}.layx-dialog-icon .layx-iconfont{font-size:40px !important}.layx-dialog-msg .layx-dialog-icon .layx-iconfont,.layx-dialog-tip .layx-dialog-icon .layx-iconfont{font-size:25px !important}.layx-dialog-msg .layx-dialog-icon,.layx-dialog-tip .layx-dialog-icon{top:0}.layx-dialog-icon-success{color:#01aaed}.layx-dialog-icon-warn{color:#ffb800}.layx-dialog-icon-error{color:#f00}.layx-dialog-icon-help{color:#009688}.layx-dialog-msg,.layx-dialog-tip,.layx-dialog-load{color:#000;padding:10px}.layx-dialog-alert,.layx-dialog-confirm,.layx-dialog-prompt{padding:10px;color:#039}.layx-dialog-prompt{width:100%}.layx-dialog-msg,.layx-dialog-tip{height:100%}.layx-dialog-content{font-size:14px}.layx-textarea{display:block;border:1px solid #ddd;width:100%;resize:none;height:60px;margin-top:8px;padding:8px;font-size:15px;color:#000;line-height:1.5}.layx-textarea:focus{border:1px solid #3baced}.layx-buttons{padding:8px 10px;text-align:right}.layx-button-item{padding:0 16px;height:24px;line-height:normal;color:#000;font-size:14px;border:1px solid #adadad;outline:none;margin-left:8px;display:inline-block;background-color:#e1e1e1;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.layx-buttons .layx-button-item:hover{background-color:#e5f1fb;border:1px solid #0078d7}.layx-buttons .layx-button-item[disabled]{color:#999;cursor:not-allowed}.layx-buttons .layx-button-item[disabled]:hover{background-color:#e1e1e1;border:1px solid #adadad}.layx-iframe{width:1px;min-width:100%;*width:100%;height:100%;position:absolute;top:0;right:0;bottom:0;left:0;z-index:1}.layx-statu-bar{border-top:1px solid #ddd;min-height:25px;background-color:#eeeef2}.layx-resizes[data-enable='0']{visibility:hidden}.layx-resizes>div{position:absolute;z-index:3;-ms-touch-action:none;touch-action:none}.layx-resize-top,.layx-resize-bottom{height:3px;left:3px;right:3px}.layx-resize-top{top:0;cursor:n-resize}.layx-resize-bottom{bottom:0;cursor:s-resize}.layx-resize-left,.layx-resize-right{width:3px;top:3px;bottom:3px}.layx-resize-left{left:0;cursor:w-resize}.layx-resize-right{right:0;cursor:e-resize}.layx-resize-left-top,.layx-resize-right-top,.layx-resize-left-bottom,.layx-resize-right-bottom{width:3px;height:3px}.layx-resize-left-top{left:0;top:0;cursor:nw-resize}.layx-resize-right-top{right:0;top:0;cursor:ne-resize}.layx-resize-left-bottom{left:0;bottom:0;cursor:sw-resize}.layx-resize-right-bottom{right:0;bottom:0;cursor:se-resize}.layx-resize-top.layx-reisize-touch,.layx-resize-bottom.layx-reisize-touch{height:16px;left:16px;right:16px}.layx-resize-left.layx-reisize-touch,.layx-resize-right.layx-reisize-touch{width:16px;top:16px;bottom:16px}.layx-resize-left-top.layx-reisize-touch,.layx-resize-right-top.layx-reisize-touch,.layx-resize-left-bottom.layx-reisize-touch,.layx-resize-right-bottom.layx-reisize-touch{width:16px;height:16px}.layx-resize-top.layx-reisize-touch{top:-8px}.layx-resize-bottom.layx-reisize-touch{bottom:-8px}.layx-resize-left.layx-reisize-touch{left:-8px}.layx-resize-right.layx-reisize-touch{right:-8px}.layx-resize-left-top.layx-reisize-touch{left:-8px;top:-8px}.layx-resize-right-top.layx-reisize-touch{right:-8px;top:-8px}.layx-resize-left-bottom.layx-reisize-touch{left:-8px;bottom:-8px}.layx-resize-right-bottom.layx-reisize-touch{right:-8px;bottom:-8px}.layx-resize-left[data-enable='0'],.layx-resize-top[data-enable='0'],.layx-resize-right[data-enable='0'],.layx-resize-bottom[data-enable='0'],.layx-resize-left-top[data-enable='0'],.layx-resize-left-bottom[data-enable='0'],.layx-resize-right-top[data-enable='0'],.layx-resize-right-bottom[data-enable='0']{visibility:hidden}.layx-auto-destroy-tip{position:absolute;bottom:3px;right:3px;height:25px;line-height:25px;z-index:5;color:#444;background-color:#f1f1f1;padding:0 8px;font-size:13px}.layx-code{border:1px solid #dedede;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;padding:10px;width:100%;height:100%;-webkit-overflow-scrolling:touch;-webkit-transform:translate3d(0,0,0);background:#f5f5f5;overflow:auto}.layx-bubble,.layx-bubble-inlay{position:absolute;width:0;height:0}.layx-bubble-bottom{top:-11px;left:2px;border-left:10px solid transparent;border-right:10px solid transparent;border-bottom:11px solid transparent}.layx-bubble-inlay-bottom{top:2px;left:-9px;border-left:9px solid transparent;border-right:9px solid transparent;border-bottom:9px solid transparent}.layx-bubble-top{bottom:-11px;left:2px;border-left:10px solid transparent;border-right:10px solid transparent;border-top:11px solid transparent}.layx-bubble-inlay-top{bottom:2px;left:-9px;border-left:9px solid transparent;border-right:9px solid transparent;border-top:9px solid transparent}.layx-bubble-right{top:2px;left:-11px;border-top:10px solid transparent;border-bottom:10px solid transparent;border-right:11px solid transparent}.layx-bubble-inlay-right{top:-9px;left:2px;border-top:9px solid transparent;border-bottom:9px solid transparent;border-right:9px solid transparent}.layx-bubble-left{top:2px;right:-11px;border-top:10px solid transparent;border-bottom:10px solid transparent;border-left:11px solid transparent}.layx-bubble-inlay-left{top:-9px;right:2px;border-top:9px solid transparent;border-bottom:9px solid transparent;border-left:9px solid transparent}.layx-pre{height:auto;width:100%;font-size:14px;font-family:Arial;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;display:block;font-family:Arial}.layx-dot{display:inline-block;width:25px}.layx-load-animate{width:32px;height:32px;position:relative;margin-right:10px}.layx-load-inner,.layx-load-inner2{position:absolute;width:100%;height:100%;border-radius:40px;-webkit-border-radius:40px;-moz-border-radius:40px;overflow:hidden;left:0;top:0}.layx-load-inner{opacity:1;background-color:#89abdd;-webkit-animation:layx-second-half-hide 1.6s steps(1,end) infinite;animation:layx-second-half-hide 1.6s steps(1,end) infinite;-moz-animation:layx-second-half-hide 1.6s steps(1,end) infinite}.layx-load-inner2{opacity:0;background-color:#4b86db;-webkit-animation:layx-second-half-show 1.6s steps(1,end) infinite;animation:layx-second-half-show 1.6s steps(1,end) infinite;-moz-animation:layx-second-half-show 1.6s steps(1,end) infinite}.layx-load-spiner,.layx-load-filler,.layx-load-masker{position:absolute;width:50%;height:100%}.layx-load-spiner{border-radius:40px 0 0 40px;-webkit-border-radius:40px 0 0 40px;-moz-border-radius:40px 0 0 40px;background-color:#4b86db;-webkit-transform-origin:right center;-ms-transform-origin:right center;transform-origin:right center;-moz-transform-origin:right center;-webkit-animation:layx-spin 800ms infinite linear;animation:layx-spin 800ms infinite linear;-moz-animation:layx-spin 800ms infinite linear;left:0;top:0}.layx-load-filler{border-radius:0 40px 40px 0;-webkit-border-radius:0 40px 40px 0;-moz-border-radius:0 40px 40px 0;background-color:#4b86db;-webkit-animation:layx-second-half-hide 800ms steps(1,end) infinite;animation:layx-second-half-hide 800ms steps(1,end) infinite;-moz-animation:layx-second-half-hide 800ms steps(1,end) infinite;left:50%;top:0;opacity:1}.layx-load-masker{border-radius:40px 0 0 40px;-moz-border-radius:40px 0 0 40px;-webkit-border-radius:40px 0 0 40px;background-color:#89abdd;-webkit-animation:layx-second-half-show 800ms steps(1,end) infinite;animation:layx-second-half-show 800ms steps(1,end) infinite;-moz-animation:layx-second-half-show 800ms steps(1,end) infinite;left:0;top:0;opacity:0}.layx-load-inner2 .layx-load-spiner,.layx-load-inner2 .layx-load-filler{background-color:#89abdd}.layx-load-inner2 .layx-load-masker{background-color:#4b86db}.layx-window.layx-skin-default{border:1px solid #3baced}.layx-window.layx-skin-default .layx-control-bar{background-color:#fff}.layx-window.layx-skin-cloud .layx-control-bar{background-color:#ecf0f1}.layx-window.layx-skin-cloud .layx-inlay-menus .layx-icon:hover{background-color:#bdc3c7}.layx-window.layx-skin-cloud .layx-button-item{background-color:#ecf0f1;border:1px solid #ccc}.layx-window.layx-skin-cloud .layx-button-item:hover{background-color:#bdc3c7;color:#fff;border:1px solid #ecf0f1}.layx-window.layx-skin-turquoise .layx-control-bar{background-color:#1abc9c;color:#fff}.layx-window.layx-skin-turquoise .layx-inlay-menus .layx-icon:hover{background-color:#16a085}.layx-window.layx-skin-turquoise .layx-button-item{background-color:#1abc9c;color:#fff;border:1px solid #1abc9c}.layx-window.layx-skin-turquoise .layx-button-item:hover{background-color:#16a085;border:1px solid #1abc9c}.layx-window.layx-skin-river .layx-control-bar{background-color:#3498db;color:#fff}.layx-window.layx-skin-river .layx-inlay-menus .layx-icon:hover{background-color:#2980b9}.layx-window.layx-skin-river .layx-button-item{background-color:#3498db;color:#fff;border:1px solid #3498db}.layx-window.layx-skin-river .layx-button-item:hover{background-color:#2980b9;border:1px solid #3498db}.layx-window.layx-skin-asphalt .layx-control-bar{background-color:#34495e;color:#fff}.layx-window.layx-skin-asphalt .layx-inlay-menus .layx-icon:hover{background-color:#2c3e50}.layx-window.layx-skin-asphalt .layx-button-item{background-color:#34495e;color:#fff;border:1px solid #34495e}.layx-window.layx-skin-asphalt .layx-button-item:hover{background-color:#2c3e50;border:1px solid #34495e}@keyframes layx-flicker{from{-webkit-box-shadow:1px 1px 24px rgba(0,0,0,.3);box-shadow:1px 1px 24px rgba(0,0,0,.3);-moz-box-shadow:1px 1px 24px rgba(0,0,0,.3)}to{-webkit-box-shadow:1px 1px 12px rgba(0,0,0,.3);box-shadow:1px 1px 12px rgba(0,0,0,.3);-moz-box-shadow:1px 1px 12px rgba(0,0,0,.3)}}@-webkit-keyframes layx-flicker{from{-webkit-box-shadow:1px 1px 24px rgba(0,0,0,.3);box-shadow:1px 1px 24px rgba(0,0,0,.3);-moz-box-shadow:1px 1px 24px rgba(0,0,0,.3)}to{-webkit-box-shadow:1px 1px 12px rgba(0,0,0,.3);box-shadow:1px 1px 12px rgba(0,0,0,.3);-moz-box-shadow:1px 1px 12px rgba(0,0,0,.3)}}@-webkit-keyframes layx-spin{0%{-webkit-transform:rotate(360deg);transform:rotate(360deg);-moz-transform:rotate(360deg)}100%{-webkit-transform:rotate(0deg);transform:rotate(0deg);-moz-transform:rotate(0deg)}}@keyframes layx-spin{0%{-webkit-transform:rotate(360deg);transform:rotate(360deg);-moz-transform:rotate(360deg)}100%{-webkit-transform:rotate(0deg);transform:rotate(0deg);-moz-transform:rotate(0deg)}}@-webkit-keyframes layx-second-half-hide{0%{opacity:1}50%,100%{opacity:0}}@keyframes layx-second-half-hide{0%{opacity:1}50%,100%{opacity:0}}@-webkit-keyframes layx-second-half-show{0%{opacity:0}50%,100%{opacity:1}}@keyframes layx-second-half-show{0%{opacity:0}50%,100%{opacity:1}} |
| New file |
| | |
| | | /*! |
| | | * file : layx.js |
| | | * gitee : https://gitee.com/monksoul/LayX |
| | | * github : https://github.com/MonkSoul/Layx/ |
| | | * author : 百小僧/MonkSoul |
| | | * version : v2.5.4 |
| | | * create time : 2018.05.11 |
| | | * update time : 2018.11.03 |
| | | */ |
| | | !function(n,t){var r={version:"2.5.4",defaults:{id:"",icon:!0,title:"",width:800,height:600,minWidth:200,minHeight:200,position:"ct",storeStatus:!0,control:!0,style:"",controlStyle:"",existFlicker:!0,bgColor:"#fff",shadow:!0,border:!0,borderRadius:"3px",skin:"default",type:"html",focusToReveal:!0,enableDomainFocus:!0,dialogType:"",frames:[],frameIndex:0,preload:1,mergeTitle:!0,content:"",dialogIcon:!1,cloneElementContent:!0,url:"",useFrameTitle:!1,opacity:1,escKey:!0,floatTarget:!1,floatDirection:"bottom",shadable:!1,shadeDestroy:!1,readonly:!1,loadingText:"内容正在加载中,请稍后",dragInTopToMax:!0,isOverToMax:!0,stickMenu:!1,stickable:!0,minMenu:!0,minable:!0,maxMenu:!0,maxable:!0,closeMenu:!0,closable:!0,debugMenu:!1,restorable:!0,resizable:!0,autodestroy:!1,autodestroyText:"此窗口将在 <strong>{second}<\/strong> 秒内自动关闭.",resizeLimit:{t:!1,r:!1,b:!1,l:!1,lt:!1,rt:!1,lb:!1,rb:!1},buttonKey:"enter",buttons:[],movable:!0,moveLimit:{vertical:!1,horizontal:!1,leftOut:!0,rightOut:!0,topOut:!0,bottomOut:!0},focusable:!0,alwaysOnTop:!1,allowControlDbclick:!0,statusBar:!1,statusBarStyle:"",event:{onload:{before:function(){},after:function(){}},onmin:{before:function(){},after:function(){}},onmax:{before:function(){},after:function(){}},onrestore:{before:function(){},after:function(){}},ondestroy:{before:function(){},after:function(){}},onvisual:{before:function(){},after:function(){}},onmove:{before:function(){},progress:function(){},after:function(){}},onresize:{before:function(){},progress:function(){},after:function(){}},onfocus:function(){},onexist:function(){},onswitch:{before:function(){},after:function(){}},onstick:{before:function(){},after:function(){}}}},defaultButtons:{label:"确定",callback:function(){},id:"",classes:[],style:""},defaultFrames:{id:"",title:"",type:"html",url:"",content:"",useFrameTitle:!1,cloneElementContent:!0,bgColor:"#fff"},zIndex:1e7,windows:{},stickZIndex:2e7,prevFocusId:null,focusId:null,create:function(n){var s=this,e=layxDeepClone({},s.defaults,n||{}),o={},ct,lt,at,h,vi,yi,d,rt,ut,ft,ki,yt,oi,pi,l,p,pt,wt,v,bt,g,y,si,kt,wi,et,ot,k,nt,tt,st,a,hi,dt,vt,gi,c,b,ht,bi,ci,li,w,gt,ni,ti,ii,ri,ui,fi,ei,it,di,ai;if(!e.id){console.error("窗口id不能为空且唯一");return}if(r.prevFocusId=r.focusId,r.focusId=e.id,ct=s.windows[e.id],ct){if(ct.status==="min"&&s.restore(ct.id),ct.existFlicker===!0&&s.flicker(e.id),i.isFunction(e.event.onexist))e.event.onexist(ct.layxWindow,ct);return ai=setInterval(function(){e.id!==r.focusId?s.updateZIndex(e.id):clearInterval(ai)},0),ct}if(i.isArray(e.frames))for(c=0;c<e.frames.length;c++)if(e.frames[c]=layxDeepClone({},s.defaultFrames,e.frames[c]),!e.frames[c].id){console.error("窗口组窗口id不能为空且窗口组内唯一");return}if(i.isArray(e.buttons))for(c=0;c<e.buttons.length;c++)e.buttons[c]=layxDeepClone({},s.defaultButtons,e.buttons[c]);if((e.shadable===!0||/^(0(\.[0-9])?$)|(1)$/.test(e.shadable))&&(lt=document.createElement("div"),lt.setAttribute("id","layx-"+e.id+"-shade"),lt.classList.add("layx-shade"),lt.style.zIndex=e.alwaysOnTop===!0?++s.stickZIndex:++s.zIndex,/^(0(\.[0-9])?$)|(1)$/.test(e.shadable)&&(lt.style.backgroundColor="rgba(0,0,0,"+e.shadable+")"),lt.oncontextmenu=function(n){return n=n||window.event,n.returnValue=!1,!1},lt.onclick=function(n){n=n||window.event;e.shadeDestroy===!0?s.destroy(e.id,null,!0):e.existFlicker===!0&&s.flicker(e.id);n.stopPropagation()},document.body.appendChild(lt)),e.style&&(at=document.getElementById("layx-style"),at?at.innerHTML+=e.style:(at=document.createElement("style"),at.setAttribute("id","layx-style"),at.type="text/css",at.innerHTML=e.style,document.getElementsByTagName("HEAD").item(0).appendChild(at))),h=document.createElement("div"),h.setAttribute("id","layx-"+e.id),h.classList.add("layx-window"),h.classList.add("layx-flexbox"),h.classList.add("layx-skin-"+e.skin),e.shadow===!0&&(h.style.setProperty("box-shadow","1px 1px 24px rgba(0, 0, 0, .3)"),h.style.setProperty("-moz-box-shadow","1px 1px 24px rgba(0, 0, 0, .3)"),h.style.setProperty("-webkit-box-shadow","1px 1px 24px rgba(0, 0, 0, .3)")),vi=i.compileLayxWidthOrHeight("width",e.minWidth,s.defaults.minWidth),yi=i.compileLayxWidthOrHeight("height",e.minHeight,s.defaults.minHeight),d=i.compileLayxWidthOrHeight("width",e.width,s.defaults.width),rt=i.compileLayxWidthOrHeight("height",e.height,s.defaults.height),d=Math.max(d,vi),rt=Math.max(rt,yi),ki=i.compileLayxPosition(d,rt,e.position),ut=ki.top,ft=ki.left,ut=Math.max(ut,0),ut=Math.min(t.innerHeight-15,ut),ft=Math.max(ft,-(d-15)),ft=Math.min(ft,t.innerWidth-15),e.storeStatus===!0&&e.floatTarget===!1?(yt=s.getStoreWindowAreaInfo(e.id),yt?(d=yt.width,rt=yt.height,ut=yt.top,ft=yt.left):s.storeWindowAreaInfo(e.id,{width:d,height:rt,top:ut,left:ft})):s.removeStoreWindowAreaInfo(e.id),i.isDom(e.floatTarget)&&(h.classList.add("layx-bubble-type"),oi=document.createElement("div"),oi.classList.add("layx-bubble"),oi.classList.add("layx-bubble-"+e.floatDirection),h.appendChild(oi),pi=document.createElement("div"),pi.classList.add("layx-bubble-inlay"),pi.classList.add("layx-bubble-inlay-"+e.floatDirection),oi.appendChild(pi)),h.style.zIndex=e.alwaysOnTop===!0?++s.stickZIndex:++s.zIndex,h.style.width=d+"px",h.style.height=rt+"px",h.style.minWidth=vi+"px",h.style.minHeight=yi+"px",h.style.top=ut+"px",h.style.left=ft+"px",h.style.setProperty("border",i.isBoolean(e.border)?e.skin==="default"&&e.border===!0?"":"none":e.border),h.style.backgroundColor=e.bgColor,h.style.setProperty("border-radius",e.borderRadius),h.style.setProperty("-moz-border-radius",e.borderRadius),h.style.setProperty("-webkit-border-radius",e.borderRadius),h.style.opacity=/^(0(\.[0-9])?$)|(1)$/.test(e.opacity)?e.opacity:1,e.focusable===!0&&(h.onclick=function(n){if(n=n||window.event,i.isFunction(e.event.onfocus)){var t=i.isFunction(e.event.onfocus);if(t===!1)return;e.event.onfocus(h,o)}s.updateZIndex(e.id)}),document.body.appendChild(h),l=h.currentStyle?h.currentStyle:t.getComputedStyle(h,null),o.id=e.id,o.title=e.title,o.layxWindowId=h.getAttribute("id"),o.layxWindow=h,o.createDate=new Date,o.status="normal",o.type=e.type,o.buttons=e.buttons,o.frames=e.frames,o.useFrameTitle=e.useFrameTitle,o.cloneElementContent=e.cloneElementContent,o.storeStatus=e.storeStatus,o.url=e.url,o.content=e.content,o.escKey=e.escKey,o.focusToReveal=e.focusToReveal,o.dialogType=e.dialogType,o.enableDomainFocus=e.enableDomainFocus,o.buttonKey=e.buttonKey,o.existFlicker=e.existFlicker,o.groupCurrentId=i.isArray(e.frames)&&e.frames.length>0&&e.frames[e.frameIndex]?e.frames[e.frameIndex].id:null,o.area={width:d,height:rt,minWidth:vi,minHeight:yi,top:ut,left:ft},o.border=e.border,o.control=e.control,o.isFloatTarget=i.isDom(e.floatTarget),o.floatTarget=e.floatTarget,o.floatDirection=e.floatDirection,o.loadingText=e.loadingText,o.focusable=e.focusable,o.isStick=e.alwaysOnTop===!0,o.zIndex=e.alwaysOnTop===!0?s.stickZIndex:s.zIndex,o.movable=e.movable,o.moveLimit=e.moveLimit,o.resizable=e.resizable,o.resizeLimit=e.resizeLimit,o.stickable=e.stickable,o.minable=e.minable,o.maxable=e.maxable,o.restorable=e.restorable,o.closable=e.closable,o.skin=e.skin,o.event=e.event,o.dragInTopToMax=e.dragInTopToMax,s.windows[e.id]=o,e.control===!0){if(p=document.createElement("div"),p.classList.add("layx-control-bar"),p.classList.add("layx-flexbox"),p.style.setProperty("border-radius",l.borderRadius+" "+l.borderRadius+" 0 0"),p.style.setProperty("-moz-border-radius",l.borderRadius+" "+l.borderRadius+" 0 0"),p.style.setProperty("-webkit-border-radius",l.borderRadius+" "+l.borderRadius+" 0 0"),e.controlStyle&&p.setAttribute("style",e.controlStyle),e.type==="group"&&e.mergeTitle===!0&&p.classList.add("layx-type-group"),h.appendChild(p),e.icon!==!1&&(pt=document.createElement("div"),pt.classList.add("layx-left-bar"),pt.classList.add("layx-flexbox"),pt.classList.add("layx-flex-vertical"),p.appendChild(pt),wt=document.createElement("div"),wt.classList.add("layx-icon"),wt.classList.add("layx-window-icon"),wt.innerHTML=e.icon===!0?'<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-default-icon"><\/use><\/svg>':e.icon,e.icon===!0&&(wt.ondblclick=function(n){n=n||window.event;s.destroy(e.id,null,!0);n.stopPropagation()}),pt.appendChild(wt)),v=document.createElement("div"),v.classList.add("layx-title"),v.classList.add("layx-flexauto"),v.classList.add("layx-flexbox"),v.classList.add("layx-flex-vertical"),e.type==="group"&&e.mergeTitle===!0&&v.classList.add("layx-type-group"),e.allowControlDbclick===!0&&(v.ondblclick=function(n){n=n||window.event;e.restorable===!0&&s.restore(e.id);n.stopPropagation()}),e.movable===!0&&i.isDom(e.floatTarget)==!1&&new f(v),p.appendChild(v),e.type!=="group")g=document.createElement("label"),g.classList.add("layx-label"),g.innerHTML=e.useFrameTitle===!0?"":e.title,v.setAttribute("title",g.innerText),v.appendChild(g);else if(i.isArray(e.frames))for(e.mergeTitle===!1&&(bt=document.createElement("div"),bt.classList.add("layx-group-tab"),bt.classList.add("layx-flexbox"),bt.classList.add("layx-type-group"),h.appendChild(bt),g=document.createElement("label"),g.classList.add("layx-label"),g.innerHTML=e.useFrameTitle===!0?"":e.title,v.setAttribute("title",g.innerText),v.appendChild(g)),c=0;c<e.frames.length;c++)b=layxDeepClone({},s.defaultFrames,e.frames[c]),y=document.createElement("div"),y.setAttribute("data-frameId",b.id),y.classList.add("layx-group-title"),y.classList.add("layx-flexauto"),y.classList.add("layx-flex-vertical"),c===e.frameIndex&&y.setAttribute("data-enable","1"),i.isSupportTouch?(y.ontouchstart=function(n){n=n||window.event;s._setGroupIndex(e.id,this)},i.IsPC()&&(y.onclick=function(n){n=n||window.event;s._setGroupIndex(e.id,this);n.stopPropagation()})):y.onclick=function(n){n=n||window.event;s._setGroupIndex(e.id,this);n.stopPropagation()},e.mergeTitle===!1?bt.appendChild(y):v.appendChild(y),si=document.createElement("label"),si.classList.add("layx-label"),si.innerHTML=b.title,y.setAttribute("title",si.innerText),y.appendChild(si);kt=document.createElement("div");kt.classList.add("layx-right-bar");kt.classList.add("layx-flexbox");p.appendChild(kt);wi=document.createElement("div");wi.classList.add("layx-custom-menus");wi.classList.add("layx-flexbox");kt.appendChild(wi);(e.stickMenu===!0||e.minMenu===!0||e.maxMenu===!0||e.closeMenu===!0||e.debugMenu===!0)&&(et=document.createElement("div"),et.classList.add("layx-inlay-menus"),et.classList.add("layx-flexbox"),kt.appendChild(et),i.isDom(e.floatTarget)||(e.debugMenu===!0&&(ot=document.createElement("div"),ot.classList.add("layx-icon"),ot.classList.add("layx-flexbox"),ot.classList.add("layx-flex-center"),ot.classList.add("layx-debug-menu"),ot.setAttribute("title","调试信息"),ot.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-debug"><\/use><\/svg>',ot.onclick=function(n){n=n||window.event;var t=JSON.stringify(o,null,4).replace(/</g,"<").replace(/>/g,">");s.create({id:"layx-"+e.id+"-debug",title:"窗口调试信息",width:300,height:300,content:'<div class="layx-padding" style="padding:10px;height:100%;overflow:hidden;"><div class="layx-code"><pre class="layx-pre">'+t+"<\/pre><\/div><\/div>",shadable:!0,debugMenu:!1,minMenu:!1,minable:!1,position:[h.offsetTop+10,h.offsetLeft+10],storeStatus:!1})},et.appendChild(ot)),(e.stickMenu===!0||e.alwaysOnTop===!0&&e.stickMenu)&&(k=document.createElement("div"),k.classList.add("layx-icon"),k.classList.add("layx-flexbox"),k.classList.add("layx-flex-center"),k.classList.add("layx-stick-menu"),e.alwaysOnTop===!0?k.setAttribute("title","取消置顶"):k.setAttribute("title","置顶"),e.alwaysOnTop===!0&&k.setAttribute("data-enable","1"),k.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-stick"><\/use><\/svg>',e.stickable===!0&&(k.onclick=function(n){n=n||window.event;s.stickToggle(e.id)}),et.appendChild(k)),e.minMenu===!0&&(nt=document.createElement("div"),nt.classList.add("layx-icon"),nt.classList.add("layx-flexbox"),nt.classList.add("layx-flex-center"),nt.classList.add("layx-min-menu"),nt.setAttribute("title","最小化"),nt.setAttribute("data-menu","min"),nt.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-min"><\/use><\/svg>',nt.onclick=function(n){n=n||window.event;this.classList.contains("layx-restore-menu")?e.restorable===!0&&s.restore(e.id):e.minable===!0&&s.min(e.id)},et.appendChild(nt)),e.maxMenu===!0&&(tt=document.createElement("div"),tt.classList.add("layx-icon"),tt.classList.add("layx-flexbox"),tt.classList.add("layx-flex-center"),tt.classList.add("layx-max-menu"),tt.setAttribute("title","最大化"),tt.setAttribute("data-menu","max"),tt.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-max"><\/use><\/svg>',tt.onclick=function(n){n=n||window.event;this.classList.contains("layx-restore-menu")?e.restorable===!0&&s.restore(e.id):e.maxable===!0&&s.max(e.id)},et.appendChild(tt))),e.closeMenu===!0&&(st=document.createElement("div"),st.classList.add("layx-icon"),st.classList.add("layx-flexbox"),st.classList.add("layx-flex-center"),st.classList.add("layx-destroy-menu"),st.setAttribute("title","关闭"),st.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-destroy"><\/use><\/svg>',st.onclick=function(n){n=n||window.event;e.closable===!0&&s.destroy(e.id,null,!0)},et.appendChild(st)))}a=document.createElement("div");a.classList.add("layx-main");a.classList.add("layx-flexauto");e.statusBar||(a.style.setProperty("border-radius","0 0 "+l.borderRadius+" "+l.borderRadius),a.style.setProperty("-moz-border-radius","0 0 "+l.borderRadius+" "+l.borderRadius),a.style.setProperty("-webkit-border-radius","0 0 "+l.borderRadius+" "+l.borderRadius));h.appendChild(a);e.readonly===!0&&(hi=document.createElement("div"),hi.classList.add("layx-readonly"),hi.oncontextmenu=function(n){return n=n||window.event,n.returnValue=!1,!1},e.focusable===!0&&(hi.onclick=function(n){if(n=n||window.event,i.isFunction(e.event.onfocus)){var t=i.isFunction(e.event.onfocus);if(t===!1)return;e.event.onfocus(h,o)}s.updateZIndex(e.id);n.stopPropagation()}),a.appendChild(hi));switch(e.type){case"html":default:if(i.isFunction(e.event.onload.before)&&(dt=e.event.onload.before(h,o),dt===!1))return;vt=s.createContenLoadAnimate(a,e.loadingText,o);s.createHtmlBody(a,e,e.content);vt&&a.removeChild(vt);o.loadingTextTimer&&(clearInterval(o.loadingTextTimer),delete o.loadingTextTimer);i.isFunction(e.event.onload.after)&&e.event.onload.after(h,o);break;case"url":if(i.isFunction(e.event.onload.before)&&(dt=e.event.onload.before(h,o),dt===!1))return;vt=s.createContenLoadAnimate(a,e.loadingText,o);s.createFrameBody(a,e,h,o);break;case"group":if(i.isArray(e.frames)){if(i.isFunction(e.event.onload.before)&&(dt=e.event.onload.before(h,o),dt===!1))return;for(vt=s.createContenLoadAnimate(a,e.loadingText,o),e.preload=/(^[1-9]\d*$)/.test(e.preload)===!1?!0:Math.min(e.preload,e.frames.length),gi=setInterval(function(){var n=h.querySelectorAll(".layx-group-main[data-complete='1']");(n.length===i.isBoolean(e.preload)?e.frames.length:e.preload)&&(clearInterval(gi),o.loadingTextTimer&&(clearInterval(o.loadingTextTimer),delete o.loadingTextTimer),h.setAttribute("data-group-init","1"),vt&&a.removeChild(vt),i.isFunction(e.event.onload.after)&&e.event.onload.after(h,o))},100),c=0;c<e.frames.length;c++)b=layxDeepClone({},s.defaultFrames,e.frames[c]),ht=document.createElement("div"),ht.classList.add("layx-group-main"),ht.style.backgroundColor=b.bgColor,ht.setAttribute("data-frameId",b.id),c===e.frameIndex&&ht.setAttribute("data-enable","1"),a.appendChild(ht),bi=c===e.frameIndex?!0:i.isBoolean(e.preload)?!0:c+1<=e.preload,b.type==="html"?(s.createHtmlBody(ht,e,b.content,"group",b,bi),bi&&ht.setAttribute("data-complete","1")):b.type==="url"&&s.createFrameBody(ht,e,h,o,"group",b,bi)}}return/(^[1-9]\d*$)/.test(e.autodestroy)&&(ci=e.autodestroy/1e3,e.autodestroyText!==!1&&(li=document.createElement("div"),li.classList.add("layx-auto-destroy-tip"),li.innerHTML=e.autodestroyText.replace("{second}",ci),h.appendChild(li)),o.destroyTimer=setInterval(function(){--ci;e.autodestroyText!==!1&&(li.innerHTML=e.autodestroyText.replace("{second}",ci));ci<=0&&(clearInterval(o.destroyTimer),s.destroy(e.id,null,!0))},1e3)),w=document.createElement("div"),w.classList.add("layx-resizes"),e.resizable===!1&&w.setAttribute("data-enable","0"),h.appendChild(w),gt=document.createElement("div"),gt.classList.add("layx-resize-top"),i.isSupportTouch&>.classList.add("layx-reisize-touch"),e.resizeLimit.t===!0&>.setAttribute("data-enable","0"),new u(gt,!0,!1,!0,!1),w.appendChild(gt),ni=document.createElement("div"),ni.classList.add("layx-resize-left"),i.isSupportTouch&&ni.classList.add("layx-reisize-touch"),e.resizeLimit.l===!0&&ni.setAttribute("data-enable","0"),new u(ni,!1,!0,!1,!0),w.appendChild(ni),ti=document.createElement("div"),ti.classList.add("layx-resize-left-top"),i.isSupportTouch&&ti.classList.add("layx-reisize-touch"),e.resizeLimit.lt===!0&&ti.setAttribute("data-enable","0"),new u(ti,!0,!0,!1,!1),w.appendChild(ti),ii=document.createElement("div"),ii.classList.add("layx-resize-right-top"),i.isSupportTouch&&ii.classList.add("layx-reisize-touch"),e.resizeLimit.rt===!0&&ii.setAttribute("data-enable","0"),new u(ii,!0,!1,!1,!1),w.appendChild(ii),ri=document.createElement("div"),ri.classList.add("layx-resize-left-bottom"),i.isSupportTouch&&ri.classList.add("layx-reisize-touch"),e.resizeLimit.lb===!0&&ri.setAttribute("data-enable","0"),new u(ri,!1,!0,!1,!1),w.appendChild(ri),ui=document.createElement("div"),ui.classList.add("layx-resize-right"),i.isSupportTouch&&ui.classList.add("layx-reisize-touch"),e.resizeLimit.r===!0&&ui.setAttribute("data-enable","0"),new u(ui,!1,!1,!1,!0),w.appendChild(ui),fi=document.createElement("div"),fi.classList.add("layx-resize-bottom"),i.isSupportTouch&&fi.classList.add("layx-reisize-touch"),e.resizeLimit.b===!0&&fi.setAttribute("data-enable","0"),new u(fi,!1,!1,!0,!1),w.appendChild(fi),ei=document.createElement("div"),ei.classList.add("layx-resize-right-bottom"),i.isSupportTouch&&ei.classList.add("layx-reisize-touch"),e.resizeLimit.rb===!0&&ei.setAttribute("data-enable","0"),new u(ei,!1,!1,!1,!1),w.appendChild(ei),e.statusBar&&(it=document.createElement("div"),it.classList.add("layx-statu-bar"),it.style.setProperty("border-radius","0 0 "+l.borderRadius+" "+l.borderRadius),it.style.setProperty("-moz-border-radius","0 0 "+l.borderRadius+" "+l.borderRadius),it.style.setProperty("-webkit-border-radius","0 0 "+l.borderRadius+" "+l.borderRadius),e.statusBarStyle&&it.setAttribute("style",e.statusBarStyle),e.statusBar===!0&&i.isArray(e.buttons)?(di=s.createLayxButtons(e.buttons,e.id,e.dialogType==="prompt"?!0:!1),di&&it.appendChild(di)):i.isDom(e.statusBar)?it.appendChild(e.statusBar):it.innerHTML=e.statusBar,h.appendChild(it)),i.isDom(e.floatTarget)&&s.updateFloatWinPosition(e.id,e.floatDirection),e.isOverToMax===!0&&i.isDom(e.floatTarget)===!1&&(d>window.innerWidth||rt>window.innerHeight)&&s.max(e.id),ai=setInterval(function(){e.id!==r.focusId?s.updateZIndex(e.id):clearInterval(ai)},0),o},updateFloatWinPosition:function(n,r){var l=this,y="layx-"+n,s=document.getElementById(y),u=l.windows[n],e,o,a,v;if(s&&u&&u.isFloatTarget===!0&&(r=["top","bottom","left","right"].indexOf(r)>-1?r:u.floatDirection,e=s.querySelector(".layx-bubble"),o=s.querySelector(".layx-bubble-inlay"),e&&o)){e.classList.remove("layx-bubble-"+u.floatDirection);e.style["border"+u.floatDirection.toFirstUpperCase()+"Color"]="transparent";o.classList.remove("layx-bubble-inlay-"+u.floatDirection);o.style["border"+u.floatDirection.toFirstUpperCase()+"Color"]="transparent";e.classList.add("layx-bubble-"+r);o.classList.add("layx-bubble-inlay-"+r);var f=s.currentStyle?s.currentStyle:t.getComputedStyle(s,null),h=s.querySelector(".layx-control-bar"),c=h&&(h.currentStyle?h.currentStyle:t.getComputedStyle(h,null));u.control===!0&&h&&c?(e.style["border"+r.toFirstUpperCase()+"Color"]=f.borderColor==="rgba(0, 0, 0, 0)"||f.borderColor==="transparent"||!f.borderColor||i.isBoolean(u.border)?u.skin==="default"?"#3baced":c.backgroundColor:f.borderColor,o.style["border"+r.toFirstUpperCase()+"Color"]=c.backgroundColor):(e.style["border"+r.toFirstUpperCase()+"Color"]=f.borderColor==="rgba(0, 0, 0, 0)"||f.borderColor==="transparent"||!f.borderColor||i.isBoolean(u.border)?u.skin==="default"?"#3baced":"#fff":f.borderColor,o.style["border"+r.toFirstUpperCase()+"Color"]=f.backgroundColor);a=i.compilebubbleDirection(r,u.floatTarget,u.area.width,u.area.height);l.setPosition(n,{top:a.top,left:a.left},!0);v=i.getElementPos(u.floatTarget);(r==="top"||r==="bottom")&&(e.style.left=Math.abs(v.x+u.floatTarget.offsetWidth/2-u.layxWindow.offsetLeft-9)+"px");(r==="left"||r==="right")&&(e.style.top=Math.abs(v.y+u.floatTarget.offsetHeight/2-u.layxWindow.offsetTop-9)+"px");(r==="top"||(r==="right"||r==="left")&&u.control===!0&&h&&c&&e.offsetTop>h.offsetHeight)&&(e.style["border"+r.toFirstUpperCase()+"Color"]=f.borderColor==="rgba(0, 0, 0, 0)"||f.borderColor==="transparent"||!f.borderColor||i.isBoolean(u.border)?u.skin==="default"?"#3baced":"#fff":f.borderColor,o.style["border"+r.toFirstUpperCase()+"Color"]=f.backgroundColor);u.floatDirection=r;l.updateFloatWinResize(n,r)}},updateFloatWinResize:function(n,t){var u=this,f="layx-"+n,i=document.getElementById(f),r=u.windows[n];if(i&&r&&r.isFloatTarget===!0){t=["top","bottom","left","right"].indexOf(t)>-1?t:r.floatDirection;switch(t){case"bottom":i.querySelector(".layx-resize-left").setAttribute("data-enable","0");i.querySelector(".layx-resize-top").setAttribute("data-enable","0");i.querySelector(".layx-resize-left-top").setAttribute("data-enable","0");i.querySelector(".layx-resize-left-bottom").setAttribute("data-enable","0");i.querySelector(".layx-resize-right-top").setAttribute("data-enable","0");r.resizeLimit.r===!1&&i.querySelector(".layx-resize-right").removeAttribute("data-enable");r.resizeLimit.b===!1&&i.querySelector(".layx-resize-bottom").removeAttribute("data-enable");r.resizeLimit.rb===!1&&i.querySelector(".layx-resize-right-bottom").removeAttribute("data-enable");break;case"top":i.querySelector(".layx-resize-left").setAttribute("data-enable","0");i.querySelector(".layx-resize-left-top").setAttribute("data-enable","0");i.querySelector(".layx-resize-bottom").setAttribute("data-enable","0");i.querySelector(".layx-resize-left-bottom").setAttribute("data-enable","0");i.querySelector(".layx-resize-right-bottom").setAttribute("data-enable","0");r.resizeLimit.r===!1&&i.querySelector(".layx-resize-right").removeAttribute("data-enable");r.resizeLimit.t===!1&&i.querySelector(".layx-resize-top").removeAttribute("data-enable");r.resizeLimit.rt===!1&&i.querySelector(".layx-resize-right-top").removeAttribute("data-enable");break;case"right":i.querySelector(".layx-resize-left").setAttribute("data-enable","0");i.querySelector(".layx-resize-top").setAttribute("data-enable","0");i.querySelector(".layx-resize-left-top").setAttribute("data-enable","0");i.querySelector(".layx-resize-left-bottom").setAttribute("data-enable","0");i.querySelector(".layx-resize-right-top").setAttribute("data-enable","0");r.resizeLimit.r===!1&&i.querySelector(".layx-resize-right").removeAttribute("data-enable");r.resizeLimit.b===!1&&i.querySelector(".layx-resize-bottom").removeAttribute("data-enable");r.resizeLimit.rb===!1&&i.querySelector(".layx-resize-right-bottom").removeAttribute("data-enable");break;case"left":i.querySelector(".layx-resize-top").setAttribute("data-enable","0");i.querySelector(".layx-resize-right").setAttribute("data-enable","0");i.querySelector(".layx-resize-left-top").setAttribute("data-enable","0");i.querySelector(".layx-resize-right-top").setAttribute("data-enable","0");i.querySelector(".layx-resize-right-bottom").setAttribute("data-enable","0");r.resizeLimit.l===!1&&i.querySelector(".layx-resize-left").removeAttribute("data-enable");r.resizeLimit.b===!1&&i.querySelector(".layx-resize-bottom").removeAttribute("data-enable");r.resizeLimit.lb===!1&&i.querySelector(".layx-resize-left-bottom").removeAttribute("data-enable")}}},removeStoreWindowAreaInfo:function(n){var u=this,i="layx-"+n,r=typeof Storage!="undefined"&&!(t.location.protocol.indexOf("file:")>-1)&&localStorage.getItem(i);r&&localStorage.removeItem(i)},storeWindowAreaInfo:function(n,i){var u=this,r="layx-"+n;typeof Storage=="undefined"||t.location.protocol.indexOf("file:")>-1||localStorage.setItem(r,JSON.stringify(i))},getStoreWindowAreaInfo:function(n){var u=this,r="layx-"+n,i=typeof Storage!="undefined"&&!(t.location.protocol.indexOf("file:")>-1)&&localStorage.getItem(r);return i?JSON.parse(i):null},_setGroupIndex:function(n,t){var s=this,a="layx-"+n,u=document.getElementById(a),r=s.windows[n],h,c,f;if(u&&r&&r.type==="group"&&(h=u.querySelector(".layx-group-title[data-enable='1']"),h!==t)){if(i.isFunction(r.event.onswitch.before)&&(c=r.event.onswitch.before(u,r,h.getAttribute("data-frameId")),c===!1))return;h.removeAttribute("data-enable");t.setAttribute("data-enable","1");var e=t.getAttribute("data-frameId"),l=u.querySelector(".layx-group-main[data-enable='1']"),o=u.querySelector(".layx-group-main[data-frameId='"+e+"']");o!==l&&(l.removeAttribute("data-enable"),o.setAttribute("data-enable","1"),r.groupCurrentId=e,o.getAttribute("data-preload")==="1"&&(f=s.getGroupFrame(r.frames,e),f.type==="url"&&(s.setGroupUrl(n,e,f.url),o.removeAttribute("data-preload")),f.type==="html"&&(s.setGroupContent(n,e,f.content,f.cloneElementContent),o.removeAttribute("data-preload"))));i.isFunction(r.event.onswitch.after)&&r.event.onswitch.after(u,r,t.getAttribute("data-frameId"))}},setGroupIndex:function(n,t){var u=this,f="layx-"+n,i=document.getElementById(f),e=u.windows[n],r;i&&e&&(r=i.querySelector(".layx-group-title[data-frameId='"+t+"']"),r.click())},cloneStore:{},createHtmlBody:function(n,u,f,e,o,s){var v=this,c=document.createElement("div"),h,l,a;c.classList.add("layx-html");c.setAttribute("id","layx-"+u.id+(e==="group"?"-"+o.id+"-":"-")+"html");s!==!1?i.isDom(f)?(l=f.currentStyle?f.currentStyle:t.getComputedStyle(f,null),e!=="group"&&u.cloneElementContent===!1&&(r.cloneStore[u.id]={prev:f.previousSibling,parent:f.parentNode,next:f.nextSibling,display:l.display}),e==="group"&&o.cloneElementContent===!1&&(r.cloneStore[u.id]||(r.cloneStore[u.id]={frames:{}}),r.cloneStore[u.id].frames[o.id]={prev:f.previousSibling,parent:f.parentNode,next:f.nextSibling,display:l.display}),h=c.appendChild((e==="group"?o:u).cloneElementContent===!0?f.cloneNode(!0):f)):c.innerHTML=f:n.setAttribute("data-preload","1");n.appendChild(c);i.isDom(h)&&(a=h.currentStyle?h.currentStyle:t.getComputedStyle(h,null),a.display==="none"&&(h.style.display=""))},frameLoadHandle:function(n,t,u,f,o,s,h,c){var v=this,l=(s==="group"?n.parentNode.parentNode:n.parentNode).querySelector(".layx-content-shade"),a;try{u.focusable===!0&&u.enableDomainFocus===!0&&(n.getAttribute("data-focus")||(e.track(n,function(){if(i.isFunction(u.event.onfocus)){var n=i.isFunction(u.event.onfocus);if(n===!1)return;u.event.onfocus(f,o)}v.updateZIndex(u.id)}),n.setAttribute("data-focus","true")));a=u.title;s==="group"?h.useFrameTitle===!0&&(a=n.contentWindow.document.querySelector("title").innerText,v.setGroupTitle(u.id,h.id,a)):u.useFrameTitle===!0&&(a=n.contentWindow.document.querySelector("title").innerText,v.setTitle(u.id,a));n.contentWindow.document.addEventListener("click",function(n){var r=n||window.event||arguments.callee.caller.arguments[0],t;if(u.focusable===!0){if(i.isFunction(u.event.onfocus)){if(t=i.isFunction(u.event.onfocus),t===!1)return;u.event.onfocus(f,o)}v.updateZIndex(u.id)}},!1);n.contentWindow.document.addEventListener("keydown",function(n){var i=n||window.event||arguments.callee.caller.arguments[0],t=r.windows[r.focusId],u;i&&i.keyCode==27&&t&&r.destroy(r.focusId,{},!1,!0);i&&i.keyCode===13&&t&&t.buttons.length>0&&(t.buttonKey.toLowerCase()!=="enter"||i.ctrlKey?t.buttonKey.toLowerCase()==="ctrl+enter"&&i.ctrlKey&&(t.dialogType!=="prompt"?t.buttons[0].callback(t.id,r.getButton(t.id,t.buttons[0].id,i)):(u=r.getPromptTextArea(t.id),t.buttons[0].callback(t.id,(u?u.value:"").replace(/(^\s*)|(\s*$)/g,""),u,r.getButton(t.id,t.buttons[0].id,i)))):t.dialogType!=="prompt"?t.buttons[0].callback(t.id,r.getButton(t.id,t.buttons[0].id,i)):(u=r.getPromptTextArea(t.id),t.buttons[0].callback(t.id,(u?u.value:"").replace(/(^\s*)|(\s*$)/g,""),u,r.getButton(t.id,t.buttons[0].id,i))))},!1)}catch(y){s==="group"&&l&&l.parentNode.removeChild(l);console.warn(y)}finally{s==="group"?(c&&t.setAttribute("data-complete","1"),f.getAttribute("data-group-init")==="1"&&(o.loadingTextTimer&&(clearInterval(o.loadingTextTimer),delete o.loadingTextTimer),l&&l.parentNode.removeChild(l),i.isFunction(u.event.onload.after)&&u.event.onload.after(f,o))):(l&&l.parentNode.removeChild(l),o.loadingTextTimer&&(clearInterval(o.loadingTextTimer),delete o.loadingTextTimer),i.isFunction(u.event.onload.after)&&u.event.onload.after(f,o))}},createFrameBody:function(n,i,r,u,f,e,o){var h=this,s=document.createElement("iframe");s.setAttribute("id","layx-"+i.id+(f==="group"?"-"+e.id+"-":"-")+"iframe");s.classList.add("layx-iframe");s.classList.add("layx-flexbox");s.setAttribute("allowtransparency","true");s.setAttribute("frameborder","0");t.navigator.userAgent.toLowerCase().indexOf("iphone")>-1||!!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)?s.setAttribute("scrolling","no"):s.setAttribute("scrolling","auto");s.setAttribute("allowfullscreen","");s.setAttribute("mozallowfullscreen","");s.setAttribute("webkitallowfullscreen","");s.src=o!==!1?(f==="group"?e.url:i.url)||"about:blank":"about:blank";s.attachEvent?s.attachEvent("onreadystatechange",function(){(s.readyState==="complete"||s.readyState=="loaded")&&(s.detachEvent("onreadystatechange",arguments.callee),h.frameLoadHandle(s,n,i,r,u,f,e,o))}):s.addEventListener("load",function(){this.removeEventListener("load",arguments.call,!1);h.frameLoadHandle(s,n,i,r,u,f,e,o)},!1);o===!1&&n.setAttribute("data-preload","1");n.appendChild(s)},setContent:function(n,u,f){var l=this,p="layx-"+n,h=document.getElementById(p),e=l.windows[n],o,a,c,s,v,y;if(h&&e&&e.type==="html"&&(o=h.querySelector("#layx-"+n+"-html"),o)){if(i.isFunction(e.event.onload.before)&&(a=e.event.onload.before(h,e),a===!1))return;try{c=l.createContenLoadAnimate(o.parentNode,e.loadingText,e);f=i.isBoolean(f)?f:e.cloneElementContent;i.isDom(u)?(v=u.currentStyle?u.currentStyle:t.getComputedStyle(u,null),f===!1&&(r.cloneStore[n]={prev:u.previousSibling,parent:u.parentNode,next:u.nextSibling,display:v.display}),o.innerHTML="",s=o.appendChild(f===!0?u.cloneNode(!0):u)):o.innerHTML=u;i.isDom(s)&&(y=s.currentStyle?s.currentStyle:window.getComputedStyle(s,null),y.display==="none"&&(s.style.display=""));e.content=u}finally{c&&o.parentNode.removeChild(c);e.loadingTextTimer&&(clearInterval(e.loadingTextTimer),delete e.loadingTextTimer);i.isFunction(e.event.onload.after)&&e.event.onload.after(h,e)}}},getGroupFrame:function(n,t){for(var r={},i=0;i<n.length;i++)if(n[i].id===t){r=n[i];break}return r},reloadGroupFrame:function(n,t){var i=this,s="layx-"+n,f=document.getElementById(s),r=i.windows[n],e,u,o;f&&r&&r.type==="group"&&(e=i.getGroupFrame(r.frames,t),e.type==="url"&&(u=f.querySelector("#layx-"+n+"-"+t+"-iframe"),u&&(o=u.getAttribute("src"),i.setGroupUrl(n,t,o))))},setGroupContent:function(n,u,f,e){var a=this,b="layx-"+n,c=document.getElementById(b),o=a.windows[n],l,s,y,v,h,p,w;if(c&&o&&o.type==="group"&&(l=a.getGroupFrame(o.frames,u),l.type==="html"&&(s=c.querySelector("#layx-"+n+"-"+u+"-html"),s))){if(i.isFunction(o.event.onload.before)&&(y=o.event.onload.before(c,o),y===!1))return;try{v=a.createContenLoadAnimate(s.parentNode.parentNode,o.loadingText,o);e=i.isBoolean(e)?e:l.cloneElementContent;i.isDom(f)?(p=f.currentStyle?f.currentStyle:t.getComputedStyle(f,null),e===!1&&(r.cloneStore[n]||(r.cloneStore[n]={frames:{}}),r.cloneStore[n].frames[u]={prev:f.previousSibling,parent:f.parentNode,next:f.nextSibling,display:p.display}),s.innerHTML="",h=s.appendChild(e===!0?f.cloneNode(!0):f)):s.innerHTML=f;i.isDom(h)&&(w=h.currentStyle?h.currentStyle:window.getComputedStyle(h,null),w.display==="none"&&(h.style.display=""));l.content=f}finally{v&&s.parentNode.parentNode.removeChild(v);o.loadingTextTimer&&(clearInterval(o.loadingTextTimer),delete o.loadingTextTimer);i.isFunction(o.event.onload.after)&&o.event.onload.after(c,o)}}},createContenLoadAnimate:function(n,t,r,u){var h=this,f,e,s,o;if(t!==!1)return i.isArray(t)&&t.length===2&&t[0]===!0?h.createContenLoadAnimate(n,t[1],r,!1):(f=document.createElement("div"),f.classList.add("layx-content-shade"),f.classList.add("layx-flexbox"),f.classList.add("layx-flex-center"),i.isDom(t)?f.appendChild(t):(u!==!1&&f.appendChild(h.createLoadAnimate()),e=document.createElement("div"),e.classList.add("layx-load-content-msg"),e.innerHTML=t,f.appendChild(e),s=document.createElement("span"),s.classList.add("layx-dot"),e.appendChild(s),o=0,r.loadingTextTimer=setInterval(function(){var n,t;for(o===5&&(o=0),++o,n="",t=0;t<o;t++)n+=".";s.innerHTML=n},200)),n.appendChild(f))},setUrl:function(n,t){var u,o,h;t=t||"about:blank";var e=this,s="layx-"+n,f=document.getElementById(s),r=e.windows[n];if(f&&r&&r.type==="url"&&(u=f.querySelector("#layx-"+n+"-iframe"),u)){if(i.isFunction(r.event.onload.before)&&(o=r.event.onload.before(f,r),o===!1))return;h=e.createContenLoadAnimate(u.parentNode,r.loadingText,r);u.setAttribute("src",t)}},setGroupUrl:function(n,t,r){var s,f,h,l;r=r||"about:blank";var e=this,c="layx-"+n,o=document.getElementById(c),u=e.windows[n];if(o&&u&&u.type==="group"&&(s=e.getGroupFrame(u.frames,t),s.type==="url"&&(f=o.querySelector("#layx-"+n+"-"+t+"-iframe"),f))){if(i.isFunction(u.event.onload.before)&&(h=u.event.onload.before(o,u),h===!1))return;f.parentNode.removeAttribute("data-complete");l=e.createContenLoadAnimate(f.parentNode.parentNode,u.loadingText,u);f.setAttribute("src",r)}},setGroupTitle:function(n,t,i,r){var h=this,l="layx-"+n,e=document.getElementById(l),o=h.windows[n],u,s,c,f;if(e&&o&&o.type==="group"&&(u=e.querySelector(".layx-group-title[data-frameId='"+t+"']"),u)){if(s=h.getGroupFrame(o.frames,t),r===!0&&s.type==="url"){c=e.querySelector("#layx-"+n+"-"+t+"-iframe");try{i=c.contentDocument.querySelector("title").innerText}catch(a){}}f=u.querySelector(".layx-label");f&&(f.innerHTML=i,u.setAttribute("title",f.innerHTML),s.title=i)}},setTitle:function(n,t,i){var s=this,h="layx-"+n,f=document.getElementById(h),e=s.windows[n],r,o,u;if(f&&e&&(r=f.querySelector(".layx-title"),r)){if(i===!0&&e.type==="url"){o=f.querySelector("#layx-"+n+"-iframe");try{t=o.contentDocument.querySelector("title").innerText}catch(c){}}u=r.querySelector(".layx-label");u&&(u.innerHTML=t,r.setAttribute("title",u.innerHTML),e.title=t)}},stickToggle:function(n){var f=this,o="layx-"+n,u=document.getElementById(o),t=f.windows[n],e,r;if(u&&t){if(f.updateZIndex(n),i.isFunction(t.event.onstick.before)&&(e=t.event.onstick.before(u,t),e===!1))return;t.isStick=!t.isStick;r=u.querySelector(".layx-stick-menu");r&&(r.setAttribute("data-enable",t.isStick?"1":"0"),t.isStick?r.setAttribute("title","取消置顶"):r.setAttribute("title","置顶"));f.updateZIndex(n);i.isFunction(t.event.onstick.after)&&t.event.onstick.after(u,t)}},reloadFrame:function(n){var i=this,e="layx-"+n,r=document.getElementById(e),u=i.windows[n],t,f;r&&u&&u.type==="url"&&(t=r.querySelector("#layx-"+n+"-iframe"),t&&(f=t.getAttribute("src"),i.setUrl(n,f)))},restore:function(n){var e=this,c="layx-"+n,t=document.getElementById(c),r=e.windows[n],h,f,u,o,s;if(t&&r){if(r.restorable!==!0)return;if(e.updateZIndex(n),i.isFunction(r.event.onrestore.before)&&(h=r.event.onrestore.before(t,r),h===!1))return;f=r.area;r.status==="normal"?e.max(n):r.status==="max"&&(document.body.classList.contains("ilayx-body")&&document.body.classList.remove("ilayx-body"),t.style.top=f.top+"px",t.style.left=f.left+"px",t.style.width=f.width+"px",t.style.height=f.height+"px",t.classList.remove("layx-max-statu"),r.status="normal",u=t.querySelector(".layx-restore-menu[data-menu='max']"),u&&(u.classList.remove("layx-restore-menu"),u.classList.add("layx-max-menu"),u.setAttribute("title","最大化"),u.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-max"><\/use><\/svg>'),o=t.querySelector(".layx-resizes"),o&&o.removeAttribute("data-enable"));r.status==="min"&&(r.minBefore==="normal"?(t.style.top=f.top+"px",t.style.left=f.left+"px",t.style.width=f.width+"px",t.style.height=f.height+"px",r.status="normal",u=t.querySelector(".layx-restore-menu[data-menu='min']"),u&&(u.classList.remove("layx-restore-menu"),u.classList.add("layx-min-menu"),u.setAttribute("title","最小化"),u.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-min"><\/use><\/svg>'),o=t.querySelector(".layx-resizes"),o&&o.removeAttribute("data-enable")):r.minBefore==="max"&&e.max(n),e.updateMinLayout());s=layxDeepClone({},{},r);delete e.windows[n];e.windows[n]=s;e.updateMinLayout();t.classList.contains("layx-min-statu")&&t.classList.remove("layx-min-statu");i.isFunction(s.event.onrestore.after)&&s.event.onrestore.after(t,s)}},min:function(n){var e=this,c="layx-"+n,r=document.getElementById(c),t=e.windows[n],s,l,u,o,f,h;if(r&&t&&t.isFloatTarget===!1){if(t.minable!==!0||t.status==="min")return;if(e.updateZIndex(n),i.isFunction(t.event.onmin.before)&&(s=t.event.onmin.before(r,t),s===!1))return;l=i.innerArea();t.minBefore=t.status;t.status="min";u=r.querySelector(".layx-min-menu");u&&(u.classList.remove("layx-max-menu"),u.classList.add("layx-restore-menu"),u.setAttribute("title","还原"),u.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-restore"><\/use><\/svg>');o=r.querySelector(".layx-resizes");o&&o.setAttribute("data-enable","0");f=r.querySelector(".layx-restore-menu[data-menu='max']");f&&(f.classList.remove("layx-restore-menu"),f.classList.add("layx-max-menu"),f.setAttribute("title","最大化"),f.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-max"><\/use><\/svg>');r.classList.contains("layx-max-statu")&&r.classList.remove("layx-max-statu");h=layxDeepClone({},t);delete e.windows[n];e.windows[n]=h;e.updateMinLayout();document.body.classList.contains("ilayx-body")&&document.body.classList.remove("ilayx-body");i.isFunction(t.event.onmin.after)&&t.event.onmin.after(r,t)}},updateZIndex:function(n){var i=this,e="layx-"+n,f=document.getElementById(e),t=i.windows[n],u;f&&t&&(t.dialogType!=="load"&&t.dialogType!=="msg"&&(r.focusId=n),t.focusToReveal===!0&&(u=document.getElementById("layx-"+n+"-shade"),u&&(u.style.zIndex=t.isStick===!0?++i.stickZIndex:++i.zIndex),t.zIndex=t.isStick===!0?++i.stickZIndex+1:++i.zIndex+1,f.style.zIndex=t.zIndex))},updateMinLayout:function(){var a=this,s=a.windows,h=i.innerArea(),t=10,r=240,u=0,c=Math.floor(h.width/(r+t)),f,l,n,e,o;for(f in s)l=s[f],n=document.getElementById("layx-"+f),n&&l.status==="min"&&(e=n.querySelector(".layx-control-bar"),e&&(o=e.offsetHeight,n.classList.add("layx-min-statu"),n.style.width=r+"px",n.style.height=o+"px",n.style.top=h.height-(Math.floor(u/c)+1)*(o+10)+"px",n.style.left=u%c*(r+t)+t+"px",u++))},max:function(n){var e=this,l="layx-"+n,t=document.getElementById(l),r=e.windows[n],o=i.innerArea(),h,u,s,f,c;if(t&&r&&r.isFloatTarget===!1){if(r.maxable!==!0)return;if(r.status==="max")t.style.top=0,t.style.left=0,t.style.width=o.width+"px",t.style.height=o.height+"px";else{if(e.updateZIndex(n),i.isFunction(r.event.onmax.before)&&(h=r.event.onmax.before(t,r),h===!1))return;document.body.classList.add("ilayx-body");t.style.top=0;t.style.left=0;t.style.width=o.width+"px";t.style.height=o.height+"px";t.classList.add("layx-max-statu");r.status="max";u=t.querySelector(".layx-max-menu");u&&(u.classList.remove("layx-max-menu"),u.classList.add("layx-restore-menu"),u.setAttribute("title","还原"),u.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-restore"><\/use><\/svg>');s=t.querySelector(".layx-resizes");s&&s.setAttribute("data-enable","0");f=t.querySelector(".layx-restore-menu[data-menu='min']");f&&(f.classList.remove("layx-restore-menu"),f.classList.add("layx-min-menu"),f.setAttribute("title","最小化"),f.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-min"><\/use><\/svg>');c=layxDeepClone({},r);delete e.windows[n];e.windows[n]=c;e.updateMinLayout();t.classList.contains("layx-min-statu")&&t.classList.remove("layx-min-statu");i.isFunction(r.event.onmax.after)&&r.event.onmax.after(t,r)}}},visual:function(n,t,r,u){var o=this,s="layx-"+n,e=document.getElementById(s),c=document.getElementById(s+"-shade"),f=o.windows[n],h;if(e&&f){if(i.isFunction(f.event.onvisual.before)&&(h=f.event.onvisual.before(e,f,r||{},u===!0,t!==!1),h===!1))return;t!==!1?e.classList.remove("layx-hide-statu"):e.classList.add("layx-hide-statu");o.updateMinLayout();i.isFunction(f.event.onvisual.after)&&f.event.onvisual.after(e,f,t!==!1)}},destroyInlay:function(n){var t=this;t.destroy(n,null,!0)},destroy:function(n,t,u,f,e){var l=this,w="layx-"+n,a=document.getElementById(w),y=document.getElementById(w+"-shade"),o=l.windows[n],b,s,p,c,v,h,k;if(a&&o){if(o.escKey===!1&&f===!0)return;if(l.updateZIndex(n),i.isFunction(o.event.ondestroy.before)&&(b=o.event.ondestroy.before(a,o,t||{},u===!0,f===!0),e!==!0&&b===!1))return;if(o.closable!==!0)return;if(s=l.cloneStore[n],o.type==="html"&&s&&(v=a.querySelector("#layx-"+n+"-html"),v&&(h=v.children[0],h&&h.style&&(h.style.display=s.display),s.prev?setTimeout(function(){i.insertAfter(h,s.prev)},0):setTimeout(function(){s.parent&&s.parent.insertBefore(h,s.next)},0))),o.type==="group"&&s&&s&&s.frames)for(p in s.frames)c=s.frames[p],v=a.querySelector("#layx-"+n+"-"+p+"-html"),v&&(h=v.children[0],h&&h.style&&(h.style.display=c.display),c.prev?setTimeout(function(){i.insertAfter(h,c.prev)},0):setTimeout(function(){c.parent&&c.parent.insertBefore(h,c.next)},0));r.focusId=r.prevFocusId;delete l.cloneStore[n];delete l.windows[n];document.body.classList.contains("ilayx-body")&&document.body.classList.remove("ilayx-body");a.parentNode.removeChild(a);y&&y.parentNode.removeChild(y);l.updateMinLayout();i.isFunction(o.event.ondestroy.after)&&o.event.ondestroy.after();o.destroyTimer&&clearInterval(o.destroyTimer);o.loadTimer&&clearInterval(o.loadTimer);o.loadingTextTimer&&clearInterval(o.loadingTextTimer);for(k in o)delete o[k];o=undefined}},destroyAll:function(){var n=this;for(var t in r.windows)n.destroy(t)},flicker:function(n){var i=this,r,u="layx-"+n,t=document.getElementById(u),f=i.windows[n];t&&f&&(i.updateZIndex(n),t.classList.contains("layx-flicker")&&t.classList.remove("layx-flicker"),t.classList.add("layx-flicker"),r=setTimeout(function(){t.classList.remove("layx-flicker");clearTimeout(r)},960))},setPosition:function(n,t,r){var o=this,s="layx-"+n,e=document.getElementById(s),u=o.windows[n],f;e&&u&&(f=r===!0?t:i.compileLayxPosition(u.area.width,u.area.height,t),u.area.left=f.left,u.area.top=f.top,u.storeStatus===!0&&o.storeWindowAreaInfo(n,u.area),e.style.left=f.left+"px",e.style.top=f.top+"px")},setSize:function(n,t){var u=this,s="layx-"+n,f=document.getElementById(s),r=u.windows[n],e,o;f&&r&&t&&(t.width&&(e=i.compileLayxWidthOrHeight("width",t.width,u.defaults.width),r.area.width=e,f.style.width=e+"px"),t.height&&(o=i.compileLayxWidthOrHeight("height",t.height,u.defaults.height),r.area.height=o,f.style.height=o+"px"),r.storeStatus===!0&&u.storeWindowAreaInfo(n,r.area))},getFrameContext:function(n){var f=this,e="layx-"+n,i=document.getElementById(e),r=f.windows[n],u=null,t;if(i&&r&&r.type==="url"&&(t=i.querySelector(".layx-iframe"),t))try{u=t.contentWindow}catch(o){}return u},getParentContext:function(n){var i=this,t=i.getFrameContext(n);return t?t.parent:null},getGroupFrameContext:function(n,t){var u=this,s="layx-"+n,f=document.getElementById(s),i=u.windows[n],e=null,o,r;if(f&&i&&i.type==="group"&&(o=u.getGroupFrame(i.frames,t),o.type==="url"&&(r=f.querySelector("#layx-"+n+"-"+t+"-iframe"),r)))try{e=r.contentWindow}catch(h){}return e},createLayxButtons:function(n,t,r){var o=this,h=document.createElement("div"),e,f,u,s;for(h.classList.add("layx-buttons"),e=0;e<n.length;e++){if(f=document.createElement("button"),u=layxDeepClone({},o.defaultButtons,n[e]),f.classList.add("layx-button-item"),f.setAttribute("title",u.label),f.innerText=u.label,u.id&&f.setAttribute("id","layx-"+t+"-button-"+u.id),i.isArray(u.classes))for(s=0;s<u.classes.length;s++)f.classList.add(u.classes[s]);else u.classes&&f.classList.add(u.classes.toString());u.style&&f.setAttribute("style",u.style);f.callback=n[e].callback;f.onclick=function(n){if(n=n||window.event||arguments.callee.caller.arguments[0],i.isFunction(this.callback))if(r===!0){var u=o.getPromptTextArea(t);o.updateZIndex(t);this.callback(t,(u?u.value:"").replace(/(^\s*)|(\s*$)/g,""),u,this,n)}else o.updateZIndex(t),this.callback(t,this,n)};h.appendChild(f)}return h},setButtonStatus:function(n,t,i){var f=this,e="layx-"+n,u=document.getElementById(e),o=f.windows[n],r;u&&o&&(r=u.querySelector("#layx-"+n+"-button-"+t),r&&(i===!1?r.setAttribute("disabled","disabled"):r.removeAttribute("disabled")))},getStrSizeRange:function(n,t,i,r,u,f){var o=0,s=0,e=document.createElement("span");return e.innerHTML=n,e.classList.add("layx-calc-text"),e.style.visibility="hidden",e.style.display="inline-block",e.style.minWidth=t+"px",e.style.minHeight=i+"px",e.style.maxWidth=r+"px",e.style.maxHeight=u+"px",e.style.paddingLeft="10px",e.style.paddingRight="10px",e.style.paddingTop="10px",e.style.paddingBottom="10px",e.style.margin="0",e.style.border="none",e.style.lineHeight=1.5,document.body.appendChild(e),o=e.offsetWidth,s=e.offsetHeight+1,document.body.removeChild(e),{width:o+(f===!0?45:0),height:s}},getButton:function(n,t){var r=this,u="layx-"+n,i=document.getElementById(u),f=r.windows[n];return i&&f?i.querySelector("#layx-"+n+"-button"+(t?"-"+t:"")):null},tip:function(n,t,r,u){var f=this,e;i.isDom(t)&&(e=u&&u.id?u.id:"layx-dialog-tip-"+i.rndNum(8),t.addEventListener("mouseover",function(){var i=f.getStrSizeRange(n,20,20,320,90,u&&u.dialogIcon?!0:!1);f.create(layxDeepClone({},{id:e,type:"html",control:!1,content:f.createDialogContent("tip",n,u&&u.dialogIcon?u.dialogIcon:!1),width:i.width,height:i.height,minHeight:i.height,minWidth:i.width,stickMenu:!1,minMenu:!1,floatTarget:t,floatDirection:r||"bottom",maxMenu:!1,closeMenu:!1,alwaysOnTop:!0,resizable:!1,movable:!1,allowControlDbclick:!1,autodestroyText:!1,loadingText:!1,storeStatus:!1},u))},!1),t.addEventListener("mouseout",function(){f.destroy(e,null,!0)},!1))},msg:function(n,t){var r=this,u=r.getStrSizeRange(n,120,20,320,90,t&&t.dialogIcon?!0:!1),f=r.create(layxDeepClone({},{id:t&&t.id?t.id:"layx-dialog-msg-"+i.rndNum(8),type:"html",control:!1,content:r.createDialogContent("msg",n,t&&t.dialogIcon?t.dialogIcon:!1),autodestroy:5e3,width:u.width,height:u.height,minHeight:u.height,stickMenu:!1,minMenu:!1,maxMenu:!1,closeMenu:!1,alwaysOnTop:!0,resizable:!1,movable:!1,allowControlDbclick:!1,position:[10,"tc"],autodestroyText:!1,loadingText:!1,storeStatus:!1,dialogType:"msg"},t));return r.flicker(f.id),f},createDialogContent:function(n,t,i){var o=this,u=document.createElement("div"),e,r,f;if(u.classList.add("layx-dialog-"+n),u.classList.add("layx-flexbox"),i){e=document.createElement("div");e.classList.add("layx-dialog-icon");r=document.createElement("div");r.classList.add("layx-icon");r.classList.add("layx-dialog-icon-"+i);switch(i){case"success":r.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-right"><\/use><\/svg>';break;case"warn":r.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-warn"><\/use><\/svg>';break;case"error":r.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-error"><\/use><\/svg>';break;case"help":r.innerHTML='<svg class="layx-iconfont" aria-hidden="true"><use xlink:href="#layx-icon-help"><\/use><\/svg>'}e.appendChild(r);u.appendChild(e)}return f=document.createElement("div"),f.classList.add("layx-dialog-content"),f.classList.add("layx-flexauto"),f.innerHTML=t,u.appendChild(f),u},alert:function(n,t,u,f){var e=this,o=e.getStrSizeRange(t,137,66,352,157,f&&f.dialogIcon?!0:!1);return e.create(layxDeepClone({},{id:f&&f.id?f.id:"layx-dialog-alert-"+i.rndNum(8),title:n||"提示消息",icon:!1,type:"html",content:e.createDialogContent("alert",t,f&&f.dialogIcon?f.dialogIcon:!1),width:o.width+20,height:o.height+73,minHeight:o.height+73,stickMenu:!1,dialogType:"alert",minMenu:!1,minable:!1,maxMenu:!1,maxable:!1,alwaysOnTop:!0,resizable:!1,allowControlDbclick:!1,shadable:!0,statusBar:!0,buttons:[{label:"确定",callback:function(n,t,f){if(f=f||window.event||arguments.callee.caller.arguments[0],f.stopPropagation(),i.isFunction(u)){var e=u(n,t,f);e!==!1&&r.destroy(n)}else r.destroy(n)}}],position:"ct",loadingText:!1,storeStatus:!1},f))},confirm:function(n,t,u,f){var e=this,o=e.getStrSizeRange(t,180,137,352,180,f&&f.dialogIcon?!0:!1);return e.create(layxDeepClone({},{id:f&&f.id?f.id:"layx-dialog-confirm-"+i.rndNum(8),title:n||"询问消息",icon:!1,type:"html",content:e.createDialogContent("confirm",t,f&&f.dialogIcon?f.dialogIcon:!1),width:o.width+20,height:o.height,minHeight:o.height,stickMenu:!1,dialogType:"confirm",minMenu:!1,minable:!1,maxMenu:!1,maxable:!1,alwaysOnTop:!0,resizable:!1,allowControlDbclick:!1,shadable:!0,buttons:[{label:"确定",callback:function(n,t,f){if(f=f||window.event||arguments.callee.caller.arguments[0],f.stopPropagation(),i.isFunction(u)){var e=u(n,t);e!==!1&&r.destroy(n)}}},{label:"取消",callback:function(n,t,i){i=i||window.event;i.stopPropagation();r.destroy(n)}}],statusBar:!0,position:"ct",loadingText:!1,storeStatus:!1},f))},getPromptTextArea:function(n){var f=this,e="layx-"+n,r=document.getElementById(e),u=f.windows[n],t,i;return r&&u&&u.type==="html"&&(t=r.querySelector(".layx-dialog-prompt"),t&&(i=t.querySelector(".layx-textarea"),i))?i:null},prompt:function(n,t,u,f,e){var o=this,s=o.getStrSizeRange(t,200,184,352,200);return o.create(layxDeepClone({},{id:e&&e.id?e.id:"layx-dialog-prompt-"+i.rndNum(8),title:n||"请输入信息",icon:!1,type:"html",content:o.createDialogContent("prompt","<label>"+t+"<\/label><textarea class='layx-textarea'>"+(f?f.toString():"")+"<\/textarea>"),width:s.width+20,height:s.height,minHeight:s.height,stickMenu:!1,dialogType:"prompt",minMenu:!1,minable:!1,maxMenu:!1,maxable:!1,alwaysOnTop:!0,resizable:!1,allowControlDbclick:!1,shadable:!0,statusBar:!0,buttonKey:"ctrl+enter",buttons:[{label:"确定",callback:function(n,t,f,e,o){if(o=o||window.event||arguments.callee.caller.arguments[0],o.stopPropagation(),f&&t.length===0)f.focus();else if(i.isFunction(u)){var s=u(n,t,f,e,o);s!==!1&&r.destroy(n)}}},{label:"取消",callback:function(n,t,i,u,f){f=f||window.event;f.stopPropagation();r.destroy(n)}}],position:"ct",loadingText:!1,storeStatus:!1},e))},createLoadAnimate:function(){var t=document.createElement("div"),n,r,u,f,i;return t.classList.add("layx-load-animate"),n=document.createElement("div"),n.classList.add("layx-load-inner"),r=document.createElement("div"),r.classList.add("layx-load-spiner"),n.appendChild(r),u=document.createElement("div"),u.classList.add("layx-load-filler"),n.appendChild(u),f=document.createElement("div"),f.classList.add("layx-load-masker"),n.appendChild(f),t.appendChild(n),i=n.cloneNode(!0),i.classList.remove("layx-load-inner"),i.classList.add("layx-load-inner2"),t.appendChild(i),t},load:function(n,t,r){var s=this,h=s.getStrSizeRange(t,120,53,320,90),u=document.createElement("div"),f,e;u.classList.add("layx-dialog-load");u.classList.add("layx-flexbox");u.classList.add("layx-flex-center");u.appendChild(s.createLoadAnimate());f=document.createElement("div");f.classList.add("layx-load-msg");f.innerHTML=t;u.appendChild(f);e=document.createElement("span");e.classList.add("layx-dot");f.appendChild(e);var o=0,l=setInterval(function(){var n,t;for(o===5&&(o=0),++o,n="",t=0;t<o;t++)n+=".";e.innerHTML=n},200),c=s.create(layxDeepClone({},{id:n?n:"layx-dialog-load-"+i.rndNum(8),type:"html",control:!1,shadable:!0,content:u,cloneElementContent:!1,width:h.width+70,height:h.height,minHeight:h.height,stickMenu:!1,minMenu:!1,maxMenu:!1,closeMenu:!1,escKey:!1,alwaysOnTop:!0,resizable:!1,movable:!1,allowControlDbclick:!1,position:"ct",loadingText:!1,storeStatus:!1,dialogType:"load"},r));return c.loadTimer=l,c}};String.prototype.toFirstUpperCase=function(){return this.replace(/^\S/,function(n){return n.toUpperCase()})};"classList"in document.documentElement||Object.defineProperty(HTMLElement.prototype,"classList",{get:function(){function t(t){return function(i){var r=n.className.split(/\s+/g),u=r.indexOf(i);t(r,u,i);n.className=r.join(" ")}}var n=this;return{add:t(function(n,t,i){~t||n.push(i)}),remove:t(function(n,t){~t&&n.splice(t,1)}),toggle:t(function(n,t,i){~t?n.splice(t,1):n.push(i)}),contains:function(t){return!!~n.className.split(/\s+/g).indexOf(t)},item:function(t){return n.className.split(/\s+/g)[t]||null}}}});var e={resolution:0,iframes:[],interval:null,Iframe:function(){this.element=arguments[0];this.cb=arguments[1];this.hasTracked=!1},track:function(n,t){if(this.iframes.push(new this.Iframe(n,t)),!this.interval){var i=this;this.interval=setInterval(function(){i.checkClick()},this.resolution)}},checkClick:function(){var i,n;if(document.activeElement){i=document.activeElement;for(n in this.iframes)i===this.iframes[n].element?this.iframes[n].hasTracked==!1&&(this.iframes[n].cb.apply(t,[]),this.iframes[n].hasTracked=!0):this.iframes[n].hasTracked=!1}}},i={isSupportTouch:"ontouchstart"in document?!0:!1,isSupportMouse:"onmouseup"in document?!0:!1,IsPC:function(){for(var r=navigator.userAgent,t=["Android","iPhone","SymbianOS","Windows Phone","iPad","iPod"],i=!0,n=0;n<t.length;n++)if(r.indexOf(t[n])>0){i=!1;break}return i},isBoolean:function(n){return typeof n=="boolean"},isString:function(n){return typeof n=="string"},isNumber:function(n){return typeof n=="number"},isArray:function(n){return Object.prototype.toString.call(n)=="[object Array]"},isFunction:function(n){return n&&Object.prototype.toString.call(n)==="[object Function]"},isDom:function(n){return!!(n&&typeof window!="undefined"&&(n===window||n.nodeType))},insertAfter:function(n,t){var i=t.parentNode;n&&(i.lastChild==t?i.appendChild(n):i.insertBefore(n,t.nextSibling))},innerArea:function(){return{width:t.innerWidth,height:t.innerHeight}},getCross:function(n,t,i){return(t.x-n.x)*(i.y-n.y)-(i.x-n.x)*(t.y-n.y)},IsPointInMatrix:function(n,t){var i=this,r=n.p1,u=n.p2,f=n.p3,e=n.p4;return i.getCross(r,u,t)*i.getCross(f,e,t)>=0&&i.getCross(u,f,t)*i.getCross(e,r,t)>=0},checkElementIsVisual:function(n,t,i){var f=this,o=f.innerArea(),e=f.getElementPos(n),s={x:e.x+n.offsetWidth,y:e.y+n.offsetHeight},r=f.getElementPos(t),u={x:r.x+t.offsetWidth,y:r.y+t.offsetHeight};if(i===!1){var h={p1:{x:e.x,y:s.y},p2:{x:e.x,y:e.y},p3:{x:s.x,y:e.y},p4:{x:s.x,y:s.y}},c={p1:{x:0,y:o.height},p2:{x:0,y:0},p3:{x:o.width,y:0},p4:{x:o.width,y:o.height}},l=f.IsPointInMatrix(h,{x:r.x,y:r.y}),a=f.IsPointInMatrix(h,{x:u.x,y:r.y}),v=f.IsPointInMatrix(h,{x:r.x,y:u.y}),y=f.IsPointInMatrix(h,{x:u.x,y:u.y}),p=f.IsPointInMatrix(c,{x:r.x,y:r.y}),w=f.IsPointInMatrix(c,{x:u.x,y:r.y}),b=f.IsPointInMatrix(c,{x:r.x,y:u.y}),k=f.IsPointInMatrix(c,{x:u.x,y:u.y});return(l||a||v||y)&&(p||w||b||k)}return r.x>=e.x&&u.x<=s.x&&r.y>=e.y&&u.y<=s.y&&r.x>=0&&u.x<=o.width&&r.y>=0&&u.y<=o.height},compilebubbleDirection:function(n,t,i,r){var s=this,f=s.getElementPos(t),e=s.innerArea(),o=11,u={top:0,left:0};n=["top","bottom","left","right"].indexOf(n)>-1?n:"bottom";switch(n){case"bottom":u.top=f.y+t.offsetHeight+o;u.left=f.x;f.x+i>=e.width&&(u.left=e.width-i);break;case"top":u.top=f.y-(r+o);u.left=f.x;f.x+i>=e.width&&(u.left=e.width-i);break;case"right":u.top=f.y;u.left=f.x+t.offsetWidth+o;f.y+r>=e.height&&(u.top=e.height-r);break;case"left":u.top=f.y;u.left=f.x-(i+o);f.y+r>=e.height&&(u.top=e.height-r)}return u},compileLayxPosition:function(n,t,i){var f=this,u=f.innerArea(),r={top:0,left:0};if(f.isArray(i)&&i.length===2)r.top=f.isNumber(i[0])?i[0]:f.compileLayxPosition(n,t,i[0]).top,r.left=f.isNumber(i[1])?i[1]:f.compileLayxPosition(n,t,i[1]).left;else{i=["ct","lt","rt","lb","rb","lc","tc","rc","bc"].indexOf(i.toString())>-1?i.toString():"ct";switch(i){case"ct":r.top=(u.height-t)/2;r.left=(u.width-n)/2;break;case"lt":r.top=0;r.left=0;break;case"rt":r.top=0;r.left=u.width-n;break;case"lb":r.top=u.height-t;r.left=0;break;case"rb":r.top=u.height-t;r.left=u.width-n;break;case"lc":r.left=0;r.top=(u.height-t)/2;break;case"tc":r.top=0;r.left=(u.width-n)/2;break;case"rc":r.left=u.width-n;r.top=(u.height-t)/2;break;case"bc":r.top=u.height-t;r.left=(u.width-n)/2}}return r},rndNum:function(n){for(var t="",i=0;i<n;i++)t+=Math.floor(Math.random()*10);return t},compileLayxWidthOrHeight:function(n,t,i){var f=this,r=f.innerArea(),u;if(/(^[1-9]\d*$)/.test(t))return Number(t);if(/^(100|[1-9]?\d(\.\d\d?)?)%$/.test(t)){if(u=Number(t.toString().replace("%","")),n==="width")return r.width*(u/100);if(n==="height")return r.height*(u/100)}if(/^[1-9]\d*v[hw]$/.test(t)){if(n==="width")return r.width*parseFloat(t)/100;if(n==="height")return r.height*parseFloat(t)/100}return i},getNodeByClassName:function(n,i,r){var u,f;return(r=r||t,u=this,n===r.document.body)?null:(f=n.classList,f.contains(i)?n:u.getNodeByClassName(n.parentNode,i))},getMousePosition:function(n){var t;if(n=n||window.event,n.touches){if(i.IsPC()&&(t=n.button||n.which,t==1&&n.shiftKey==!1)){var r=document.documentElement.scrollLeft||document.body.scrollLeft,u=document.documentElement.scrollTop||document.body.scrollTop,f=n.pageX||n.clientX+r,e=n.pageY||n.clientY+u;return{x:f,y:e}}return{x:n.touches[0].clientX,y:n.touches[0].clientY}}var r=document.documentElement.scrollLeft||document.body.scrollLeft,u=document.documentElement.scrollTop||document.body.scrollTop,f=n.pageX||n.clientX+r,e=n.pageY||n.clientY+u;return{x:f,y:e}},getElementPos:function(n){var u=navigator.userAgent.toLowerCase(),h=u.indexOf("opera")!=-1,c=u.indexOf("msie")!=-1&&!h,t,i,r,f,e,o,s;if(n.parentNode===null||n.style.display=="none")return!1;if(t=null,i=[],n.getBoundingClientRect)return r=n.getBoundingClientRect(),f=Math.max(document.documentElement.scrollTop,document.body.scrollTop),e=Math.max(document.documentElement.scrollLeft,document.body.scrollLeft),{x:r.left+e,y:r.top+f};if(document.getBoxObjectFor)r=document.getBoxObjectFor(n),o=n.style.borderLeftWidth?parseInt(n.style.borderLeftWidth):0,s=n.style.borderTopWidth?parseInt(n.style.borderTopWidth):0,i=[r.x-o,r.y-s];else{if(i=[n.offsetLeft,n.offsetTop],t=n.offsetParent,t!=n)while(t)i[0]+=t.offsetLeft,i[1]+=t.offsetTop,t=t.offsetParent;(u.indexOf("opera")!=-1||u.indexOf("safari")!=-1&&n.style.position=="absolute")&&(i[0]-=document.body.offsetLeft,i[1]-=document.body.offsetTop)}for(t=n.parentNode?n.parentNode:null;t&&t.tagName!="BODY"&&t.tagName!="HTML";)i[0]-=t.scrollLeft,i[1]-=t.scrollTop,t=t.parentNode?t.parentNode:null;return{x:i[0],y:i[1]}}},u=function(n,f,e,o,s){u.isResizing=!1;u.isFirstResizing=!0;var h=function(t){var y,w;t=t||window.event;var p=i.getMousePosition(t),a=p.x-n.mouseStartCoord.x,v=p.y-n.mouseStartCoord.y;if(i.isSupportTouch){if(t.cancelable&&(t.defaultPrevented||t.preventDefault()),((a!==0||v!==0)&&new Date-n.touchDate>100)==!1)return;if(i.IsPC()){if(y=t.button||t.which,(y==1&&t.shiftKey==!1)==!1)return;if(t.defaultPrevented||t.preventDefault(),(a!==0||v!==0)==!1)return}}else{if(y=t.button||t.which,(y==1&&t.shiftKey==!1)==!1)return;if(t.defaultPrevented||t.preventDefault(),(a!==0||v!==0)==!1)return}var r=n.winform.area.top+v,h=n.winform.area.left+a,c=f?n.winform.area.height-v:n.winform.area.height+v,l=e?n.winform.area.width-a:n.winform.area.width+a;if(u.isResizing=!0,u.isFirstResizing===!0&&(u.isFirstResizing=!1,i.isFunction(n.winform.event.onresize.before)&&(w=n.winform.event.onresize.before(n.layxWindow,n.winform),w===!1))){u.isResizing=!1;u.isFirstResizing=!0;i.isSupportTouch?(document.ontouchend=null,document.ontouchmove=null,i.IsPC()&&(document.onmouseup=null,document.onmousemove=null)):(document.onmouseup=null,document.onmousemove=null);return}l=Math.max(l,n.winform.area.minWidth);e?(h=Math.min(h,n.winform.area.left+n.winform.area.width-n.winform.area.minWidth),h=Math.max(0,h),l=Math.min(l,n.winform.area.left+n.winform.area.width)):(h=Math.min(h,n.winform.area.left),h=Math.max(n.winform.area.left,h),l=Math.min(l,n.innerArea.width-n.winform.area.left));c=Math.max(c,n.winform.area.minHeight);f?(r=Math.min(r,n.winform.area.top+n.winform.area.height-n.winform.area.minHeight),r=Math.max(0,r),c=Math.min(c,n.winform.area.top+n.winform.area.height)):(r=Math.min(r,n.winform.area.top),r=Math.max(n.winform.area.top,r),c=Math.min(c,n.innerArea.height-n.winform.area.top));s&&(n.layxWindow.style.width=l+"px",n.layxWindow.style.left=h+"px");o&&(n.layxWindow.style.top=r+"px",n.layxWindow.style.height=c+"px");s===!1&&o===!1&&(n.layxWindow.style.width=l+"px",n.layxWindow.style.left=h+"px",n.layxWindow.style.top=r+"px",n.layxWindow.style.height=c+"px");i.isFunction(n.winform.event.onresize.progress)&&n.winform.event.onresize.progress(n.layxWindow,n.winform)},c=function(t){var h,s,f,e,o;if(t=t||window.event,i.isSupportTouch){if(document.ontouchend=null,document.ontouchmove=null,i.IsPC()){if(h=t.button||t.which,h==1&&t.shiftKey==!1)for(s=n.layxWindow.querySelectorAll(".layx-resizes > div"),f=0;f<s.length;f++)s[f].classList.add("layx-reisize-touch");document.onmouseup=null;document.onmousemove=null}}else document.onmouseup=null,document.onmousemove=null;e=n.layxWindow.querySelector(".layx-mouse-preventDefault");e&&e.parentNode.removeChild(e);o=document.getElementById("layx-window-move");o&&o.parentNode.removeChild(o);u.isResizing===!0&&(u.isResizing=!1,u.isFirstResizing=!0,n.winform.area.top=n.layxWindow.offsetTop,n.winform.area.left=n.layxWindow.offsetLeft,n.winform.area.width=n.layxWindow.offsetWidth,n.winform.area.height=n.layxWindow.offsetHeight,n.winform.storeStatus===!0&&r.storeWindowAreaInfo(n.winform.id,{top:n.winform.area.top,left:n.winform.area.left,width:n.winform.area.width,height:n.winform.area.height}),i.isFunction(n.winform.event.onresize.after)&&n.winform.event.onresize.after(n.layxWindow,n.winform))},l=function(u){var f,l,e,o,p,s,v,w,y,a;if(u=u||window.event,f=i.getNodeByClassName(n,"layx-window",t),f&&(l=f.getAttribute("id").substr(5),e=r.windows[l],e))if(e.status!=="min"&&e.resizable===!0)if(o=document.getElementById("layx-window-move"),o||(o=document.createElement("div"),o.setAttribute("id","layx-window-move"),document.body.appendChild(o)),r.updateZIndex(l),o.style.zIndex=e.zIndex-1,p=i.getMousePosition(u),n.mouseStartCoord=p,n.layxWindow=f,n.winform=e,n.innerArea=i.innerArea(),n.touchDate=new Date,s=f.querySelector(".layx-mouse-preventDefault"),s||(s=document.createElement("div"),s.classList.add("layx-mouse-preventDefault"),v=f.querySelector(".layx-main"),v&&v.appendChild(s)),i.isSupportTouch){if(document.ontouchend=c,document.ontouchmove=h,i.IsPC()){if(w=u.button||u.which,w==1&&u.shiftKey==!1)for(y=f.querySelectorAll(".layx-resizes > div"),a=0;a<y.length;a++)y[a].classList.remove("layx-reisize-touch");document.onmouseup=c;document.onmousemove=h}}else document.onmouseup=c,document.onmousemove=h;else r.restore(l);return!1};i.isSupportTouch?(n.ontouchstart=l,i.IsPC()&&(n.onmousedown=l)):n.onmousedown=l},f=function(n){f.isMoveing=!1;f.isFirstMoveing=!0;var u=function(t){var c,l,u,o;t=t||window.event;var e=i.getMousePosition(t),s=e.x-n.mouseStartCoord.x,h=e.y-n.mouseStartCoord.y;if(i.isSupportTouch){if(t.cancelable&&(t.defaultPrevented||t.preventDefault()),((s!==0||h!==0)&&new Date-n.touchDate>100)==!1)return;if(i.IsPC()){if(c=t.button||t.which,(c==1&&t.shiftKey==!1)==!1)return;if(t.defaultPrevented||t.preventDefault(),(s!==0||h!==0)==!1)return}}else{if(c=t.button||t.which,(c==1&&t.shiftKey==!1)==!1)return;if(t.defaultPrevented||t.preventDefault(),(s!==0||h!==0)==!1)return}if(f.isMoveing=!0,f.isFirstMoveing===!0&&(f.isFirstMoveing=!1,i.isFunction(n.winform.event.onmove.before)&&(l=n.winform.event.onmove.before(n.layxWindow,n.winform),l===!1))){f.isMoveing=!1;f.isFirstMoveing=!0;i.isSupportTouch?(document.ontouchend=null,document.ontouchmove=null):(document.onmouseup=null,document.onmousemove=null);return}u=n.winform.area.left+s;o=n.winform.area.top+h;n.winform.status==="max"&&n.winform.resizable===!0&&(e.x<n.winform.area.width/2?u=0:e.x>n.winform.area.width/2&&e.x<n.innerArea.width-n.winform.area.width?u=e.x-n.winform.area.width/2:n.innerArea.width-e.x<n.winform.area.width/2?u=n.innerArea.width-n.winform.area.width:n.innerArea.width-e.x>n.winform.area.width/2&&e.x>=n.innerArea.width-n.winform.area.width&&(u=e.x-n.winform.area.width/2),o=0,n.winform.area.top=0,n.winform.area.left=u,r.restore(n.winform.id));n.winform.moveLimit.horizontal===!0&&(u=n.winform.area.left);n.winform.moveLimit.vertical===!0&&(o=n.winform.area.top);n.winform.moveLimit.leftOut===!1&&(u=Math.max(u,0));n.winform.moveLimit.rightOut===!1&&(u=Math.min(u,n.innerArea.width-n.winform.area.width));n.winform.moveLimit.bottomOut===!1&&(o=Math.min(o,n.innerArea.height-n.winform.area.height));o=Math.max(o,0);o=Math.min(n.innerArea.height-15,o);u=Math.max(u,-(n.winform.area.width-15));u=Math.min(u,n.innerArea.width-15);n.layxWindow.style.left=u+"px";n.layxWindow.style.top=o+"px";i.isFunction(n.winform.event.onmove.progress)&&n.winform.event.onmove.progress(n.layxWindow,n.winform)},e=function(t){var h,s,u,e,o;if(t=t||window.event,i.isSupportTouch){if(document.ontouchend=null,document.ontouchmove=null,i.IsPC()){if(h=t.button||t.which,h==1&&t.shiftKey==!1)for(s=n.layxWindow.querySelectorAll(".layx-resizes > div"),u=0;u<s.length;u++)s[u].classList.add("layx-reisize-touch");document.onmouseup=null;document.onmousemove=null}}else document.onmouseup=null,document.onmousemove=null;e=n.layxWindow.querySelector(".layx-mouse-preventDefault");e&&e.parentNode.removeChild(e);o=document.getElementById("layx-window-move");o&&o.parentNode.removeChild(o);f.isMoveing===!0&&(f.isMoveing=!1,f.isFirstMoveing=!0,n.winform.area.top=n.layxWindow.offsetTop,n.winform.area.left=n.layxWindow.offsetLeft,n.winform.storeStatus===!0&&r.storeWindowAreaInfo(n.winform.id,{top:n.winform.area.top,left:n.winform.area.left,width:n.winform.area.width,height:n.winform.area.height}),n.winform.area.top===0&&n.winform.status==="normal"&&n.winform.maxable===!0&&n.winform.resizable===!0&&n.winform.dragInTopToMax===!0&&(n.winform.area.top=n.defaultArea.top,n.winform.area.left=n.defaultArea.left,n.winform.storeStatus===!0&&r.storeWindowAreaInfo(n.winform.id,{top:n.winform.area.top,left:n.winform.area.left,width:n.winform.area.width,height:n.winform.area.height}),r.max(n.winform.id)),i.isFunction(n.winform.event.onmove.after)&&n.winform.event.onmove.after(n.layxWindow,n.winform))},o=function(f){var o,l,s,h,p,c,v,w,y,a;if(f=f||window.event,o=i.getNodeByClassName(n,"layx-window",t),o&&(l=o.getAttribute("id").substr(5),s=r.windows[l],s))if(s.status!=="min"&&s.movable===!0)if(h=document.getElementById("layx-window-move"),h||(h=document.createElement("div"),h.setAttribute("id","layx-window-move"),document.body.appendChild(h)),r.updateZIndex(l),h.style.zIndex=s.zIndex-1,p=i.getMousePosition(f),n.mouseStartCoord=p,n.layxWindow=o,n.winform=s,n.innerArea=i.innerArea(),n.defaultArea=layxDeepClone({},s.area),n.touchDate=new Date,c=o.querySelector(".layx-mouse-preventDefault"),c||(c=document.createElement("div"),c.classList.add("layx-mouse-preventDefault"),v=o.querySelector(".layx-main"),v&&v.appendChild(c)),i.isSupportTouch){if(document.ontouchend=e,document.ontouchmove=u,i.IsPC()){if(w=f.button||f.which,w==1&&f.shiftKey==!1)for(y=o.querySelectorAll(".layx-resizes > div"),a=0;a<y.length;a++)y[a].classList.remove("layx-reisize-touch");document.onmouseup=e;document.onmousemove=u}}else document.onmouseup=e,document.onmousemove=u;else r.restore(l);return!1};i.isSupportTouch?(n.ontouchstart=o,i.IsPC()&&(n.onmousedown=o)):n.onmousedown=o};t.layx={v:function(){return r.version}(),open:function(n){return r.create(n)},html:function(n,t,i,u){return r.create(layxDeepClone({},{id:n,title:t,type:"html",content:i},u||{}))},iframe:function(n,t,i,u){return r.create(layxDeepClone({},{id:n,title:t,type:"url",url:i,useFrameTitle:t===!0?!0:!1},u||{}))},group:function(n,t,i,u){return r.create(layxDeepClone({},{id:n,type:"group",frames:t,frameIndex:typeof i=="number"?i>t.length?0:i:0},u||{}))},windows:function(){return r.windows},getWindow:function(n){return r.windows[n]},destroy:function(n,t,i){r.destroy(n,t,!1,!1,i)},visual:function(n,t,i){r.visual(n,t,i)},min:function(n){r.min(n)},max:function(n){r.max(n)},setTitle:function(n,t,i){r.setTitle(n,t,i)},flicker:function(n){r.flicker(n)},restore:function(n){r.restore(n)},updateZIndex:function(n){r.updateZIndex(n)},updateMinLayout:function(){r.updateMinLayout()},stickToggle:function(n){r.stickToggle(n)},setPosition:function(n,t){r.setPosition(n,t)},getFrameContext:function(n){return r.getFrameContext(n)},getParentContext:function(n){return r.getParentContext(n)},setContent:function(n,t,i){r.setContent(n,t,i)},setUrl:function(n,t){r.setUrl(n,t)},setGroupContent:function(n,t,i,u){r.setGroupContent(n,t,i,u)},setGroupTitle:function(n,t,i,u){r.setGroupTitle(n,t,i,u)},setGroupUrl:function(n,t,i){r.setGroupUrl(n,t,i)},setGroupIndex:function(n,t){r.setGroupIndex(n,t)},getGroupFrameContext:function(n,t){return r.getGroupFrameContext(n,t)},destroyAll:function(){r.destroyAll()},tip:function(n,t,i,u){r.tip(n,t,i,u)},msg:function(n,t){return r.msg(n,t)},alert:function(n,t,i,u){return r.alert(n,t,i,u)},confirm:function(n,t,i,u){return r.confirm(n,t,i,u)},getPromptTextArea:function(n){return r.getPromptTextArea(n)},prompt:function(n,t,i,u,f){return r.prompt(n,t,i,u,f)},load:function(n,t,i){return r.load(n,t,i)},multiLine:function(n){return n.toString().replace(/^[^\/]+\/\*!?\s?/,"").replace(/\*\/[^\/]+$/,"")},reloadFrame:function(n){r.reloadFrame(n)},reloadGroupFrame:function(n,t){r.reloadGroupFrame(n,t)},setButtonStatus:function(n,t,i){r.setButtonStatus(n,t,i)},updateFloatWinPosition:function(n,t){r.updateFloatWinPosition(n,t)},getElementPos:function(n){return i.getElementPos(n)},destroyInlay:function(n){r.destroyInlay(n)},checkVisual:function(n,t,r){return i.checkElementIsVisual(n,t,r)},getButton:function(n,t){return r.getButton(n,t)},setSize:function(n,t){r.setSize(n,t)}};t.document.addEventListener("keydown",function(n){var i=n||window.event||arguments.callee.caller.arguments[0],t=r.windows[r.focusId],u;i&&i.keyCode==27&&t&&r.destroy(r.focusId,{},!1,!0);i&&i.keyCode===13&&t&&t.buttons.length>0&&(t.buttonKey.toLowerCase()!=="enter"||i.ctrlKey?t.buttonKey.toLowerCase()==="ctrl+enter"&&i.ctrlKey&&(t.dialogType!=="prompt"?t.buttons[0].callback(t.id,r.getButton(t.id,t.buttons[0].id,i)):(u=r.getPromptTextArea(t.id),t.buttons[0].callback(t.id,(u?u.value:"").replace(/(^\s*)|(\s*$)/g,""),u,r.getButton(t.id,t.buttons[0].id,i)))):t.dialogType!=="prompt"?t.buttons[0].callback(t.id,r.getButton(t.id,t.buttons[0].id,i)):(u=r.getPromptTextArea(t.id),t.buttons[0].callback(t.id,(u?u.value:"").replace(/(^\s*)|(\s*$)/g,""),u,r.getButton(t.id,t.buttons[0].id,i))))},!1)}(top,window,self);!function(n){var i,r,t;t=function(n){return Object.prototype.toString.call(n)==="[object Object]"};r=function u(n,i){for(var r in n)if(n.hasOwnProperty(r))if(t(n[r])&&t(i[r])&&u(n[r],i[r]),i.hasOwnProperty(r))continue;else i[r]=n[r]};i=function(){var n=arguments,u={},i;if(!n.length)return{};for(i=n.length-1;i>=0;i--)t(n[i])&&r(n[i],u);return n[0]=u,u};n.layxDeepClone=i}(window);!function(n){function o(){var i,n;i=document.createElement("div");i.innerHTML=t;t=null;n=i.getElementsByTagName("svg")[0];n&&(n.setAttribute("aria-hidden","true"),n.style.position="absolute",n.style.width=0,n.style.height=0,n.style.overflow="hidden",e(n,document.body))}var t='<svg><symbol id="layx-icon-warn" viewBox="0 0 1044 1024"><path d="M589.8368 120.10666667q2.88 4.8 19.68 33.12t42.24 71.52 57.12 97.92 65.28 111.84 66.72 113.28 60.48 103.2 47.04 80.64 27.36 46.08q14.4 24 17.76 48t-2.88 43.2-22.08 31.2-38.88 11.04q-11.52 0-48.96-0.48t-90.24-0.48l-120 0-135.36 0q-69.12 0-137.28 0.48t-126.72 0.48l-102.72 0-65.28 0q-36.48 0-56.16-12.48t-26.4-32.16-1.44-42.72 18.72-43.2q6.72-10.56 26.4-43.2t47.52-79.2 61.44-102.72 68.16-114.24 67.2-112.8 58.56-98.88 43.2-72.96l20.16-33.6q13.44-21.12 35.04-32.16t44.64-11.04 44.64 10.08 35.04 30.24zM565.8368 308.26666667q0-11.52-5.28-21.6t-13.92-18.24-19.68-12.96-22.56-4.8q-22.08 0-40.8 17.28t-18.72 39.36l0 251.52q0 22.08 18.72 39.84t40.8 17.76q23.04 0 42.24-16.8t19.2-38.88l0-252.48zM504.3968 673.06666667q-24.96 0-42.72 17.28t-17.76 42.24 17.76 42.72 42.72 17.76 42.24-17.76 17.28-42.72-17.28-42.24-42.24-17.28z" ><\/path><\/symbol><symbol id="layx-icon-help" viewBox="0 0 1024 1024"><path d="M512.697383 63.444984c-247.538793 0-448.208115 200.649879-448.208115 448.208115 0 247.520373 200.66932199 448.208115 448.208115 448.20811499s448.208115-200.68774199 448.20811499-448.20811499C960.90549801 264.094864 760.236176 63.444984 512.697383 63.444984zM510.98846199 735.138056c-25.550932 0-46.25958-21.30114199-46.25958-47.563272s20.708648-47.563272 46.25958-47.563272c25.56116599 0 46.269813 21.30114199 46.26981301 47.563272S536.548604 735.138056 510.98846199 735.138056zM640.211569 436.222129c-6.383384 12.29195401-13.970176 22.86986999-22.75116701 31.769564-8.78098999 8.936533-24.55730201 23.927969-47.29925899 45.046962-6.291287 5.945409-11.334139 11.161201-15.11934899 15.684214-3.792373 4.48719799-6.619768 8.608052-8.46274201 12.365632-1.868557 3.71971799-3.291976 7.47729799-4.303003 11.197016-1.013073 3.756557-2.543939 10.32208999-4.57929499 19.73343699-3.518127 19.95037801-14.524808 29.910217-33.02720802 29.91021701-9.611915 0-17.70831401-3.24797401-24.26565998-9.775644-6.573719-6.529717-9.848299-16.194844-9.84829901-29.071106 0-16.086373 2.39862999-30.05552601 7.204076-41.83685101 4.814656-11.818163 11.18882999-22.177092 19.150152-31.07678599 7.960299-8.89969399 18.684548-19.514449 32.17991-31.806403 11.835559-10.724249 20.39858601-18.821671 25.660426-24.293289 5.287423-5.470595 9.72038601-11.562337 13.32344701-18.273179 3.610224-6.711865 5.415336-14.007015 5.415336-21.84861101 0-15.355733-5.508457-28.305673-16.50388201-38.84572699-11.016915-10.541077-25.205055-15.830547-42.594097-15.830547-20.354584 0-35.33578599 5.325285-44.94770099 15.975856-9.62010199 10.650571-17.754363 26.29794599-24.42017901 47.05264199-6.291287 21.66646199-18.219967 32.49918199-35.791158 32.49918201-10.349719 0-19.10308-3.793396-26.217105-11.380188-7.121188-7.586792-10.6782-15.793708-10.6782-24.583908 0-18.237363 5.635347-36.694737 16.915251-55.405891 11.279904-18.67533799 27.757181-34.17638 49.396014-46.43251901 21.63064599-12.292977 46.888913-18.420535 75.742055-18.42053499 26.825972 0 50.489928 5.143137 71.025637 15.392572 20.534685 10.249435 36.39286199 24.219611 47.580668 41.83685099 11.189853 17.654079 16.788361 36.839023 16.78836099 57.557904C649.785621 409.668357 646.593929 423.96701401 640.211569 436.222129z" ><\/path><\/symbol><symbol id="layx-icon-right" viewBox="0 0 1024 1024"><path d="M511.59752247 82.09957256c-237.19528125 0-429.47861308 192.28333184-429.4786131 429.47771397 0 237.19528125 192.28333184 429.47771396 429.47861309 429.47771396 237.19438213 0 429.47681484-192.28153271 429.47681485-429.47771396C941.07343818 274.38380352 748.79100547 82.09957256 511.59752247 82.09957256zM416.15603193 750.07218711L225.32791396 559.24676651l47.61641602-47.61641602L416.15603193 654.84205332l334.09018653-334.09198564 47.6155169 47.61461689L416.15603193 750.07218711z" ><\/path><\/symbol><symbol id="layx-icon-restore" viewBox="0 0 1157 1024"><path d="M1016.52185234 724.44050175L833.87364805 724.44050175 833.87364805 898.52098643 833.87364805 960.05279112 833.87364805 961.2211168 772.34184336 961.2211168 772.34184336 960.05279112 124.31068789 960.05279112 124.31068789 961.2211168 62.7788832 961.2211168 62.7788832 960.05279112 62.7788832 898.52098643 62.7788832 360.31241885 62.7788832 298.78061416 124.31068789 298.78061416 298.78061416 298.78061416 298.78061416 62.7788832 303.06447442 62.7788832 360.31241885 62.7788832 1016.52185234 62.7788832 1074.15923838 62.7788832 1078.05365615 62.7788832 1078.05365615 662.90869795 1078.05365615 724.44050175 1016.52185234 724.44050175ZM124.31068789 898.52098643L772.34184336 898.52098643 772.34184336 724.44050175 772.34184336 662.90869795 772.34184336 360.31241885 124.31068789 360.31241885 124.31068789 898.52098643ZM1016.52185234 124.31068789L360.31241885 124.31068789 360.31241885 298.78061416 772.34184336 298.78061416 833.87364805 298.78061416 833.87364805 360.31241885 833.87364805 662.90869795 1016.52185234 662.90869795 1016.52185234 124.31068789Z" ><\/path><\/symbol><symbol id="layx-icon-reload" viewBox="0 0 1024 1024"><path d="M919.8125 399.5L751.0625 399.5c-23.203125 0-42.1875-18.984375-42.1875-42.1875 0-23.203125 18.984375-42.1875 42.1875-42.1875l68.90625 0C755.28125 213.875 641.375 146.375 512 146.375c-201.796875 0-365.625 163.828125-365.625 365.625 0 201.796875 163.828125 365.625 365.625 365.625 196.875 0 357.890625-156.09375 364.921875-351.5625l0.703125 0c0-23.203125 18.984375-42.1875 42.1875-42.1875 23.203125 0 42.1875 18.984375 42.1875 42.1875 0 2.8125 0 5.625-0.703125 7.734375C950.046875 772.15625 753.171875 962 512 962 263.796875 962 62 760.203125 62 512 62 263.796875 263.796875 62 512 62c150.46875 0 284.0625 73.828125 365.625 187.734375L877.625 188.5625c0-23.203125 18.984375-42.1875 42.1875-42.1875 23.203125 0 42.1875 18.984375 42.1875 42.1875l0 168.75C962 380.515625 943.015625 399.5 919.8125 399.5z" ><\/path><\/symbol><symbol id="layx-icon-default-icon" viewBox="0 0 1024 1024"><path d="M891.88743395 61.93952995L132.11256605 61.93952995c-38.92547129 0-70.60411733 31.65534435-70.60411734 70.5924665L61.50844871 891.46800355c0 38.91382045 31.67864605 70.59246649 70.60411734 70.5924665l759.7748679 0c38.92547129 0 70.60411733-31.67864605 70.60411734-70.5924665L962.49155129 132.53199645C962.49155129 93.59487431 930.81290525 61.93952995 891.88743395 61.93952995zM844.02576498 142.29540409c16.71896178 0 30.25724302 13.54993209 30.25724302 30.26889386 0 16.70731093-13.53828125 30.25724302-30.25724302 30.25724303s-30.25724302-13.54993209-30.25724303-30.25724303C813.76852195 155.84533618 827.3068032 142.29540409 844.02576498 142.29540409zM735.60300658 142.29540409c16.71896178 0 30.25724302 13.54993209 30.25724302 30.26889386 0 16.70731093-13.53828125 30.25724302-30.25724302 30.25724303s-30.25724302-13.54993209-30.25724303-30.25724303C705.34576355 155.84533618 718.8840448 142.29540409 735.60300658 142.29540409zM881.80945351 881.37837227L142.19054649 881.37837227 142.19054649 277.92288427l739.60725618 0L881.79780267 881.37837227zM758.85809209 638.26020125l-0.01165084-180.19196018 90.09598008 90.09598008L758.85809209 638.26020125zM265.15355875 638.26020125l-90.09598008-90.0959801 90.08432924-90.08432924L265.15355875 638.26020125z" ><\/path><\/symbol><symbol id="layx-icon-min" viewBox="0 0 1024 1024"><path d="M65.23884 456.152041 958.760137 456.152041l0 111.695918L65.23884 567.847959 65.23884 456.152041z" ><\/path><\/symbol><symbol id="layx-icon-max" viewBox="0 0 1024 1024"><path d="M75.74912227 948.24738475L75.74912227 75.75145131l872.50059037 0 0 872.49593344L75.74912227 948.24738475zM839.18786674 184.81446115L184.81213326 184.81446115l0 654.37573462 654.37573461 0L839.18786674 184.81446115z" ><\/path><\/symbol><symbol id="layx-icon-debug" viewBox="0 0 1024 1024"><path d="M990.18635001 578.93861562c0 10.3648125-3.782715 19.33089375-11.35486126 26.90304001-7.57310531 7.57310531-16.5372675 11.3606175-26.89728375 11.3606175L818.04354219 617.20227312c0 68.14739625-13.34551219 125.92518281-40.04900719 173.34295313l124.32690656 124.934175c7.57214625 7.56159281 11.3606175 16.53247125 11.3606175 26.89728375 0 10.36001625-3.782715 19.32609657-11.3606175 26.89824281-7.17497531 7.56159281-16.13434125 11.350065-26.89728375 11.350065-10.75814625 0-19.72518656-3.78847125-26.89728375-11.350065L730.17287844 851.51860625c-1.99161001 1.98585375-4.97710594 4.578975-8.96128407 7.765935-3.9928125 3.186-12.3564225 8.872065-25.11097499 17.03612906-12.74879625 8.17078031-25.70193375 15.44360906-38.84982 21.82136531-13.1526825 6.37295906-29.49616125 12.15591844-49.02180283 17.33736563-19.52564156 5.17281281-38.85653531 7.76785313-57.97733155 7.76785312L550.251665 387.6750125l-76.51100531 0 0 535.57224188c-20.31422719 0-40.54690875-2.69481281-60.66351-8.07676407-20.13099094-5.376195-37.46260031-11.95253625-52.00921781-19.72422656-14.54853562-7.77169125-27.69546281-15.53666625-39.44749501-23.31315376-11.75778844-7.77265031-20.419755-14.24346281-26.0060475-19.4201128l-8.96128406-8.3741625L177.26614999 968.07478156c-7.96931719 8.36360906-17.53115344 12.55021125-28.69318593 12.55021125-9.56375531 0-18.12691031-3.19175625-25.69617844-9.56471531-7.57406437-7.17401625-11.659935-16.040325-12.26336531-26.59892625-0.59383781-10.55956031 2.49334969-19.82208094 9.27499125-27.79427531l120.73797938-135.68176782c-23.10977156-45.43575469-34.66897406-100.03041937-34.66897407-163.79071031L72.06771406 617.19459781c-10.36673156 0-19.32801562-3.78847125-26.89728375-11.35486124-7.57406437-7.5769425-11.36253657-16.5382275-11.36253656-26.90304 0-10.36001625 3.78847125-19.33089375 11.36253656-26.89632469 7.56926812-7.56830906 16.53055219-11.35102406 26.89728375-11.35102407l133.88874375 0L205.95645781 364.95953375l-103.40828906-103.40828906c-7.57022719-7.57310531-11.35678031-16.5382275-11.35678031-26.89824281 0-10.35905625 3.79134938-19.33089375 11.35678031-26.89728376 7.56734906-7.57214625 16.53630844-11.36541469 26.89824281-11.36541469 10.36577156 0 19.32417844 3.79902469 26.89920188 11.3654147l103.40828906 103.40828906 504.49507219 0 103.40924812-103.40828907c7.56639001-7.57214625 16.53055219-11.36541469 26.89728375-11.36541469 10.36001625 0 19.32897469 3.79902469 26.89632469 11.36541469 7.57310531 7.56639001 11.36157655 16.5382275 11.36157656 26.89728375 0 10.36001625-3.78847125 19.32609657-11.36157656 26.89824282l-103.40828906 103.40828906 0 175.73269312 133.88970281 0c10.3648125 0 19.32993469 3.782715 26.89728375 11.35678032 7.57214625 7.56543094 11.3606175 16.53630844 11.3606175 26.89056843l0 0L990.18635001 578.93861562 990.18635001 578.93861562zM703.26983938 234.64820469L320.72056719 234.64820469c0-52.99351031 18.62960906-98.12611031 55.89074625-135.38820656 37.25058375-37.26209625 82.3899-55.88594906 135.38532843-55.88594907 52.99638844 0 98.13570375 18.62385281 135.38724751 55.88594907C684.64694563 136.52113438 703.26983938 181.65469437 703.26983938 234.64820469L703.26983938 234.64820469 703.26983938 234.64820469 703.26983938 234.64820469z" ><\/path><\/symbol><symbol id="layx-icon-destroy" viewBox="0 0 1024 1024"><path d="M933.89254819 139.71606348L884.23129279 90.08990363 511.96490363 462.39138834 140.40044113 90.82692583 90.84447403 140.34779656 462.40893653 511.91225907 90.10745181 884.2137446 139.73361166 933.875 512.03509637 561.53841892 883.59955887 933.10288141 933.15552597 883.58201068 561.59106347 512.01754819Z" ><\/path><\/symbol><symbol id="layx-icon-error" viewBox="0 0 1024 1024"><path d="M482 50.66666667C235.99999999 50.66666667 32 254.66666667 32 500.66666667s204.00000001 450 450 450 450-204.00000001 450-450S728 50.66666667 482 50.66666667z m192 576c18 18 18 42 0 60-18 18-42 18-60 0L488 560.66666667 356 692.66666667c-18 18-48 18-66 0-18-18-18-48 0-66L422 494.66666667 296 368.66666667c-18-18-18-42 0-60 18-18 42-18 60 0L482 434.66666667l132-132c18-18 48-18 66 0 18 18 18 48-1e-8 66L548 500.66666667l126 126z" fill="" ><\/path><\/symbol><symbol id="layx-icon-stick" viewBox="0 0 1024 1024"><path d="M863.92416068 184.3484319H160.07583932a50.27488011 50.27488011 0 0 1 0-100.5497602h703.84832136a50.27488011 50.27488011 0 0 1 0 100.5497602z m-50.27488007 804.39808157a50.22460522 50.22460522 0 0 1-35.69516489-14.57971521L512 708.21268254l-265.95411572 265.95411572A50.27488011 50.27488011 0 0 1 160.07583932 938.47163339V335.1730722a50.27488011 50.27488011 0 0 1 50.27488007-50.27488013h603.29856122a50.27488011 50.27488011 0 0 1 50.27488007 50.27488013v603.29856119a50.27488011 50.27488011 0 0 1-50.27488007 50.27488008z m-301.64928061-402.19904078a50.22460522 50.22460522 0 0 1 35.69516487 14.57971522L763.37440051 816.80642355V385.44795228H260.62559949v431.86122007l215.67923564-215.67923564A50.27488011 50.27488011 0 0 1 512 586.54747269z" ><\/path><\/symbol><\/svg>',i=function(){var n=document.getElementsByTagName("script");return n[n.length-1]}(),r=i.getAttribute("data-injectcss"),u=function(t){function r(n,t){var i=n.document,r=!1,u=function(){r||(r=!0,t())},f=function(){try{i.documentElement.doScroll("left")}catch(n){setTimeout(f,50);return}u()};f();i.onreadystatechange=function(){i.readyState=="complete"&&(i.onreadystatechange=null,u())}}if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(t,0);else{var i=function(){document.removeEventListener("DOMContentLoaded",i,!1);t()};document.addEventListener("DOMContentLoaded",i,!1)}else document.attachEvent&&r(n,t)},f=function(n,t){t.parentNode.insertBefore(n,t)},e=function(n,t){t.firstChild?f(n,t.firstChild):t.appendChild(n)};if(r&&!n.__iconfont__svg__cssinject__){n.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}<\/style>")}catch(s){console&&console.log(s)}}u(o)}(window); |
| | |
| | | <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"> |
| | | <link rel="stylesheet" href="../static/css/layx.min.css" type="text/css" /> |
| | | <script src="../static/js/tools/layx.min.js"></script> |
| | | <style> |
| | | .layui-logo img { |
| | | width: 25px; |
| | |
| | | font-size: 18px; |
| | | 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> |
| | |
| | | <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>--> |
| | | <!-- </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> |
| | | </li> |
| | |
| | | <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/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 中扬立库平台 %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 () { |
| | |
| | | } |
| | | }); |
| | | |
| | | $.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 <= 30) { |
| | | $("#licenseShow").show() |
| | | $("#licenseDays").html(days) |
| | | } |
| | | }else { |
| | | top.location.href = baseUrl + "/login"; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | // 默认加载主页 |
| | | index.loadHome({ |
| | | menuPath: baseUrl+'/views/home/navigation.html', |