自动化立体仓库 - WMS系统
dubin
1 天以前 5b6e33867d337b6aaeaf91b2fcd1b6e94c07de6c
许可证2.0
8个文件已修改
7个文件已添加
530 ■■■■ 已修改文件
src/main/java/com/zy/system/controller/LicenseCreatorController.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/LicenseInfos.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/AbstractServerInfos.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/CustomKeyStoreParam.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/CustomLicenseManager.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LicenseCheckListener.java 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LicenseVerify.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LinuxServerInfos.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/mapper/LicenseInfosMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/service/LicenseInfosService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/service/impl/LicenseInfosServiceImpl.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/timer/LicenseTimer.java 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/LicenseInfosMapper.xml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/locDetl/locDetl.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/index.html 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/controller/LicenseCreatorController.java
@@ -3,7 +3,7 @@
import com.core.common.Cools;
import com.core.common.R;
import com.zy.system.entity.license.*;
import de.schlichtherle.license.LicenseContent;
import com.zy.system.timer.LicenseTimer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
@@ -14,7 +14,6 @@
import java.io.File;
import java.io.IOException;
import java.util.Date;
/**
 *
@@ -26,10 +25,10 @@
    @Value("${license.licensePath}")
    private String licensePath;
    @Autowired
    private LicenseCheckListener licenseCheckListener;
    @Autowired
    private LicenseTimer licenseTimer;
    /**
     * 获取服务器硬件信息
     * @param osName 操作系统类型,如果为空则自动判断
@@ -48,7 +47,7 @@
        if (osName.startsWith("windows")) {
            abstractServerInfos = new WindowsServerInfos();
        } else if (osName.startsWith("linux")) {
//            abstractServerInfos = new LinuxServerInfos();
            abstractServerInfos = new LinuxServerInfos();
        }else{//其他服务器类型
            abstractServerInfos = new WindowsServerInfos();
        }
@@ -61,19 +60,7 @@
     */
    @RequestMapping(value = "/getLicenseDays")
    public R getLicenseDays() {
        LicenseVerify licenseVerify = new LicenseVerify();
        LicenseContent verifyInfo = licenseVerify.getVerifyInfo();
        if (verifyInfo == null) {
            return R.error();
        }
        Date start = new Date();
        Date end = verifyInfo.getNotAfter();
        Long starTime = start.getTime();
        Long endTime = end.getTime();
        Long num = endTime - starTime;//时间戳相差的毫秒数
        int day = (int) (num / 24 / 60 / 60 / 1000);
        return R.ok().add(day);
        return R.ok(licenseTimer.getLicenseDays());
    }
    @RequestMapping(value = "/updateLicense")
@@ -109,4 +96,10 @@
        return R.error("许可证更新失败");
    }
    @RequestMapping(value = "/activate")
    public R activate() {
        licenseTimer.timer();
        return R.ok();
    }
}
src/main/java/com/zy/system/entity/LicenseInfos.java
New file
@@ -0,0 +1,56 @@
package com.zy.system.entity;
import com.core.common.Cools;import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.enums.IdType;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.baomidou.mybatisplus.annotations.TableField;
import org.springframework.format.annotation.DateTimeFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.baomidou.mybatisplus.annotations.TableName;
import java.io.Serializable;
@Data
@TableName("sys_license_infos")
public class LicenseInfos implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value= "")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty(value= "")
    private String license;
    @ApiModelProperty(value= "")
    private String licenseTime;
    @ApiModelProperty(value= "")
    @TableField("create_time")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    public LicenseInfos() {}
    public LicenseInfos(String license,Date createTime) {
        this.license = license;
        this.createTime = createTime;
    }
//    LicenseInfos licenseInfos = new LicenseInfos(
//            null,    //
//            null    //
//    );
    public String getCreateTime$(){
        if (Cools.isEmpty(this.createTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
    }
}
src/main/java/com/zy/system/entity/license/AbstractServerInfos.java
@@ -23,7 +23,7 @@
        LicenseCheck result = new LicenseCheck();
        try {
            result.setIpAddress(this.getIpAddress());
//            result.setIpAddress(this.getIpAddress());
            result.setMacAddress(this.getMacAddress());
            result.setCpuSerial(this.getCPUSerial());
            result.setMainBoardSerial(this.getMainBoardSerial());
src/main/java/com/zy/system/entity/license/CustomKeyStoreParam.java
@@ -2,7 +2,9 @@
import de.schlichtherle.license.AbstractKeyStoreParam;
import java.io.*;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
 * 自定义KeyStoreParam,用于将公私钥存储文件存放到其他磁盘位置而不是项目中
@@ -47,7 +49,7 @@
     */
    @Override
    public InputStream getStream() throws IOException {
        final InputStream in = new FileInputStream(new File(storePath));
        final InputStream in = this.getClass().getClassLoader().getResourceAsStream(storePath);
        if (null == in) {
            throw new FileNotFoundException(storePath);
        }
src/main/java/com/zy/system/entity/license/CustomLicenseManager.java
@@ -194,7 +194,7 @@
        if (osName.startsWith("windows")) {
            abstractServerInfos = new WindowsServerInfos();
        } else if (osName.startsWith("linux")) {
//            abstractServerInfos = new LinuxServerInfos();
            abstractServerInfos = new LinuxServerInfos();
        }else{//其他服务器类型
            abstractServerInfos = new WindowsServerInfos();
        }
src/main/java/com/zy/system/entity/license/LicenseCheckListener.java
@@ -1,9 +1,13 @@
package com.zy.system.entity.license;
import com.core.common.Cools;
import com.zy.system.entity.LicenseInfos;
import com.zy.system.service.LicenseInfosService;
import com.zy.system.timer.LicenseTimer;
import de.schlichtherle.license.LicenseContent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
@@ -11,6 +15,7 @@
import org.springframework.stereotype.Component;
import java.io.File;
import java.util.Date;
/**
 * 在项目启动时安装证书
@@ -48,6 +53,10 @@
     */
    @Value("${license.publicKeysStorePath}")
    private String publicKeysStorePath;
    @Autowired
    private LicenseTimer licenseTimer;
    @Autowired
    private LicenseInfosService licenseInfosService;
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
@@ -64,31 +73,51 @@
            logger.info("++++++++ 开始加载许可证 ++++++++");
            try {
                String publicKeysStoreFileName = this.getClass().getClassLoader().getResource(publicKeysStorePath).getPath();
                File publicKeysStoreFile = new File(publicKeysStoreFileName);
                licenseTimer.getRemoteLicense();
            } catch (Exception e) {
            }
                String licensePathFileName = this.getClass().getClassLoader().getResource(licensePath).getPath();
                File licensePathFile = new File(licensePathFileName);
            try {
                LicenseVerifyParam param = new LicenseVerifyParam();
                param.setSubject(subject);
                param.setPublicAlias(publicAlias);
                param.setStorePass(storePass);
                param.setLicensePath(licensePathFile.getPath());
                param.setPublicKeysStorePath(publicKeysStoreFile.getPath());
                param.setLicensePath(licensePath);
                param.setPublicKeysStorePath(publicKeysStorePath);
                LicenseVerify licenseVerify = new LicenseVerify();
                LicenseInfos latestLicense = licenseInfosService.getLatestLicense();
                if (latestLicense == null) {
                    logger.info("许可证不存在");
                    return false;
                }
                //安装证书
                LicenseContent install = licenseVerify.install(param);
                LicenseContent install = licenseVerify.install(param, latestLicense.getLicense());
                logger.info("++++++++ 许可证加载结束 ++++++++");
                licenseTimer.setSystemSupport(install!=null);
                if (install != null) {
                    Date start = new Date();
                    Date end = install.getNotAfter();
                    Long starTime = start.getTime();
                    Long endTime = end.getTime();
                    Long num = endTime - starTime;//时间戳相差的毫秒数
                    int day = (int) (num / 24 / 60 / 60 / 1000);
                    licenseTimer.setLicenseDays(day);
                }
                return install != null;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        licenseTimer.setSystemSupport(false);
        return false;
    }
}
src/main/java/com/zy/system/entity/license/LicenseVerify.java
@@ -5,9 +5,13 @@
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.prefs.Preferences;
/**
@@ -19,16 +23,18 @@
    /**
     * 安装License证书
     */
    public synchronized LicenseContent install(LicenseVerifyParam param){
    public synchronized LicenseContent install(LicenseVerifyParam param, String license) {
        LicenseContent result = null;
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //1. 安装证书
        try{
            LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param));
            LicenseParam licenseParam = initLicenseParam(param);
            LicenseManager licenseManager = LicenseManagerHolder.getInstance(licenseParam);
            licenseManager.uninstall();
            result = licenseManager.install(new File(param.getLicensePath()));
            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);
@@ -45,11 +51,6 @@
            LicenseManager licenseManager = LicenseManagerHolder.getInstance(null);
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (!updateSystemTime()) {
                //时间更新失败,系统时间被更改
                return false;
            }
            LicenseContent licenseContent = licenseManager.verify();
            logger.info(MessageFormat.format("许可证校验通过,许可证有效期:{0} - {1}",format.format(licenseContent.getNotBefore()),format.format(licenseContent.getNotAfter())));
            return true;
@@ -64,11 +65,6 @@
     */
    public LicenseContent getVerifyInfo(){
        LicenseManager licenseManager = LicenseManagerHolder.getInstance(null);
        if (!updateSystemTime()) {
            //时间更新失败,系统时间被更改
            return null;
        }
        //校验证书
        try {
@@ -103,31 +99,28 @@
    }
    /**
     * 更新时间到注册表中
     * 将Base64字符串转换为临时文件
     * @param base64String Base64编码的字符串
     * @param filePrefix 文件名前缀(例如 "license_")
     * @param fileSuffix 文件后缀(例如 ".lic")
     * @return 生成的临时File对象(自动在JVM退出时删除)
     * @throws IOException
     */
    private boolean updateSystemTime() {
        // 获取用户根节点
        Preferences userRoot = Preferences.userRoot();
        // 获取指定路径下的节点
        Preferences node = userRoot.node("/zhongyang");
        String key = "time";
        // 读取注册表
        String value = node.get(key, null);
        if (value != null) {
            long originTime = Long.parseLong(value);
            long now = System.currentTimeMillis();
            long diff = now - originTime;//现在时间 - 源时间 = 时间差
            if (diff > 0) {
                //时间差大于0才允许更新注册表时间
                node.put(key, String.valueOf(System.currentTimeMillis()));
                return true;
    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();
            }
        }else {
            // 写入注册表
            node.put(key, String.valueOf(System.currentTimeMillis()));
            return true;
        }
        return false;
    public File createTempFileFromBase64(String base64Data) throws IOException {
        return base64ToTempFile(base64Data, "temp_license_", ".bin");
    }
}
src/main/java/com/zy/system/entity/license/LinuxServerInfos.java
New file
@@ -0,0 +1,91 @@
package com.zy.system.entity.license;
import com.core.common.Cools;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.util.List;
import java.util.stream.Collectors;
/**
 * 用于获取客户Linux服务器的基本信息
 */
public class LinuxServerInfos extends AbstractServerInfos {
    @Override
    protected List<String> getIpAddress() throws Exception {
        List<String> result = null;
        //获取所有网络接口
        List<InetAddress> inetAddresses = getLocalAllInetAddress();
        if (inetAddresses != null && inetAddresses.size() > 0) {
            result = inetAddresses.stream().map(InetAddress::getHostAddress).distinct().map(String::toLowerCase).collect(Collectors.toList());
        }
        return result;
    }
    @Override
    protected List<String> getMacAddress() throws Exception {
        List<String> result = null;
        //1. 获取所有网络接口
        List<InetAddress> inetAddresses = getLocalAllInetAddress();
        if (inetAddresses != null && inetAddresses.size() > 0) {
            //2. 获取所有网络接口的Mac地址
            result = inetAddresses.stream().map(this::getMacByInetAddress).distinct().collect(Collectors.toList());
        }
        return result;
    }
    @Override
    protected String getCPUSerial() throws Exception {
        //序列号
        String serialNumber = "";
        //使用dmidecode命令获取CPU序列号
        String[] shell = {"/bin/bash", "-c", "dmidecode -t processor | grep 'ID' | awk -F ':' '{print $2}' | head -n 1"};
        Process process = Runtime.getRuntime().exec(shell);
        process.getOutputStream().close();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        if (null == reader.readLine()) {
            return serialNumber;
        }
        String line = reader.readLine().trim();
        if (!Cools.isEmpty(line)) {
            serialNumber = line;
        }
        reader.close();
        return serialNumber;
    }
    @Override
    protected String getMainBoardSerial() throws Exception {
        //序列号
        String serialNumber = "";
        //使用dmidecode命令获取主板序列号
        String[] shell = {"/bin/bash", "-c", "dmidecode | grep 'Serial Number' | awk -F ':' '{print $2}' | head -n 1"};
        Process process = Runtime.getRuntime().exec(shell);
        process.getOutputStream().close();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        if (null == reader.readLine()) {
            return serialNumber;
        }
        String line = reader.readLine().trim();
        if (!Cools.isEmpty(line)) {
            serialNumber = line;
        }
        reader.close();
        return serialNumber;
    }
}
src/main/java/com/zy/system/mapper/LicenseInfosMapper.java
New file
@@ -0,0 +1,14 @@
package com.zy.system.mapper;
import com.zy.system.entity.LicenseInfos;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface LicenseInfosMapper extends BaseMapper<LicenseInfos> {
    LicenseInfos getLatestLicense();
}
src/main/java/com/zy/system/service/LicenseInfosService.java
New file
@@ -0,0 +1,10 @@
package com.zy.system.service;
import com.zy.system.entity.LicenseInfos;
import com.baomidou.mybatisplus.service.IService;
public interface LicenseInfosService extends IService<LicenseInfos> {
    LicenseInfos getLatestLicense();
}
src/main/java/com/zy/system/service/impl/LicenseInfosServiceImpl.java
New file
@@ -0,0 +1,16 @@
package com.zy.system.service.impl;
import com.zy.system.mapper.LicenseInfosMapper;
import com.zy.system.entity.LicenseInfos;
import com.zy.system.service.LicenseInfosService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("licenseInfosService")
public class LicenseInfosServiceImpl extends ServiceImpl<LicenseInfosMapper, LicenseInfos> implements LicenseInfosService {
    @Override
    public LicenseInfos getLatestLicense() {
        return this.baseMapper.getLatestLicense();
    }
}
src/main/java/com/zy/system/timer/LicenseTimer.java
New file
@@ -0,0 +1,163 @@
package com.zy.system.timer;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.core.common.Cools;
import com.zy.common.utils.HttpHandler;
import com.zy.system.entity.LicenseInfos;
import com.zy.system.entity.license.*;
import com.zy.system.service.LicenseInfosService;
import de.schlichtherle.license.LicenseContent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
@Component
public class LicenseTimer {
    private static boolean SYSTEM_SUPPORT = false;//系统激活状态,默认关闭
    private static int LICENSE_DAYS = 0;//许可证天数
    /**
     * 证书subject
     */
    @Value("${license.subject}")
    private String subject;
    /**
     * 公钥别称
     */
    @Value("${license.publicAlias}")
    private String publicAlias;
    /**
     * 访问公钥库的密码
     */
    @Value("${license.storePass}")
    private String storePass;
    /**
     * 证书生成路径
     */
    @Value("${license.licensePath}")
    private String licensePath;
    /**
     * 密钥库存储路径
     */
    @Value("${license.publicKeysStorePath}")
    private String publicKeysStorePath;
    @Autowired
    private LicenseInfosService licenseInfosService;
    //每天晚上11点更新系统激活状态
    @Scheduled(cron = "0 0 23 * * ? ")
    public void timer() {
        try {
            getRemoteLicense();
        } catch (Exception e) {
        }
        try {
            verify();
        } catch (Exception e) {
        }
    }
    public void getRemoteLicense() {
        try {
            AbstractServerInfos abstractServerInfos = null;
            String osName = System.getProperty("os.name");
            //根据不同操作系统类型选择不同的数据获取方法
            if (osName.startsWith("windows")) {
                abstractServerInfos = new WindowsServerInfos();
            } else if (osName.startsWith("linux")) {
                abstractServerInfos = new LinuxServerInfos();
            }else{//其他服务器类型
                abstractServerInfos = new WindowsServerInfos();
            }
            LicenseCheck serverInfos = abstractServerInfos.getServerInfos();
            HashMap<String, Object> map = new HashMap<>();
            map.put("subject", subject);
            map.put("licenseCheck", serverInfos);
            String response = new HttpHandler.Builder()
                    .setUri("http://net.zoneyung.net:9999/license")
                    .setPath("/remoteQueryLicense")
                    .setJson(JSON.toJSONString(map))
                    .build()
                    .doPost();
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.getString("result").equals("ok")) {
                LicenseInfos licenseInfos = new LicenseInfos();
                licenseInfos.setLicense(jsonObject.getString("data"));
                licenseInfos.setCreateTime(new Date());
                licenseInfos.setLicenseTime(jsonObject.getString("licenseTime"));
                licenseInfosService.insert(licenseInfos);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void verify() {
        LicenseInfos latestLicense = licenseInfosService.getLatestLicense();
        if (latestLicense == null) {
            setLicenseDays(0);
            setSystemSupport(false);
            return;
        }
        LicenseVerifyParam param = new LicenseVerifyParam();
        param.setSubject(subject);
        param.setPublicAlias(publicAlias);
        param.setStorePass(storePass);
        param.setLicensePath(licensePath);
        param.setPublicKeysStorePath(publicKeysStorePath);
        //验证许可证是否有效
        LicenseVerify licenseVerify = new LicenseVerify();
        //安装证书
        LicenseContent install = licenseVerify.install(param, latestLicense.getLicense());
        if (install != null) {
            Date start = new Date();
            Date end = install.getNotAfter();
            Long starTime = start.getTime();
            Long endTime = end.getTime();
            long num = endTime - starTime;//时间戳相差的毫秒数
            int day = (int) (num / 24 / 60 / 60 / 1000);
            setLicenseDays(day);
            setSystemSupport(true);
        }else {
            setLicenseDays(0);
            setSystemSupport(false);
        }
    }
    public boolean getSystemSupport() {
        return SYSTEM_SUPPORT;
    }
    public void setSystemSupport(boolean systemSupport) {
        SYSTEM_SUPPORT = systemSupport;
    }
    public int getLicenseDays() {
        return LICENSE_DAYS;
    }
    public void setLicenseDays(int licenseDays) {
        LICENSE_DAYS = licenseDays;
    }
}
src/main/resources/mapper/LicenseInfosMapper.xml
New file
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zy.system.mapper.LicenseInfosMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.zy.system.entity.LicenseInfos">
        <id column="id" property="id" />
        <result column="license" property="license" />
        <result column="license_time" property="licenseTime" />
        <result column="create_time" property="createTime" />
    </resultMap>
    <select id="getLatestLicense" resultMap="BaseResultMap">
        select top 1 * from sys_license_infos order by create_time desc
    </select>
</mapper>
src/main/webapp/static/js/locDetl/locDetl.js
@@ -17,7 +17,7 @@
        ,{field: 'brand', align: 'center',title: '品牌', hide: true}
        ,{field: 'unit', align: 'center',title: '单位', hide: true}
        ,{field: 'price', align: 'center',title: '单价', hide: true}
        ,{field: 'sku', align: 'center',title: '简图', hide: false}
        ,{field: 'sku', align: 'center',title: '简图', hide: true}
        ,{field: 'units', align: 'center',title: '单位量', hide: true}
        ,{field: 'barcode', align: 'center',title: '条码', hide: true}
        ,{field: 'origin', align: 'center',title: '产地', hide: true}
src/main/webapp/views/index.html
@@ -8,7 +8,7 @@
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <link rel="icon" type="image/x-icon" href="../static/image/favicon.ico" />
  <link rel="stylesheet" href="../static/layui/css/layui.css" media="all">
  <link rel="stylesheet" href="../static/css/admin.css?v=319" media="all">
  <link rel="stylesheet" href="../static/css/admin.css?v=318" media="all">
  <link rel="stylesheet" href="../static/css/loader.css" media="all">
  <style>
    .layui-logo img {
@@ -24,9 +24,9 @@
<body class="layui-layout-body">
<div class="layui-layout layui-layout-admin">
  <!-- 头部 -->
  <div class="layui-header" style=" height: 80px;">
  <div class="layui-header">
    <div class="layui-logo">
      <img src="../static/image/logo.png" style="display: inline-block; width: 95%;height: auto">
      <img src="../static/image/zy_logo_dark_color.png" style="display: inline-block; width: 40%;height: auto">
      <!--          <span style="margin-top: 0; letter-spacing: 10px">中扬立库</span>-->
      <!--          <img src="../static/image/logo.svg"/>-->
      <!--          <cite>中扬 - Zoneyung</cite>-->
@@ -42,7 +42,7 @@
    </ul>
    <ul class="layui-nav layui-layout-right">
      <li class="layui-nav-item" lay-unselect id="licenseShow" style="display: none;user-select: none;">
        <div style="color: red;">许可证有效期:<span id="licenseDays">29</span>天</div>
        <div style="color: red;">临时许可证有效期:<span id="licenseDays">29</span>天</div>
      </li>
      <li class="layui-nav-item layui-hide-xs" lay-unselect>
        <a ew-event="fullScreen" title="全屏"><i class="layui-icon layui-icon-screen-full"></i></a>
@@ -150,6 +150,7 @@
          if (days <= 30) {
            $("#licenseShow").show()
            $("#licenseDays").html(days)
            alert("临时许可有效期:" + days + "天")
          }
        }else {
          top.location.href = baseUrl + "/login";