yangys
2024-12-30 7cd413d0f1e3235223848d47e428aad97f9f13fc
去掉数据点中的计算规则和计算参数-暂时
已修改4个文件
已添加25个文件
2645 ■■■■■ 文件已修改
smart-man-boot/pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/common/config/SwaggerConfiguration.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/common/utils/DurationUtil.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/common/vo/CommonIdsVO.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/smis/controller/WorkstationController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/controller/PartWorkHourController.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/controller/PartWorkingProcessController.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/convert/PartWorkingHourConvert.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/convert/PartWorkingProcessConvert.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/entity/PartWorkingHour.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/entity/PartWorkingProcess.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/excel/PartWorkingHourExcel.java 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/excel/PartWorkingProcessExcel.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/mapper/PartWorkingHourMapper.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/mapper/PartWorkingProcessMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/service/JFreeChartUtil.java 290 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/service/PartWorkingHourExportService.java 378 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/service/PartWorkingHourService.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/service/PartWorkingProcessService.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/vo/PartWorkingHourQueryVO.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/vo/PartWorkingHourVO.java 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/vo/PartWorkingProcessVO.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/resources/com/qianwen/smartman/modules/workinghour/mapper/PartWorkingHourMapper.xml 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/resources/dp/dpend-带计算规则.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/resources/dp/dpend.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/resources/sql/iotdb/iot_struct.sql 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/main/resources/sql/mysql/workinghours.sql 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/test/java/com/qianwen/smartman/common/utils/DurationUtilTest.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/src/test/java/com/qianwen/smartman/modules/workinghour/service/PartWorkingHourServiceTest.java 510 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smart-man-boot/pom.xml
@@ -504,6 +504,13 @@
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jfree</groupId>
            <artifactId>jfreechart</artifactId>
            <version>1.5.5</version>
        </dependency>
    </dependencies>
    
  <build>
smart-man-boot/src/main/java/com/qianwen/smartman/common/config/SwaggerConfiguration.java
@@ -137,6 +137,11 @@
        return docket("andon", Collections.singletonList("com.qianwen.smartman.modules.andon"));
    }
    @Bean
    public Docket workinghourDocket() {
        return docket("workinghour", Collections.singletonList("com.qianwen.smartman.modules.workinghour"));
    }
    private Docket docket(String groupName, List<String> basePackages) {
        TypeResolver resolver = new TypeResolver();
        AlternateTypeRule listLongToString = AlternateTypeRules.newRule(resolver.resolve(List.class, new Type[]{Long.class}), resolver.resolve(List.class, new Type[]{String.class}));
smart-man-boot/src/main/java/com/qianwen/smartman/common/utils/DurationUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
package com.qianwen.smartman.common.utils;
import java.time.Duration;
public class DurationUtil {
    /**
     * å°†æ—¶é—´å·®è½¬æ¢ä¸ºä¸­æ–‡ï¼Œå¦‚1天2小时3分15秒
     * @param duration
     * @return ä¸­æ–‡æ—¶é—´å·®
     */
    public static String toChineseDuration(Duration duration) {
        String dayStr = "";
        if(duration.toDays() > 0) {
            dayStr = duration.toDays()+"天";
        }
        long temp;
        String secStr = "";
        if(duration.getSeconds() > 0) {
            temp = duration.getSeconds()%60;
            if(temp > 0) {
                secStr = temp+"秒";
            }
        }
        String minStr = "";
        if(duration.toMinutes() > 0) {
            temp = duration.toMinutes()%60;
            if(temp > 0) {
                minStr += temp+"分";
            }
        }
        String hourStr = "";
        if(duration.toHours() > 0) {
            temp = duration.toHours()%24;
            if(temp > 0) {
                hourStr = temp+"小时";
            }
        }
        return dayStr + hourStr+minStr+secStr;
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/common/vo/CommonIdsVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.qianwen.smartman.common.vo;
import java.io.Serializable;
import java.util.List;
import javax.validation.constraints.NotEmpty;
public class CommonIdsVO  implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = 1791423608430772402L;
    @NotEmpty(message = "ids不能为空")
    private List<Long> ids;
    public List<Long> getIds() {
        return ids;
    }
    public void setIds(List<Long> ids) {
        this.ids = ids;
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/smis/controller/WorkstationController.java
@@ -35,7 +35,6 @@
import com.qianwen.smartman.modules.smis.dto.WorkstationRealTimeStatusDTO;
import com.qianwen.smartman.modules.smis.excel.WorkstationImport;
import com.qianwen.smartman.modules.smis.service.IWorkstationService;
import com.qianwen.smartman.modules.smis.vo.DmpVariablesVO;
import com.qianwen.smartman.modules.smis.vo.FmsWorkstationGroupVO;
import com.qianwen.smartman.modules.smis.vo.FmsWorkstationQueryVO;
import com.qianwen.smartman.modules.smis.vo.WorkMachineEasyVO;
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/controller/PartWorkHourController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package com.qianwen.smartman.modules.workinghour.controller;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.qianwen.core.boot.ctrl.BladeController;
import com.qianwen.core.mp.support.Condition;
import com.qianwen.core.mp.support.Query;
import com.qianwen.core.oss.model.BladeFile;
import com.qianwen.core.scanner.modular.stereotype.ApiResource;
import com.qianwen.core.tenant.annotation.NonDS;
import com.qianwen.core.tool.api.R;
import com.qianwen.smartman.common.vo.CommonIdsVO;
import com.qianwen.smartman.modules.workinghour.service.PartWorkingHourExportService;
import com.qianwen.smartman.modules.workinghour.service.PartWorkingHourService;
import com.qianwen.smartman.modules.workinghour.vo.PartWorkingHourQueryVO;
import com.qianwen.smartman.modules.workinghour.vo.PartWorkingHourVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@Api(value = "工时分析", tags = {"工时分析"})
@RestController
@ApiResource({"workinghour"})
@NonDS
@Validated
public class PartWorkHourController extends BladeController {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private PartWorkingHourService partWorkingHourService;
    @Autowired
    private PartWorkingHourExportService partWorkingHourExportService;
    @PostMapping({"/page"})
    @ApiOperation("查询零件列表分页")
    public R<IPage<PartWorkingHourVO>> page(@RequestBody PartWorkingHourQueryVO queryVO,Query query) {
        //@RequestParam(value = "partNo", required = false) String partNo, @RequestParam(value="workstationName", required = false) String workstationName, @RequestParam("startDate") LocalDate startDate, @RequestParam("endDate") LocalDate endDate
        return R.data(partWorkingHourService.listPage(Condition.getPage(query), queryVO.getPartNo(), queryVO.getWorkstationName(), queryVO.getStartDate(),queryVO.getEndDate()));
    }
    @PostMapping({"/listByIds"})
    @ApiOperation("查询零件列表-按ids")
    public R<List<PartWorkingHourVO>> listByIds(@RequestBody CommonIdsVO idsVO) {
        return R.data(partWorkingHourService.listVOByIds(idsVO.getIds()));
    }
    @GetMapping({"/exportold"})
    @ApiOperation("工时数据导出old")
    public R<BladeFile> exportOld(long id) {
        return R.data(partWorkingHourService.export(id));
    }
    @GetMapping({"/export"})
    @ApiOperation("工时数据导出")
    public R<BladeFile> export(long id) {
        try {
            return R.data(partWorkingHourExportService.export(id));
        } catch (Exception e) {
            log.error("导出公式数据错误",e);
            return R.fail(e.getMessage());
        }
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/controller/PartWorkingProcessController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
package com.qianwen.smartman.modules.workinghour.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.qianwen.core.boot.ctrl.BladeController;
import com.qianwen.core.oss.model.BladeFile;
import com.qianwen.core.scanner.modular.stereotype.ApiResource;
import com.qianwen.core.tenant.annotation.NonDS;
import com.qianwen.core.tool.api.R;
import com.qianwen.smartman.modules.workinghour.service.PartWorkingProcessService;
import com.qianwen.smartman.modules.workinghour.vo.PartWorkingProcessVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@Api(value = "工时分析", tags = {"工时分析"})
@RestController
@ApiResource({"workinghour"})
@NonDS
@Validated
public class PartWorkingProcessController extends BladeController {
    @Autowired
    private PartWorkingProcessService partWorkingProcessService;
    @GetMapping({"/working-process"})
    @ApiOperation("加工过程数据")
    public R<List<PartWorkingProcessVO>> list(long id) {
        return R.data(partWorkingProcessService.listByWorkinghourId(id));
    }
    @GetMapping({"/working-process-export"})
    @ApiOperation("加工过程数据导出")
    public R<BladeFile> export(long id) {
        return R.data(partWorkingProcessService.export(id));
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/convert/PartWorkingHourConvert.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.qianwen.smartman.modules.workinghour.convert;
import java.util.List;
import org.mapstruct.Builder;
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import com.qianwen.smartman.modules.mdc.utils.ConvertUtils;
import com.qianwen.smartman.modules.workinghour.entity.PartWorkingHour;
import com.qianwen.smartman.modules.workinghour.vo.PartWorkingHourVO;
@Mapper(builder = @Builder(disableBuilder = true), imports = {ConvertUtils.class})
public interface PartWorkingHourConvert {
    public static final PartWorkingHourConvert INSTANCE = (PartWorkingHourConvert) Mappers.getMapper(PartWorkingHourConvert.class);
    //@Mappings({@Mapping(target = "alarmTime", expression = "java(ConvertUtils.format(alarm.getTime()))"), @Mapping(target = "alarmCode", source = "code"), @Mapping(target = "alarmMsg", source = "message"), @Mapping(target = "count", expression = "java(ConvertUtils.defaultValue())")})
    @Mappings({})
    PartWorkingHourVO convert(PartWorkingHour pwh);
    @Mappings({})
    List<PartWorkingHourVO> convert(List<PartWorkingHour> alarms);
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/convert/PartWorkingProcessConvert.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.qianwen.smartman.modules.workinghour.convert;
import java.util.List;
import org.mapstruct.Builder;
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import com.qianwen.smartman.modules.mdc.utils.ConvertUtils;
import com.qianwen.smartman.modules.workinghour.entity.PartWorkingProcess;
import com.qianwen.smartman.modules.workinghour.vo.PartWorkingProcessVO;
@Mapper(builder = @Builder(disableBuilder = true), imports = {ConvertUtils.class})
public interface PartWorkingProcessConvert {
    public static final PartWorkingProcessConvert INSTANCE = (PartWorkingProcessConvert) Mappers.getMapper(PartWorkingProcessConvert.class);
    //@Mappings({@Mapping(target = "alarmTime", expression = "java(ConvertUtils.format(alarm.getTime()))"), @Mapping(target = "alarmCode", source = "code"), @Mapping(target = "alarmMsg", source = "message"), @Mapping(target = "count", expression = "java(ConvertUtils.defaultValue())")})
    @Mappings({})
    PartWorkingProcessVO convert(PartWorkingProcess pwh);
    @Mappings({})
    List<PartWorkingProcessVO> convert(List<PartWorkingProcess> housrs);
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/entity/PartWorkingHour.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,170 @@
package com.qianwen.smartman.modules.workinghour.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import com.qianwen.core.tenant.mp.TenantEntity;
/**
 * é›¶ä»¶å·¥æ—¶
 */
@TableName("part_workinghour")
public class PartWorkingHour extends TenantEntity {
    /**
     * é›¶ä»¶ç¼–号
     */
    private String partNo;
    /**
     * å·¥åºå·
     */
    private String processNo;
    /**
     * ç‰ˆæ¬¡
     */
    private String version;
    /**
     * å·¥ä½id
     * */
    private long workstationId;
    /**
     * å¼€å§‹æ—¶é—´*/
    private LocalDateTime startTime;
    /**
     * ç»“束时间
     */
    private LocalDateTime endTime;
    /**
     * å æœºæ—¶é—´(秒)
     */
    private Long occupancySecs;
    /**
     * è£…夹调试时间(秒)
     */
    private Long clampingSecs;
    /**
     * é¦–件切削时间(秒)
     */
    private Long firstWorkingSecs;
    /**
     * æœ«ä»¶æ‹†å¸æ—¶é—´(秒)
     */
    private Long lastRemoveSecs;
    /**
     * é¦–件计量时间(秒)
     */
    private Long firstMeasureSecs;
    /**
     * åŠ å·¥æ—¶é—´(秒)
     */
    private Long processingSecs;
    /**
     * å‡†å¤‡æ—¶é—´(秒)
     */
    private Long prepareSecs;
    /**
     * å•件工时(秒)
     */
    private Long singleProcessSecs;
    /**
     * é›¶ä»¶ç”Ÿäº§æ•°é‡
     */
    private Long amount;
    public String getPartNo() {
        return partNo;
    }
    public void setPartNo(String partNo) {
        this.partNo = partNo;
    }
    public String getProcessNo() {
        return processNo;
    }
    public void setProcessNo(String processNo) {
        this.processNo = processNo;
    }
    public String getVersion() {
        return version;
    }
    public void setVersion(String version) {
        this.version = version;
    }
    public long getWorkstationId() {
        return workstationId;
    }
    public void setWorkstationId(long workstationId) {
        this.workstationId = workstationId;
    }
    public LocalDateTime getStartTime() {
        return startTime;
    }
    public void setStartTime(LocalDateTime startTime) {
        this.startTime = startTime;
    }
    public LocalDateTime getEndTime() {
        return endTime;
    }
    public void setEndTime(LocalDateTime endTime) {
        this.endTime = endTime;
    }
    public Long getOccupancySecs() {
        return occupancySecs;
    }
    public void setOccupancySecs(Long occupancySecs) {
        this.occupancySecs = occupancySecs;
    }
    public Long getClampingSecs() {
        return clampingSecs;
    }
    public void setClampingSecs(Long clampingSecs) {
        this.clampingSecs = clampingSecs;
    }
    public Long getFirstWorkingSecs() {
        return firstWorkingSecs;
    }
    public void setFirstWorkingSecs(Long firstWorkingSecs) {
        this.firstWorkingSecs = firstWorkingSecs;
    }
    public Long getLastRemoveSecs() {
        return lastRemoveSecs;
    }
    public void setLastRemoveSecs(Long lastRemoveSecs) {
        this.lastRemoveSecs = lastRemoveSecs;
    }
    public Long getFirstMeasureSecs() {
        return firstMeasureSecs;
    }
    public void setFirstMeasureSecs(Long firstMeasureSecs) {
        this.firstMeasureSecs = firstMeasureSecs;
    }
    public Long getProcessingSecs() {
        return processingSecs;
    }
    public void setProcessingSecs(Long processingSecs) {
        this.processingSecs = processingSecs;
    }
    public Long getPrepareSecs() {
        return prepareSecs;
    }
    public void setPrepareSecs(Long prepareSecs) {
        this.prepareSecs = prepareSecs;
    }
    public Long getSingleProcessSecs() {
        return singleProcessSecs;
    }
    public void setSingleProcessSecs(Long singleProcessSecs) {
        this.singleProcessSecs = singleProcessSecs;
    }
    public Long getAmount() {
        return amount;
    }
    public void setAmount(Long amount) {
        this.amount = amount;
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/entity/PartWorkingProcess.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
package com.qianwen.smartman.modules.workinghour.entity;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableName;
/**
 * é›¶ä»¶åŠ å·¥è¿‡ç¨‹æ•°æ®
 */
@TableName("part_working_process")
public class PartWorkingProcess{
    long id;
    /**
     * é›¶ä»¶ç¼–号
     */
    private String progName;
    /**
     * å·¥ä½id
     * */
    private long workinghourId;
    /**
     * å¼€å§‹æ—¶é—´*/
    private LocalDateTime startTime;
    /**
     * ç»“束时间
     */
    private LocalDateTime endTime;
    /**
     * è®¾å¤‡çŠ¶æ€
     */
    private Integer deviceStatus;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getProgName() {
        return progName;
    }
    public void setProgName(String progName) {
        this.progName = progName;
    }
    public long getWorkinghourId() {
        return workinghourId;
    }
    public void setWorkinghourId(long workinghourId) {
        this.workinghourId = workinghourId;
    }
    public LocalDateTime getStartTime() {
        return startTime;
    }
    public void setStartTime(LocalDateTime startTime) {
        this.startTime = startTime;
    }
    public LocalDateTime getEndTime() {
        return endTime;
    }
    public void setEndTime(LocalDateTime endTime) {
        this.endTime = endTime;
    }
    public Integer getDeviceStatus() {
        return deviceStatus;
    }
    public void setDeviceStatus(Integer deviceStatus) {
        this.deviceStatus = deviceStatus;
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/excel/PartWorkingHourExcel.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,159 @@
package com.qianwen.smartman.modules.workinghour.excel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import com.qianwen.core.tenant.mp.TenantEntity;
/**
 * é›¶ä»¶å·¥æ—¶
 */
public class PartWorkingHourExcel{
    @ExcelProperty({"零件编号"})
    private String partNo;
    @ExcelProperty({"工序号"})
    private String processNo;
    @ExcelProperty({"版次"})
    private String version;
    @ExcelProperty({"工位"})
    private String workstationName;
    @ExcelProperty({"开始时间"})
    private String startTime;
    @ExcelProperty({"结束时间"})
    private String endTime;
    @ExcelProperty({"占机时间"})
    private String occupancySecs;
    /**
     *
     */
    @ExcelProperty({"装夹调试时间"})
    private String clampingSecs;
    @ExcelProperty({"首件切削时间"})
    private String firstWorkingSecs;
    @ExcelProperty({"末件拆卸时间"})
    private String lastRemoveSecs;
    @ExcelProperty({"首件计量时间"})
    private String firstMeasureSecs;
    @ExcelProperty({"加工时间"})
    private String processingSecs;
    @ExcelProperty({"准备时间"})
    private String prepareSecs;
    @ExcelProperty({"单件工时"})
    private String singleProcessSecs;
    @ExcelProperty({"数量"})
    private Long amount;
    public String getPartNo() {
        return partNo;
    }
    public void setPartNo(String partNo) {
        this.partNo = partNo;
    }
    public String getProcessNo() {
        return processNo;
    }
    public void setProcessNo(String processNo) {
        this.processNo = processNo;
    }
    public String getVersion() {
        return version;
    }
    public void setVersion(String version) {
        this.version = version;
    }
    public String getWorkstationName() {
        return workstationName;
    }
    public void setWorkstationName(String workstationName) {
        this.workstationName = workstationName;
    }
    public String getStartTime() {
        return startTime;
    }
    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }
    public String getEndTime() {
        return endTime;
    }
    public void setEndTime(String endTime) {
        this.endTime = endTime;
    }
    public Long getAmount() {
        return amount;
    }
    public void setAmount(Long amount) {
        this.amount = amount;
    }
    public String getOccupancySecs() {
        return occupancySecs;
    }
    public void setOccupancySecs(String occupancySecs) {
        this.occupancySecs = occupancySecs;
    }
    public String getClampingSecs() {
        return clampingSecs;
    }
    public void setClampingSecs(String clampingSecs) {
        this.clampingSecs = clampingSecs;
    }
    public String getFirstWorkingSecs() {
        return firstWorkingSecs;
    }
    public void setFirstWorkingSecs(String firstWorkingSecs) {
        this.firstWorkingSecs = firstWorkingSecs;
    }
    public String getLastRemoveSecs() {
        return lastRemoveSecs;
    }
    public void setLastRemoveSecs(String lastRemoveSecs) {
        this.lastRemoveSecs = lastRemoveSecs;
    }
    public String getFirstMeasureSecs() {
        return firstMeasureSecs;
    }
    public void setFirstMeasureSecs(String firstMeasureSecs) {
        this.firstMeasureSecs = firstMeasureSecs;
    }
    public String getProcessingSecs() {
        return processingSecs;
    }
    public void setProcessingSecs(String processingSecs) {
        this.processingSecs = processingSecs;
    }
    public String getPrepareSecs() {
        return prepareSecs;
    }
    public void setPrepareSecs(String prepareSecs) {
        this.prepareSecs = prepareSecs;
    }
    public String getSingleProcessSecs() {
        return singleProcessSecs;
    }
    public void setSingleProcessSecs(String singleProcessSecs) {
        this.singleProcessSecs = singleProcessSecs;
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/excel/PartWorkingProcessExcel.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,62 @@
package com.qianwen.smartman.modules.workinghour.excel;
import java.io.Serializable;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
@HeadRowHeight(20)
@ColumnWidth(16)
@ContentRowHeight(18)
public class PartWorkingProcessExcel implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = -5329911071641310785L;
    @ExcelProperty({"程序名称"})
    private String progName;
    @ExcelProperty({"开始时间"})
    private String startTime;
    @ExcelProperty({"结束时间"})
    private String endTime;
    @ExcelProperty({"持续时长"})
    private String duration;
    @ExcelProperty({"状态"})
    private String deviceStateName;
    public String getProgName() {
        return progName;
    }
    public void setProgName(String progName) {
        this.progName = progName;
    }
    public String getStartTime() {
        return startTime;
    }
    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }
    public String getEndTime() {
        return endTime;
    }
    public void setEndTime(String endTime) {
        this.endTime = endTime;
    }
    public String getDuration() {
        return duration;
    }
    public void setDuration(String duration) {
        this.duration = duration;
    }
    public String getDeviceStateName() {
        return deviceStateName;
    }
    public void setDeviceStateName(String deviceStateName) {
        this.deviceStateName = deviceStateName;
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/mapper/PartWorkingHourMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
package com.qianwen.smartman.modules.workinghour.mapper;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.qianwen.core.datascope.annotation.DataAuth;
import com.qianwen.smartman.modules.smis.vo.WorkstationVO;
import com.qianwen.smartman.modules.workinghour.entity.PartWorkingHour;
import com.qianwen.smartman.modules.workinghour.vo.PartWorkingHourVO;
public interface PartWorkingHourMapper extends BaseMapper<PartWorkingHour> {
    /**
     * æŸ¥è¯¢åˆ†é¡µåˆ—表
     * @param page
     * @param partNo
     * @param workstationName
     * @param startDate
     * @param endDate
     * @return
     */
    @DataAuth(code = "workstation")
    List<PartWorkingHourVO> listPage(IPage<PartWorkingHourVO> page, @Param("partNo")String partNo, @Param("workstationName")String workstationName, @Param("startDate")LocalDate startDate, @Param("endDate")LocalDate endDate);
    /**
     * æ ¹æ®id选择记录
     * @param ids
     * @return
     */
    List<PartWorkingHourVO> listVOByIds(List<Long> ids);
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/mapper/PartWorkingProcessMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.qianwen.smartman.modules.workinghour.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qianwen.smartman.modules.workinghour.entity.PartWorkingProcess;
import com.qianwen.smartman.modules.workinghour.vo.PartWorkingProcessVO;
public interface PartWorkingProcessMapper extends BaseMapper<PartWorkingProcess> {
    /**
     * æ ¹æ®id选择记录
     * @param workinghourId å·¥æ—¶è¡¨id
     * @return
     */
    List<PartWorkingProcessVO> listVOByWorkingHourId(Long workinghourId);
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/service/JFreeChartUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,290 @@
package com.qianwen.smartman.modules.workinghour.service;
//import cn.hutool.core.util.StrUtil;
import org.jfree.chart.*;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.category.*;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.ui.*;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.springframework.core.io.ClassPathResource;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.List;
public class JFreeChartUtil {
    public static String NO_DATA_MSG = "数据加载失败";
    /**
     * ç”Ÿæˆä¸»é¢˜
     *
     * @param fontName å­—体名称(默认为宋体)
     * @return
     */
    public static StandardChartTheme createChartTheme(String fontName) throws Exception {
        StandardChartTheme theme = new StandardChartTheme("unicode") {
            public void apply(JFreeChart chart) {
                chart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING,
                        RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
                super.apply(chart);
            }
        };
        theme.setExtraLargeFont(getDefaultFont(Font.PLAIN, 20f));
        theme.setLargeFont(getDefaultFont(Font.PLAIN, 14f));
        theme.setRegularFont(getDefaultFont(Font.PLAIN, 12f));
        theme.setSmallFont(getDefaultFont(Font.PLAIN, 10f));
        return theme;
    }
    /**
     * èŽ·å–é»˜è®¤å­—ä½“
     *
     * @param style
     * @param size  å­—体大小
     * @return
     * @throws Exception
     */
    public static Font getDefaultFont(int style, Float size) throws Exception {
        //获取宋体文件
        //File defaultFontFile = new ClassPathResource("/font/simsun.ttc").getFile();
        //Font defaultFont = Font.createFont(Font.TRUETYPE_FONT, defaultFontFile);
        Font defaultFont = new Font("宋体",style,size.intValue());//yys改
        //defaultFont = defaultFont.deriveFont(style, size);
        return defaultFont;
    }
    /**
     * åˆ›å»ºé¥¼å›¾æ•°æ®é›†åˆ
     *
     * @param legendNameList å›¾ä¾‹åç§°åˆ—表
     * @param dataList       æ•°æ®åˆ—表
     * @return
     */
    public static DefaultPieDataset createDefaultPieDataset(List<String> legendNameList, List<Object> dataList) {
        DefaultPieDataset dataset = new DefaultPieDataset();
        //图例名称列表或数据列表为空
        if (legendNameList == null || legendNameList.size() <= 0 || dataList == null || dataList.size() <= 0) {
            return dataset;
        }
        for (int i = 0; i < legendNameList.size() && legendNameList.size() == dataList.size(); i++) {
            String value = dataList.get(i).toString();
            dataset.setValue(legendNameList.get(i), Double.valueOf(value));
        }
        return dataset;
    }
    /**
     * è®¾ç½®é¥¼çŠ¶å›¾æ¸²æŸ“
     */
    public static void setPieRender(Plot plot) {
        plot.setNoDataMessage(NO_DATA_MSG);
        plot.setInsets(new RectangleInsets(10, 10, 5, 10));
        PiePlot piePlot = (PiePlot) plot;
        piePlot.setInsets(new RectangleInsets(0, 0, 0, 0));
        piePlot.setCircular(true);// åœ†å½¢
        // ç®€å•标签
        piePlot.setLabelGap(0.01);
        piePlot.setInteriorGap(0.05D);
        // å›¾ä¾‹å½¢çж
        piePlot.setLegendItemShape(new Rectangle(10, 10));
        piePlot.setIgnoreNullValues(true);
        // åŽ»æŽ‰æ ‡ç­¾èƒŒæ™¯è‰²
        piePlot.setLabelBackgroundPaint(null);
        //去掉图表背景颜色
        piePlot.setBackgroundPaint(null);
        // åŽ»æŽ‰é˜´å½±
        piePlot.setLabelShadowPaint(null);
        // åŽ»æŽ‰è¾¹æ¡†
        piePlot.setLabelOutlinePaint(null);
        piePlot.setShadowPaint(null);
        // æ˜¾ç¤ºæ ‡ç­¾æ•°æ®
        piePlot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}:{2}"));
    }
    /**
     * åˆ›å»ºç±»åˆ«æ•°æ®é›†åˆ(柱形图、折线图)
     *
     * @param legendNameList å›¾ä¾‹åç§°åˆ—表
     * @param xAxisNameList  x轴名称列表
     * @param dataList       æ•°æ®åˆ—表
     * @return
     */
    public static DefaultCategoryDataset createDefaultCategoryDataset(List<String> legendNameList, List<String> xAxisNameList
            , List<List<Object>> dataList) {//TODO è¿™é‡Œ
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        //图例名称列表、x轴名称列表或数据列表为空
        if (xAxisNameList == null || xAxisNameList.size() <= 0 || legendNameList == null || legendNameList.size() <= 0
                || dataList == null || dataList.size() <= 0) {
            return dataset;
        }
        for (int yAxisIndex = 0; yAxisIndex < legendNameList.size() && legendNameList.size() == dataList.size(); yAxisIndex++) {
            String legendName = legendNameList.get(yAxisIndex);
            List<Object> rowList = dataList.get(yAxisIndex);
            //该组数据不存在或该组数据总数不等于x轴数据数量
            if (rowList == null || rowList.size() != xAxisNameList.size()) {
                continue;
            }
            for (int xAxisIndex = 0; xAxisIndex < rowList.size(); xAxisIndex++) {
                String value = rowList.get(xAxisIndex).toString();
                dataset.setValue(Double.parseDouble(value), legendName, xAxisNameList.get(xAxisIndex));
            }
        }
        return dataset;
    }
    /**
     * è®¾ç½®æŸ±çŠ¶å›¾æ¸²æŸ“
     *
     * @param plot
     * @param isShowDataLabels æ˜¾ç¤ºæ•°æ®å€¼æ ‡è®°
     */
    public static void setBarRenderer(CategoryPlot plot, boolean isShowDataLabels) {
        plot.setNoDataMessage(NO_DATA_MSG);
        plot.setInsets(new RectangleInsets(10, 10, 5, 10));
        BarRenderer renderer = (BarRenderer) plot.getRenderer();
        // è®¾ç½®æŸ±å­æœ€å¤§å®½åº¦
        renderer.setMaximumBarWidth(0.175);
        //设置图表背景颜色(透明)
        plot.setBackgroundPaint(null);
        //显示数据值标记
        if (isShowDataLabels) {
            renderer.setDefaultItemLabelsVisible(true);
        }
        renderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());
        //注意:此句很关键,若无此句,那数字的显示会被覆盖,给人数字没有显示出来的问题
        renderer.setDefaultPositiveItemLabelPosition(new ItemLabelPosition(
                ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_CENTER));
        setXAixs(plot);
        setYAixs(plot);
    }
    /**
     * è®¾ç½®æŠ˜çº¿å›¾æ ·å¼
     *
     * @param plot
     * @param isShowDataLabels æ˜¯å¦æ˜¾ç¤ºæ•°æ®æ ‡ç­¾
     * @param isShapesVisible  æ˜¯å¦æ˜¾ç¤ºæ•°æ®ç‚¹
     */
    public static void setLineRender(CategoryPlot plot, boolean isShowDataLabels, boolean isShapesVisible) {
        plot.setNoDataMessage(NO_DATA_MSG);
        plot.setInsets(new RectangleInsets(10, 10, 0, 10), false);
        LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
        //设置图表背景颜色(透明)
        plot.setBackgroundPaint(null);
        renderer.setDefaultStroke(new BasicStroke(1.5F));
        //显示数据标签
        if (isShowDataLabels) {
            renderer.setDefaultItemLabelsVisible(true);
            renderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator(StandardCategoryItemLabelGenerator.DEFAULT_LABEL_FORMAT_STRING,
                    NumberFormat.getInstance()));
            // ä½ç½®
            renderer.setDefaultPositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE1, TextAnchor.BOTTOM_CENTER));
        }
        // æ•°æ®ç‚¹ç»˜åˆ¶å½¢çж
        renderer.setDefaultShapesVisible(isShapesVisible);
        setXAixs(plot);
        setYAixs(plot);
    }
    /**
     * è®¾ç½®æ•£ç‚¹å›¾æ ·å¼
     *
     * @param plot
     */
    public static void setScatterRender(XYPlot plot) {
        plot.setNoDataMessage(NO_DATA_MSG);
        plot.setInsets(new RectangleInsets(10, 10, 0, 10), false);
        //设置图表背景颜色(透明)
        plot.setBackgroundPaint(null);
        setXAixs(plot);
        setYAixs(plot);
    }
    /**
     * è®¾ç½®ç±»åˆ«å›¾è¡¨(CategoryPlot) X坐标轴线条颜色和样式
     *
     * @param plot
     */
    public static void setXAixs(CategoryPlot plot) {
        Color lineColor = new Color(31, 121, 170);
        // X坐标轴颜色
        plot.getDomainAxis().setAxisLinePaint(lineColor);
        // X坐标轴标记|竖线颜色
        plot.getDomainAxis().setTickMarkPaint(lineColor);
    }
    /**
     * è®¾ç½®å›¾è¡¨(XYPlot) X坐标轴线条颜色和样式
     *
     * @param plot
     */
    public static void setXAixs(XYPlot plot) {
        Color lineColor = new Color(31, 121, 170);
        // X坐标轴颜色
        plot.getDomainAxis().setAxisLinePaint(lineColor);
        // X坐标轴标记|竖线颜色
        plot.getDomainAxis().setTickMarkPaint(lineColor);
        // x轴网格线条
        plot.setDomainGridlinePaint(new Color(192, 192, 192));
    }
    /**
     * è®¾ç½®ç±»åˆ«å›¾è¡¨(CategoryPlot) Y坐标轴线条颜色和样式 åŒæ—¶é˜²æ­¢æ•°æ®æ— æ³•显示
     *
     * @param plot
     */
    public static void setYAixs(CategoryPlot plot) {
        Color lineColor = new Color(192, 208, 224);
        ValueAxis axis = plot.getRangeAxis();
        // Y坐标轴颜色
        axis.setAxisLinePaint(lineColor);
        // Y坐标轴标记|竖线颜色
        axis.setTickMarkPaint(lineColor);
        // éšè—Y刻度
        axis.setAxisLineVisible(false);
        axis.setTickMarksVisible(false);
        // Y轴网格线条
        plot.setRangeGridlinePaint(new Color(192, 192, 192));
        plot.setRangeGridlineStroke(new BasicStroke(1));
        // è®¾ç½®é¡¶éƒ¨Y坐标轴间距,防止数据无法显示
        plot.getRangeAxis().setUpperMargin(0.1);
        // è®¾ç½®åº•部Y坐标轴间距
        plot.getRangeAxis().setLowerMargin(0.1);
    }
    /**
     * è®¾ç½®å›¾è¡¨(XYPlot) Y坐标轴线条颜色和样式 åŒæ—¶é˜²æ­¢æ•°æ®æ— æ³•显示
     *
     * @param plot
     */
    public static void setYAixs(XYPlot plot) {
        Color lineColor = new Color(192, 208, 224);
        ValueAxis axis = plot.getRangeAxis();
        // Y坐标轴颜色
        axis.setAxisLinePaint(lineColor);
        // Y坐标轴标记|竖线颜色
        axis.setTickMarkPaint(lineColor);
        // éšè—Y刻度
        axis.setAxisLineVisible(false);
        axis.setTickMarksVisible(false);
        // Y轴网格线条
        plot.setRangeGridlinePaint(new Color(192, 192, 192));
        // è®¾ç½®é¡¶éƒ¨Y坐标轴间距,防止数据无法显示
        plot.getRangeAxis().setUpperMargin(0.1);
        // è®¾ç½®åº•部Y坐标轴间距
        plot.getRangeAxis().setLowerMargin(0.1);
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/service/PartWorkingHourExportService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,378 @@
package com.qianwen.smartman.modules.workinghour.service;
import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.block.BlockBorder;
import org.jfree.chart.labels.AbstractCategoryItemLabelGenerator;
import org.jfree.chart.labels.CategoryItemLabelGenerator;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.StackedBarRenderer;
import org.jfree.chart.ui.RectangleEdge;
import org.jfree.chart.ui.RectangleInsets;
import org.jfree.chart.ui.TextAnchor;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qianwen.core.excel.util.ExcelUtil;
import com.qianwen.core.mp.base.BaseServiceImpl;
import com.qianwen.core.oss.model.BladeFile;
import com.qianwen.core.tool.utils.DateUtil;
import com.qianwen.smartman.common.enums.DefaultWcsEnum;
import com.qianwen.smartman.common.utils.DurationUtil;
import com.qianwen.smartman.modules.resource.builder.oss.OssBuilder;
import com.qianwen.smartman.modules.smis.entity.Workstation;
import com.qianwen.smartman.modules.smis.mapper.WorkstationMapper;
import com.qianwen.smartman.modules.workinghour.entity.PartWorkingHour;
import com.qianwen.smartman.modules.workinghour.entity.PartWorkingProcess;
import com.qianwen.smartman.modules.workinghour.excel.PartWorkingHourExcel;
import com.qianwen.smartman.modules.workinghour.mapper.PartWorkingHourMapper;
import com.qianwen.smartman.modules.workinghour.mapper.PartWorkingProcessMapper;
import cn.hutool.core.date.LocalDateTimeUtil;
@Service
public class PartWorkingHourExportService extends BaseServiceImpl<PartWorkingHourMapper, PartWorkingHour> {
    @Autowired
    private PartWorkingHourMapper partWorkingHourMapper;
    @Autowired
    private WorkstationMapper workstationMapper;
    @Autowired
    private PartWorkingProcessMapper partWorkingProcessMapper;
    @Autowired
    private OssBuilder ossBuilder;
    /**
     * å¯¼å‡ºä¸€æ¡æ•°æ®
     *
     * @param id
     * @return
     * @throws IOException
     */
    @Transactional(readOnly = true)
    public BladeFile export(long id) throws Exception {
        // QueryWrapper<PartWorkingProcess> wrapper = new QueryWrapper<>();
        // wrapper.lambda().eq(PartWorkingProcess::getWorkinghourId, id);
        // xx工件在x机床
        PartWorkingHour partWorkingHour = partWorkingHourMapper.selectById(id);
        Workstation ws = workstationMapper.selectById(partWorkingHour.getWorkstationId());
        String fileName = String.format("零件%s的工时数据-%s.xlsx", partWorkingHour.getPartNo(), DateUtil.time());
        PartWorkingHourExcel excelObj = new PartWorkingHourExcel();
        excelObj.setPartNo(partWorkingHour.getPartNo());
        excelObj.setAmount(partWorkingHour.getAmount());
        LocalDateTime start = LocalDateTime.now();
        LocalDateTime end;
        Duration duration;
        if (partWorkingHour.getClampingSecs() != null) {
            end = start.plusSeconds(partWorkingHour.getClampingSecs());
            duration = Duration.between(start, end);
            excelObj.setClampingSecs(DurationUtil.toChineseDuration(duration));
        }
        final String format = "yyyy-MM-dd:hh:mm:ss";
        if (partWorkingHour.getEndTime() != null) {
            excelObj.setEndTime(LocalDateTimeUtil.format(partWorkingHour.getEndTime(), format));
        }
        if (partWorkingHour.getFirstMeasureSecs() != null) {
            end = start.plusSeconds(partWorkingHour.getFirstMeasureSecs());
            duration = Duration.between(start, end);
            excelObj.setFirstMeasureSecs(DurationUtil.toChineseDuration(duration));
        }
        if (partWorkingHour.getFirstWorkingSecs() != null) {
            end = start.plusSeconds(partWorkingHour.getFirstWorkingSecs());
            duration = Duration.between(start, end);
            excelObj.setFirstWorkingSecs(DurationUtil.toChineseDuration(duration));
        }
        if (partWorkingHour.getLastRemoveSecs() != null) {
            end = start.plusSeconds(partWorkingHour.getLastRemoveSecs());
            duration = Duration.between(start, end);
            excelObj.setLastRemoveSecs(DurationUtil.toChineseDuration(duration));
        }
        if (partWorkingHour.getOccupancySecs() != null) {
            end = start.plusSeconds(partWorkingHour.getOccupancySecs());
            duration = Duration.between(start, end);
            excelObj.setOccupancySecs(DurationUtil.toChineseDuration(duration));
        }
        excelObj.setPartNo(partWorkingHour.getPartNo());
        if (partWorkingHour.getPrepareSecs() != null) {
            end = start.plusSeconds(partWorkingHour.getPrepareSecs());
            duration = Duration.between(start, end);
            excelObj.setPrepareSecs(DurationUtil.toChineseDuration(duration));
        }
        if (partWorkingHour.getProcessingSecs() != null) {
            end = start.plusSeconds(partWorkingHour.getProcessingSecs());
            duration = Duration.between(start, end);
            excelObj.setProcessingSecs(DurationUtil.toChineseDuration(duration));
        }
        excelObj.setProcessNo(partWorkingHour.getProcessNo());
        if (partWorkingHour.getSingleProcessSecs() != null) {
            end = start.plusSeconds(partWorkingHour.getSingleProcessSecs());
            duration = Duration.between(start, end);
            excelObj.setSingleProcessSecs(DurationUtil.toChineseDuration(duration));
        }
        excelObj.setStartTime(LocalDateTimeUtil.format(partWorkingHour.getStartTime(), format));
        excelObj.setWorkstationName(ws.getName());
        excelObj.setVersion(partWorkingHour.getVersion());
        MultipartFile multipartFile = ExcelUtil.exportToMultipartFile(fileName, "零件工时", Arrays.asList(excelObj),
                PartWorkingHourExcel.class);
        MultipartFile multipartFile2 = writeChart(id,multipartFile);
        BladeFile bladeFile = this.ossBuilder.tempTemplate().putFile(multipartFile2.getOriginalFilename(),
                multipartFile2);
        return bladeFile;
    }
    /**
     * åˆ›å»ºå›¾è¡¨
     * @param workinghourId
     * @param multipartFile
     * @return
     * @throws Exception
     */
    MultipartFile writeChart(long workinghourId,MultipartFile multipartFile) throws Exception {
        XSSFWorkbook workbook = new XSSFWorkbook(multipartFile.getInputStream());
        byte[] chartBytes = barChart(workinghourId);
        addPicture(workbook, chartBytes);
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
        FileItem fileItem = factory.createItem("excel", multipartFile.getContentType(), true,
                multipartFile.getOriginalFilename());
        workbook.write(fileItem.getOutputStream());
        workbook.close();
        return new CommonsMultipartFile(fileItem);
    }
    public static void addPicture(XSSFWorkbook wb, byte[] bytes) {
        XSSFSheet sheet = wb.getSheetAt(0);
        // ç”»å›¾çš„顶级管理器,一个sheet只能获取一个(一定要注意这点)
        // HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
        XSSFDrawing patriarch = sheet.createDrawingPatriarch();
        // è®¾ç½®å›¾ç‰‡ä½ç½®
        // å…«ä¸ªå‚æ•°, å‰å››ä¸ªè¡¨ç¤ºå›¾ç‰‡ç¦»èµ·å§‹å•元格和结束单元格边缘的位置,
        // åŽå››ä¸ªè¡¨ç¤ºèµ·å§‹å’Œç»“束单元格的位置, å¦‚下表示从第2列到第12列, ä»Žç¬¬1行到第15行,需要注意excel起始位置是0
        // {0,0,0,0,2,1,12,15}表示从第2列到第12列,从第1行到第15行,单元格内部的边距都是0
        // {0,0,0,0,1,4,20,5}表示从第2列到第12列,从第1行到第15行,单元格内部的边距都是0
        // HSSFClientAnchor anchor = new HSSFClientAnchor(anchors[0], anchors[1],
        // anchors[2], anchors[3], (short) anchors[4], anchors[5], (short) anchors[6],
        // anchors[7]);
        XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, 0, 3, 30, 10); // 1列-30列;3行-10行
        anchor.setAnchorType(AnchorType.DONT_MOVE_AND_RESIZE);
        // æ’入图片
        int pictureIndex = wb.addPicture(bytes, XSSFWorkbook.PICTURE_TYPE_JPEG);
        // XSSFWorkbook.PICTURE_TYPE_JPEG
        patriarch.createPicture(anchor, pictureIndex);
    }
    public byte[] barChart(long workinghourId) throws Exception {
        // è®¾ç½®æŸ±å­æ˜¾ç¤ºå¯¹åº”的数值
        QueryWrapper<PartWorkingProcess> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PartWorkingProcess::getWorkinghourId, workinghourId).orderByAsc(PartWorkingProcess::getStartTime);
        List<PartWorkingProcess> processList = partWorkingProcessMapper.selectList(wrapper);
        // æ”¯æŒæ ‡ç­¾æ˜¾ç¤ºçš„æ‰€æœ‰åˆ—数据
        List<List<Object>> dataList = new ArrayList<>();
        Duration duration;
        PartWorkingProcess process;
        for(int i=0;i<processList.size();i++) {
            //dataList.add(new ArrayList<>(Arrays.asList(133)));
            process = processList.get(i);
            duration = Duration.between(process.getStartTime(), process.getEndTime());
            dataList.add(Arrays.asList(duration.getSeconds()));
            //dataTable.add(new ArrayList<>(Arrays.asList(process.getProgName(), duration.getSeconds(), process.getDeviceStatus())));
        }
        JFreeChart chart = createStackedBarChart(workinghourId,"加工记录", dataList,processList,
                JFreeChartUtil.createChartTheme("宋体"), "秒", "");
        StackedBarRenderer renderer = new StackedBarRenderer();
        CategoryPlot plot = chart.getCategoryPlot();
        plot.setOutlineVisible(true);
        //dataTable.add(new ArrayList<>(Arrays.asList("YZL4-1100-01-50-A-2-2", 242, "运行")));
        renderer.setDefaultItemLabelsVisible(true);
        renderer.setDefaultItemLabelGenerator(new MyCategoryItemLabelGenerator(processList));
        renderer.setMaximumBarWidth(0.3);
        // æŸ±å­é¢œè‰²,有几段就set几个
        Color color;
        String colorStr;
        DefaultWcsEnum wcsEnum;
        for(int i=0;i<processList.size();i++) {
            process = processList.get(i);
            //if(dataTable.get(i))
            //color =
            wcsEnum = DefaultWcsEnum.of(process.getDeviceStatus());
            colorStr = StringUtils.removeStart(wcsEnum.getColor(), '#');
            color  = new Color(Integer.parseInt(colorStr, 16));
            renderer.setSeriesPaint(i, color);
        }
        //renderer.setSeriesPaint(0, Color.green);
        //renderer.setSeriesPaint(1, Color.yellow);
        ItemLabelPosition posi = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.HALF_ASCENT_CENTER);
        //renderer.setDefaultNegativeItemLabelPosition(posi);
        renderer.setDefaultPositiveItemLabelPosition(posi);
        int offset = 10;
        renderer.setItemLabelInsets(new RectangleInsets(0, offset, offset, offset));
        plot.setRenderer(renderer);
        java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
        ChartUtils.writeChartAsJPEG(bos, 1.0f, chart, 4096, 400, null);
        return bos.toByteArray();
    }
    /**
     * åˆ›å»ºå †å æŸ±çж图
     * @param workinghourId
     * @param chartTitle
     * @param legendNameList
     * @param xAxisNameList
     * @param dataList
     * @param theme
     * @param yAxisTitle
     * @param xAxisTitle
     * @return
     * @throws Exception
     */
    JFreeChart createStackedBarChart(long workinghourId,String chartTitle, List<List<Object>> dataList,List<PartWorkingProcess> processList,
             StandardChartTheme theme, String yAxisTitle, String xAxisTitle)
            throws Exception {
        // è®¾ç½®ä¸»é¢˜ï¼Œé˜²æ­¢ä¸­æ–‡ä¹±ç 
        theme = theme == null ? JFreeChartUtil.createChartTheme("") : theme;
        ChartFactory.setChartTheme(theme);
        boolean showLegend =false;
        //List<String> pnamelist = processList.stream().map(p -> p.getProgName()).collect(Collectors.toList());
        //DefaultCategoryDataset dataset = JFreeChartUtil.createDefaultCategoryDataset(pnamelist, Arrays.asList("xname"), dataList);
        DefaultCategoryDataset dataset = createDataSet(processList);
        JFreeChart chart = ChartFactory.createStackedBarChart(chartTitle, xAxisTitle, yAxisTitle,
                dataset,
                PlotOrientation.HORIZONTAL, showLegend, true, false);
        // è®¾ç½®æŠ—锯齿,防止字体显示不清楚
        chart.setTextAntiAlias(false);
        // å¯¹æŸ±å­è¿›è¡Œæ¸²æŸ“
        JFreeChartUtil.setBarRenderer(chart.getCategoryPlot(), true);
        //showLegend=false情况下,下列代码会引起NPE
        // è®¾ç½®æ ‡æ³¨æ— è¾¹æ¡†
        //chart.getLegend().setFrame(new BlockBorder(Color.WHITE));
        // æ ‡æ³¨ä½äºŽä¸Šä¾§
        //chart.getLegend().setPosition(RectangleEdge.TOP);
        return chart;
    }
    DefaultCategoryDataset createDataSet(List<PartWorkingProcess> processList){
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        PartWorkingProcess p;
         for (int xAxisIndex = 0; xAxisIndex < processList.size(); xAxisIndex++) {
             p = processList.get(xAxisIndex);
             //String value = rowList.get(xAxisIndex).toString();
             String value =p.getStartTime().toString();
             Duration duration = Duration.between(p.getStartTime(), p.getEndTime());
             value = duration.getSeconds()+"";
             dataset.setValue(Double.parseDouble(value), xAxisIndex+"", "程序时段");
         }
         return dataset;
    }
}
//自定义标签生成
class MyCategoryItemLabelGenerator extends AbstractCategoryItemLabelGenerator implements CategoryItemLabelGenerator {
    // private final Integer category;
    private List<PartWorkingProcess> dataTable;
    public MyCategoryItemLabelGenerator(List<PartWorkingProcess> dataTable) {
        super("", NumberFormat.getInstance());
        this.dataTable = dataTable;
    }
    @Override
    public String generateLabel(CategoryDataset dataset, int row, int column) {
        //Number val = dataset.getValue(row, column);
        PartWorkingProcess dataRow = this.dataTable.get(row);
        // dataset.
        /*
        ALARM(1, "报警"),
        RUNNING(2, "运行"),
        STANDBY(3, "待机"),
        OFFLINE(4, "离线"),
        DEBUGGING(5, "调试");
        */
        //DefaultWcsEnum wcsEnum = DefaultWcsEnum.of(dataRow.getDeviceStatus());
        //return dataRow.getProgName() + ",:" + val + "," + wcsEnum.getName();
        Duration duration = Duration.between(dataRow.getStartTime(), dataRow.getEndTime());
        return dataRow.getProgName() + "," + DurationUtil.toChineseDuration(duration);
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/service/PartWorkingHourService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,148 @@
package com.qianwen.smartman.modules.workinghour.service;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.qianwen.core.excel.util.ExcelUtil;
import com.qianwen.core.mp.base.BaseServiceImpl;
import com.qianwen.core.oss.model.BladeFile;
import com.qianwen.core.tool.utils.DateUtil;
import com.qianwen.smartman.common.enums.DefaultWcsEnum;
import com.qianwen.smartman.common.utils.DurationUtil;
import com.qianwen.smartman.modules.resource.builder.oss.OssBuilder;
import com.qianwen.smartman.modules.smis.entity.Workstation;
import com.qianwen.smartman.modules.smis.mapper.WorkstationMapper;
import com.qianwen.smartman.modules.workinghour.entity.PartWorkingHour;
import com.qianwen.smartman.modules.workinghour.entity.PartWorkingProcess;
import com.qianwen.smartman.modules.workinghour.excel.PartWorkingHourExcel;
import com.qianwen.smartman.modules.workinghour.excel.PartWorkingProcessExcel;
import com.qianwen.smartman.modules.workinghour.mapper.PartWorkingHourMapper;
import com.qianwen.smartman.modules.workinghour.vo.PartWorkingHourVO;
import cn.hutool.core.date.LocalDateTimeUtil;
@Service
public class PartWorkingHourService extends BaseServiceImpl<PartWorkingHourMapper, PartWorkingHour>{
    @Autowired
    private PartWorkingHourMapper partWorkingHourMapper;
    @Autowired
    private WorkstationMapper workstationMapper;
    @Autowired
    private OssBuilder ossBuilder;
    @Transactional(readOnly=true)
    public IPage<PartWorkingHourVO> listPage(IPage<PartWorkingHourVO> workstationVOIPage, String partNo, String workstationName, LocalDate startDate, LocalDate endDate) {
        List<PartWorkingHourVO> workstationVOS = this.partWorkingHourMapper.listPage(workstationVOIPage, partNo, workstationName, startDate, endDate);
        return workstationVOIPage.setRecords(workstationVOS);
    }
    @Transactional(readOnly=true)
    public List<PartWorkingHourVO> listVOByIds(List<Long> ids) {
        return partWorkingHourMapper.listVOByIds(ids);
    }
    /**
     * å¯¼å‡ºä¸€æ¡æ•°æ®
     * @param id
     * @return
     */
    @Transactional(readOnly=true)
       public BladeFile export(long id) {
        //QueryWrapper<PartWorkingProcess> wrapper = new QueryWrapper<>();
        //wrapper.lambda().eq(PartWorkingProcess::getWorkinghourId, id);
        //xx工件在x机床
        PartWorkingHour partWorkingHour = partWorkingHourMapper.selectById(id);
        Workstation ws = workstationMapper.selectById(partWorkingHour.getWorkstationId());
        String fileName = String.format("零件%s的工时数据-%s.xlsx", partWorkingHour.getPartNo(), DateUtil.time());
        PartWorkingHourExcel excelObj = new PartWorkingHourExcel();
        excelObj.setPartNo(partWorkingHour.getPartNo());
        excelObj.setAmount(partWorkingHour.getAmount());
        LocalDateTime start = LocalDateTime.now();
        LocalDateTime end;
        Duration duration;
        if(partWorkingHour.getClampingSecs() !=null) {
            end = start.plusSeconds(partWorkingHour.getClampingSecs());
            duration = Duration.between(start, end);
            excelObj.setClampingSecs(DurationUtil.toChineseDuration(duration));
        }
        final String format =  "yyyy-MM-dd:hh:mm:ss";
        if(partWorkingHour.getEndTime() !=null) {
            excelObj.setEndTime(LocalDateTimeUtil.format(partWorkingHour.getEndTime(),format));
        }
        if(partWorkingHour.getFirstMeasureSecs() !=null) {
            end = start.plusSeconds(partWorkingHour.getFirstMeasureSecs());
            duration = Duration.between(start, end);
            excelObj.setFirstMeasureSecs(DurationUtil.toChineseDuration(duration));
        }
        if(partWorkingHour.getFirstWorkingSecs() !=null) {
            end = start.plusSeconds(partWorkingHour.getFirstWorkingSecs());
            duration = Duration.between(start, end);
            excelObj.setFirstWorkingSecs(DurationUtil.toChineseDuration(duration));
        }
        if(partWorkingHour.getLastRemoveSecs() !=null) {
            end = start.plusSeconds(partWorkingHour.getLastRemoveSecs());
            duration = Duration.between(start, end);
            excelObj.setLastRemoveSecs(DurationUtil.toChineseDuration(duration));
        }
        if(partWorkingHour.getOccupancySecs() !=null) {
            end = start.plusSeconds(partWorkingHour.getOccupancySecs());
            duration = Duration.between(start, end);
            excelObj.setOccupancySecs(DurationUtil.toChineseDuration(duration));
        }
        excelObj.setPartNo(partWorkingHour.getPartNo());
        if(partWorkingHour.getPrepareSecs() !=null) {
            end = start.plusSeconds(partWorkingHour.getPrepareSecs());
            duration = Duration.between(start, end);
            excelObj.setPrepareSecs(DurationUtil.toChineseDuration(duration));
        }
        if(partWorkingHour.getProcessingSecs() !=null) {
            end = start.plusSeconds(partWorkingHour.getProcessingSecs());
            duration = Duration.between(start, end);
            excelObj.setProcessingSecs(DurationUtil.toChineseDuration(duration));
        }
        excelObj.setProcessNo(partWorkingHour.getProcessNo());
        if(partWorkingHour.getSingleProcessSecs() !=null) {
            end = start.plusSeconds(partWorkingHour.getSingleProcessSecs());
            duration = Duration.between(start, end);
            excelObj.setSingleProcessSecs(DurationUtil.toChineseDuration(duration));
        }
        excelObj.setStartTime(LocalDateTimeUtil.format(partWorkingHour.getStartTime(),format));
        excelObj.setWorkstationName(ws.getName());
        excelObj.setVersion(partWorkingHour.getVersion());
        MultipartFile multipartFile = ExcelUtil.exportToMultipartFile(fileName, "零件工时", Arrays.asList(excelObj), PartWorkingHourExcel.class);
        BladeFile bladeFile = this.ossBuilder.tempTemplate().putFile(multipartFile.getOriginalFilename(), multipartFile);
        return bladeFile;
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/service/PartWorkingProcessService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
package com.qianwen.smartman.modules.workinghour.service;
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qianwen.core.excel.util.ExcelUtil;
import com.qianwen.core.oss.model.BladeFile;
import com.qianwen.core.tool.utils.DateUtil;
import com.qianwen.smartman.common.enums.DefaultWcsEnum;
import com.qianwen.smartman.common.utils.DurationUtil;
import com.qianwen.smartman.modules.resource.builder.oss.OssBuilder;
import com.qianwen.smartman.modules.smis.entity.Workstation;
import com.qianwen.smartman.modules.smis.excel.WorkstationExcel;
import com.qianwen.smartman.modules.smis.mapper.WorkstationMapper;
import com.qianwen.smartman.modules.workinghour.convert.PartWorkingProcessConvert;
import com.qianwen.smartman.modules.workinghour.entity.PartWorkingHour;
import com.qianwen.smartman.modules.workinghour.entity.PartWorkingProcess;
import com.qianwen.smartman.modules.workinghour.excel.PartWorkingProcessExcel;
import com.qianwen.smartman.modules.workinghour.mapper.PartWorkingHourMapper;
import com.qianwen.smartman.modules.workinghour.mapper.PartWorkingProcessMapper;
import com.qianwen.smartman.modules.workinghour.vo.PartWorkingProcessVO;
@Service
public class PartWorkingProcessService{
    @Autowired
    private PartWorkingProcessMapper partWorkingProcessMapper;
    @Autowired
    private WorkstationMapper workstationMapper;
    @Autowired
    private PartWorkingHourMapper partWorkingHourMapper;
    @Autowired
    private OssBuilder ossBuilder;
    @Transactional(readOnly=true)
    public List<PartWorkingProcessVO> listByWorkinghourId(Long workinghourId) {
        QueryWrapper<PartWorkingProcess> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PartWorkingProcess::getWorkinghourId, workinghourId).orderByAsc(PartWorkingProcess::getStartTime);
        return PartWorkingProcessConvert.INSTANCE.convert(partWorkingProcessMapper.selectList(wrapper));
    }
    /**
     * åŠ å·¥è¿‡ç¨‹æ•°æ®å¯¼å‡º
     * @param id
     * @return
     */
    @Transactional(readOnly=true)
    public BladeFile export(long workinghourId) {
        QueryWrapper<PartWorkingProcess> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PartWorkingProcess::getWorkinghourId, workinghourId).orderByAsc(PartWorkingProcess::getStartTime);
        List<PartWorkingProcess> data = partWorkingProcessMapper.selectList(wrapper);
        List<PartWorkingProcessExcel> exportList = data.stream().map(p -> {
            PartWorkingProcessExcel e = new PartWorkingProcessExcel();
            e.setProgName(p.getProgName());
            e.setStartTime(p.getStartTime().toString());
            e.setEndTime(p.getEndTime().toString());
            Duration duration = Duration.between(p.getStartTime(), p.getEndTime());
            e.setDuration(DurationUtil.toChineseDuration(duration));
            e.setDeviceStateName(DefaultWcsEnum.of(p.getDeviceStatus()).getName());
            return e;
        }).collect(Collectors.toList());
        //xx工件在x机床
        PartWorkingHour partWorkingHour = partWorkingHourMapper.selectById(workinghourId);
        Workstation ws = workstationMapper.selectById(partWorkingHour.getWorkstationId());
        String fileName = String.format("%s的加工记录-%s.xlsx", ws.getName(), DateUtil.time());
        MultipartFile multipartFile = ExcelUtil.exportToMultipartFile(fileName, "加工记录表", exportList, PartWorkingProcessExcel.class);
        BladeFile bladeFile = this.ossBuilder.tempTemplate().putFile(multipartFile.getOriginalFilename(), multipartFile);
        return bladeFile;
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/vo/PartWorkingHourQueryVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
package com.qianwen.smartman.modules.workinghour.vo;
import java.time.LocalDate;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModelProperty;
/**
 * é›¶ä»¶å·¥æ—¶VO
 */
public class PartWorkingHourQueryVO {
    @ApiModelProperty("零件编号")
    private String partNo;
    @ApiModelProperty("工位名称")
    private String workstationName;
    @ApiModelProperty("开始时间")
    private LocalDate startDate;
    @ApiModelProperty("结束时间")
    private LocalDate endDate;
    public String getPartNo() {
        return partNo;
    }
    public void setPartNo(String partNo) {
        this.partNo = partNo;
    }
    public String getWorkstationName() {
        return workstationName;
    }
    public void setWorkstationName(String workstationName) {
        this.workstationName = workstationName;
    }
    public LocalDate getStartDate() {
        return startDate;
    }
    public void setStartDate(LocalDate startDate) {
        this.startDate = startDate;
    }
    public LocalDate getEndDate() {
        return endDate;
    }
    public void setEndDate(LocalDate endDate) {
        this.endDate = endDate;
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/vo/PartWorkingHourVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,168 @@
package com.qianwen.smartman.modules.workinghour.vo;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModelProperty;
/**
 * é›¶ä»¶å·¥æ—¶VO
 */
public class PartWorkingHourVO {
    long id;
    /**
     * é›¶ä»¶ç¼–号
     */
    @ApiModelProperty("零件编号")
    private String partNo;
    @ApiModelProperty("工序号")
    private String processNo;
    @ApiModelProperty("版次")
    private String version;
    @ApiModelProperty("工位id")
    private long workstationId;
    @ApiModelProperty("工位名称")
    private String workstationName;
    @ApiModelProperty("开始时间")
    private LocalDateTime startTime;
    @ApiModelProperty("结束时间")
    private LocalDateTime endTime;
    @ApiModelProperty("占机时间(秒)")
    private Long occupancySecs;
    @ApiModelProperty("装夹调试时间(秒)")
    private Long clampingSecs;
    @ApiModelProperty("首件切削时间(秒)")
    private Long firstWorkingSecs;
    @ApiModelProperty("末件拆卸时间(秒)")
    private Long lastRemoveSecs;
    @ApiModelProperty("首件计量时间(秒)")
    private Long firstMeasureSecs;
    @ApiModelProperty("加工时间(秒)")
    private Long processingSecs;
    @ApiModelProperty("准备时间(秒)")
    private Long prepareSecs;
    @ApiModelProperty(" å•件工时(秒)")
    private Long singleProcessSecs;
    @ApiModelProperty("数量")
    private Long amount;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getPartNo() {
        return partNo;
    }
    public void setPartNo(String partNo) {
        this.partNo = partNo;
    }
    public String getProcessNo() {
        return processNo;
    }
    public void setProcessNo(String processNo) {
        this.processNo = processNo;
    }
    public String getVersion() {
        return version;
    }
    public void setVersion(String version) {
        this.version = version;
    }
    public long getWorkstationId() {
        return workstationId;
    }
    public void setWorkstationId(long workstationId) {
        this.workstationId = workstationId;
    }
    public LocalDateTime getStartTime() {
        return startTime;
    }
    public void setStartTime(LocalDateTime startTime) {
        this.startTime = startTime;
    }
    public LocalDateTime getEndTime() {
        return endTime;
    }
    public void setEndTime(LocalDateTime endTime) {
        this.endTime = endTime;
    }
    public Long getOccupancySecs() {
        return occupancySecs;
    }
    public void setOccupancySecs(Long occupancySecs) {
        this.occupancySecs = occupancySecs;
    }
    public Long getClampingSecs() {
        return clampingSecs;
    }
    public void setClampingSecs(Long clampingSecs) {
        this.clampingSecs = clampingSecs;
    }
    public Long getFirstWorkingSecs() {
        return firstWorkingSecs;
    }
    public void setFirstWorkingSecs(Long firstWorkingSecs) {
        this.firstWorkingSecs = firstWorkingSecs;
    }
    public Long getLastRemoveSecs() {
        return lastRemoveSecs;
    }
    public void setLastRemoveSecs(Long lastRemoveSecs) {
        this.lastRemoveSecs = lastRemoveSecs;
    }
    public Long getFirstMeasureSecs() {
        return firstMeasureSecs;
    }
    public void setFirstMeasureSecs(Long firstMeasureSecs) {
        this.firstMeasureSecs = firstMeasureSecs;
    }
    public Long getPrepareSecs() {
        return prepareSecs;
    }
    public void setPrepareSecs(Long prepareSecs) {
        this.prepareSecs = prepareSecs;
    }
    public Long getSingleProcessSecs() {
        return singleProcessSecs;
    }
    public void setSingleProcessSecs(Long singleProcessSecs) {
        this.singleProcessSecs = singleProcessSecs;
    }
    public Long getAmount() {
        return amount;
    }
    public void setAmount(Long amount) {
        this.amount = amount;
    }
    public String getWorkstationName() {
        return workstationName;
    }
    public void setWorkstationName(String workstationName) {
        this.workstationName = workstationName;
    }
    public Long getProcessingSecs() {
        return processingSecs;
    }
    public void setProcessingSecs(Long processingSecs) {
        this.processingSecs = processingSecs;
    }
}
smart-man-boot/src/main/java/com/qianwen/smartman/modules/workinghour/vo/PartWorkingProcessVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,65 @@
package com.qianwen.smartman.modules.workinghour.vo;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModelProperty;
/**
 * é›¶ä»¶å·¥æ—¶VO
 */
public class PartWorkingProcessVO {
    long id;
    @ApiModelProperty("程序名称")
    private String progName;
    @ApiModelProperty("工时表id")
    private long workinghourId;
    @ApiModelProperty("开始时间")
    private LocalDateTime startTime;
    @ApiModelProperty("结束时间")
    private LocalDateTime endTime;
    @ApiModelProperty("设备状态")
    private Integer deviceStatus;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getProgName() {
        return progName;
    }
    public void setProgName(String progName) {
        this.progName = progName;
    }
    public long getWorkinghourId() {
        return workinghourId;
    }
    public void setWorkinghourId(long workinghourId) {
        this.workinghourId = workinghourId;
    }
    public LocalDateTime getStartTime() {
        return startTime;
    }
    public void setStartTime(LocalDateTime startTime) {
        this.startTime = startTime;
    }
    public LocalDateTime getEndTime() {
        return endTime;
    }
    public void setEndTime(LocalDateTime endTime) {
        this.endTime = endTime;
    }
    public Integer getDeviceStatus() {
        return deviceStatus;
    }
    public void setDeviceStatus(Integer deviceStatus) {
        this.deviceStatus = deviceStatus;
    }
}
smart-man-boot/src/main/resources/com/qianwen/smartman/modules/workinghour/mapper/PartWorkingHourMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
<?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.qianwen.smartman.modules.workinghour.mapper.PartWorkingHourMapper">
    <select id="listPage" resultType="com.qianwen.smartman.modules.workinghour.vo.PartWorkingHourVO">
        SELECT
        h.id,
        h.part_no,
        process_no,
    version,
    workstation_id,
    ws.name as workstation_name,
    start_time,
    end_time,
    occupancy_secs,
    clamping_secs,
    first_working_secs,
    last_remove_secs,
    first_measure_secs,
     processing_secs,
    prepare_secs,
    single_process_secs,
        h.amount
        FROM part_workinghour h
        LEFT JOIN blade_workstation ws on h.workstation_id=ws.id
        <where>
            h.is_deleted = 0
            <if test="partNo != null">
                and h.part_no like concat('%',#{partNo,jdbcType=VARCHAR},'%')
            </if>
            <if test="startDate != null">
                and h.start_time &gt;= #{startDate}
            </if>
            <if test="endDate != null">
                and h.start_time &lt; date_add(#{endDate}, INTERVAL 1 day)
            </if>
        </where>
        ORDER BY h.start_time DESC
    </select>
   <select id="listVOByIds" resultType="com.qianwen.smartman.modules.workinghour.vo.PartWorkingHourVO">
        SELECT
        h.id,
        h.part_no,
        process_no,
    version,
    workstation_id,
    ws.name as workstation_name,
    start_time,
    end_time,
    occupancy_secs,
    clamping_secs,
    first_working_secs,
    last_remove_secs,
    first_measure_secs,
     processing_secs,
    prepare_secs,
    single_process_secs,
        h.amount
        FROM part_workinghour h
        LEFT JOIN blade_workstation ws on h.workstation_id=ws.id
         where   h.id in
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
        ORDER BY h.start_time DESC
    </select>
</mapper>
smart-man-boot/src/main/resources/dp/dpend-´ø¼ÆËã¹æÔò.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
[{"prop":"dpUnit","label":"单位"},{"prop":"ruleContent","label":"计算规则","describe":"计算规则来源于[规则管理-计算规则],通过lua脚本编写计算规则,对数据点的原始数据进行计算,生成新的数据点及数据点值。","sendCode":1,"isReqOptions":true,"type":"option","options":["s7status_trans"]},{"prop":"ruleArgs","label":"计算参数","describe":"根据计算规则,填写计算参数,多个计算参数用英文“,”隔开;注意:dpValue为采集到的值不需要填写。","sendCode":1},{"prop":"access","isRequired":true,"sendCode":1,"label":"权限","describe":"读写权限\\n RO(只读):只允许读取点位数据、\\nRW(读/写):既能读取数据也能写入数据。","default":"RO","type":"option","options":["RO","RW"]},{"prop":"pollingInterval","isRequired":true,"label":"轮询间隔(ms)","describe":"轮询间隔(ms)","default":1000},{"prop":"keepOriginalValue","isRequired":true,"sendCode":1,"label":"保留原始值","describe":"保留原始值","default":true,"type":"boolean"},{"prop":"isSave","isRequired":true,"sendCode":1,"label":"是否存储","describe":"是否存储","default":true,"type":"boolean"}]
smart-man-boot/src/main/resources/dp/dpend.json
@@ -1 +1 @@
[{"prop":"dpUnit","label":"单位"},{"prop":"ruleContent","label":"计算规则","describe":"计算规则来源于[规则管理-计算规则],通过lua脚本编写计算规则,对数据点的原始数据进行计算,生成新的数据点及数据点值。","sendCode":1,"isReqOptions":true,"type":"option","options":["s7status_trans"]},{"prop":"ruleArgs","label":"计算参数","describe":"根据计算规则,填写计算参数,多个计算参数用英文“,”隔开;注意:dpValue为采集到的值不需要填写。","sendCode":1},{"prop":"access","isRequired":true,"sendCode":1,"label":"权限","describe":"读写权限\\n RO(只读):只允许读取点位数据、\\nRW(读/写):既能读取数据也能写入数据。","default":"RO","type":"option","options":["RO","RW"]},{"prop":"pollingInterval","isRequired":true,"label":"轮询间隔(ms)","describe":"轮询间隔(ms)","default":1000},{"prop":"keepOriginalValue","isRequired":true,"sendCode":1,"label":"保留原始值","describe":"保留原始值","default":true,"type":"boolean"},{"prop":"isSave","isRequired":true,"sendCode":1,"label":"是否存储","describe":"是否存储","default":true,"type":"boolean"}]
[{"prop":"dpUnit","label":"单位"},{"prop":"access","isRequired":true,"sendCode":1,"label":"权限","describe":"读写权限\\n RO(只读):只允许读取点位数据、\\nRW(读/写):既能读取数据也能写入数据。","default":"RO","type":"option","options":["RO","RW"]},{"prop":"pollingInterval","isRequired":true,"label":"轮询间隔(ms)","describe":"轮询间隔(ms)","default":1000},{"prop":"keepOriginalValue","isRequired":true,"sendCode":1,"label":"保留原始值","describe":"保留原始值","default":true,"type":"boolean"},{"prop":"isSave","isRequired":true,"sendCode":1,"label":"是否存储","describe":"是否存储","default":true,"type":"boolean"}]
smart-man-boot/src/main/resources/sql/iotdb/iot_struct.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
CREATE DATABASE root.f2;
create device template output aligned(workstation_id INT64,value_collect INT64 encoding=TS_2DIFF,calendar_code TEXT encoding=DICTIONARY,factory_year INT32 encoding=RLE,factory_month INT32 encoding=RLE,factory_date INT32 encoding=RLE,factory_week INT32 encoding=RLE,shift_index INT32,shift_time_type INT32,is_sync BOOLEAN encoding=RLE,employee_id INT64);
create device template aggregate_output aligned(workstation_id INT64,output INT64 encoding=TS_2DIFF,cur_output INT64 encoding=TS_2DIFF,pre_output INT64 encoding=TS_2DIFF,pre_time INT64 encoding=TS_2DIFF,calendar_code TEXT encoding=DICTIONARY,factory_year INT32 encoding=RLE,factory_month INT32 encoding=RLE,factory_date INT32 encoding=RLE,factory_week INT32 encoding=RLE,shift_index INT32,shift_time_type INT32,employee_id INT64);
create device template aggregate_state aligned(workstation_id INT64,end_time INT64,duration_collect INT64 encoding=TS_2DIFF,calendar_code TEXT encoding=DICTIONARY,factory_year INT32 encoding=RLE,factory_month INT32 encoding=RLE,factory_date INT32 encoding=RLE,factory_week INT32 encoding=RLE,shift_index INT32 encoding=TS_2DIFF,shift_time_type INT32 encoding=TS_2DIFF,wcs INT32 encoding=TS_2DIFF,rps INT32 encoding=TS_2DIFF,is_deleted BOOLEAN encoding=RLE,is_plan INT32,employee_id INT64);
create device template aggregate_state_with_feedback aligned(workstation_id INT64,end_time INT64,duration_collect INT64 encoding=TS_2DIFF,calendar_code TEXT encoding=DICTIONARY,factory_year INT32 encoding=RLE,factory_month INT32 encoding=RLE,factory_date INT32 encoding=RLE,factory_week INT32 encoding=RLE,shift_index INT32 encoding=TS_2DIFF,shift_time_type INT32 encoding=TS_2DIFF,wcs INT32 encoding=TS_2DIFF,rps INT32 encoding=TS_2DIFF,is_deleted BOOLEAN encoding=RLE,is_plan INT32,feedback_id INT64);
create device template state aligned(workstation_id INT64,value_collect INT32,calendar_code TEXT encoding=DICTIONARY,factory_year INT32 encoding=RLE,factory_month INT32 encoding=RLE,factory_date INT32 encoding=RLE,factory_week INT32 encoding=RLE,shift_index INT32 encoding=TS_2DIFF,shift_time_type INT32 encoding=TS_2DIFF,wcs INT32 encoding=TS_2DIFF,rps INT32 encoding=TS_2DIFF,is_fix_point BOOLEAN encoding=RLE,is_sync BOOLEAN encoding=RLE,is_plan INT32, feedback_point_type INT32,feedback_id INT64,is_deleted BOOLEAN encoding=RLE,employee_id INT64);
create device template process_param aligned (workstation_id INT64,v TEXT,n TEXT);
create device template alarm aligned(workstation_id INT64,calendar_code TEXT encoding=DICTIONARY,factory_year INT32 encoding=RLE,factory_month INT32 encoding=RLE,factory_date INT32 encoding=RLE,factory_week INT32 encoding=RLE,shift_index INT32,shift_time_type INT32,code TEXT,message TEXT,level TEXT);
create device template prog_name aligned(workstation_id INT64,name TEXT,part_no TEXT,process_no TEXT,version TEXT,seg_total INT32,seg_no INT32);
smart-man-boot/src/main/resources/sql/mysql/workinghours.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
/*工时分析模块*/
DROP TABLE IF EXISTS `part_workinghour`;
CREATE TABLE `part_workinghour`
(
    `id`           bigint(0)                                                     NOT NULL COMMENT '主键',
    `status`       tinyint(0)                                                    NULL DEFAULT NULL COMMENT '状态',
    `is_deleted`   int                                                      NULL DEFAULT NULL COMMENT '删除',
    `create_user`  varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',
    `create_dept`  bigint(0)                                                     NULL DEFAULT NULL COMMENT '创建部门',
    `create_time`  datetime(0)                                                   NULL DEFAULT NULL COMMENT '创建时间',
    `update_user`  bigint(0)                                                     NULL DEFAULT NULL COMMENT '更新人',
    `update_time`  datetime(0)                                                   NULL DEFAULT NULL COMMENT '更新时间',
    `tenant_id`    varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NULL DEFAULT '0' COMMENT '租户',
    `part_no`      varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '零件编号',
    `process_no`   varchar(20)                                                   NULL DEFAULT NULL COMMENT '工序号',
    `version` varchar(20)  NULL DEFAULT NULL COMMENT '版次',
    `seg_total`   int                                                      NULL DEFAULT NULL COMMENT '工序段数',
    `workstation_id`    bigint                                               NULL DEFAULT 0 COMMENT '工位id',
    `start_time`  datetime(3)                                                   NULL DEFAULT NULL COMMENT '开始时间',
    `end_time`  datetime(3)                                                   NULL DEFAULT NULL COMMENT '结束时间',
    `occupancy_secs`    bigint                                               NULL DEFAULT 0 COMMENT '占机时间(秒)',
    `clamping_secs`    bigint                                               NULL DEFAULT 0 COMMENT '装夹调试时间(秒)',
    `first_working_secs`    bigint                                               NULL DEFAULT 0 COMMENT '首件切削时间(秒)',
    `last_remove_secs`    bigint                                               NULL DEFAULT 0 COMMENT '末件拆卸时间(秒)',
    `first_measure_secs`    bigint                                               NULL DEFAULT 0 COMMENT '首件计量时间(秒)',
    `processing_secs`    bigint                                               NULL DEFAULT 0 COMMENT '加工时间(秒)',
    `prepare_secs`    bigint                                               NULL DEFAULT 0 COMMENT '准备时间(秒)',
    `single_process_secs`    bigint                                               NULL DEFAULT 0 COMMENT '单件工时(秒)',
    `amount`    bigint                                               NULL DEFAULT 0 COMMENT '数量(该批次内)',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
  CHARACTER SET = utf8mb4
  COLLATE = utf8mb4_general_ci COMMENT = '零件工时'
  ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS `part_working_process`;
CREATE TABLE `part_working_process`
(
    `id`           bigint(0)                                                     NOT NULL COMMENT '主键',
    `status`       tinyint(0)                                                    NULL DEFAULT NULL COMMENT '状态',
    `is_deleted`   int                                                      NULL DEFAULT NULL COMMENT '删除',
    `create_user`  varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',
    `create_dept`  bigint(0)                                                     NULL DEFAULT NULL COMMENT '创建部门',
    `create_time`  datetime(0)                                                   NULL DEFAULT NULL COMMENT '创建时间',
    `update_user`  bigint(0)                                                     NULL DEFAULT NULL COMMENT '更新人',
    `update_time`  datetime(0)                                                   NULL DEFAULT NULL COMMENT '更新时间',
    `prog_name`    varchar(120) NULL DEFAULT NULL COMMENT '程序名称',
    `workinghour_id`    bigint                                               NOT NULL COMMENT '零件工时表id',
    `start_time`  datetime(3)                                                   NULL DEFAULT NULL COMMENT '开始时间',
    `end_time`  datetime(3)                                                   NULL DEFAULT NULL COMMENT '结束时间',
    `device_status`  int                                                   NULL DEFAULT NULL COMMENT '设备状态',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
  CHARACTER SET = utf8mb4
  COLLATE = utf8mb4_general_ci COMMENT = '零件加工过程记录'
  ROW_FORMAT = Dynamic;
smart-man-boot/src/test/java/com/qianwen/smartman/common/utils/DurationUtilTest.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
package com.qianwen.smartman.common.utils;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.Duration;
import java.time.LocalDateTime;
import org.junit.jupiter.api.Test;
public class DurationUtilTest {
    @Test
    public void toChineseDuration() {
        //new Duration()
        LocalDateTime end = LocalDateTime.now();
        LocalDateTime start = end.minusHours(25);//25小时
        Duration duration = Duration.between(start, end);
        String str = DurationUtil.toChineseDuration(duration);
        assertEquals("1天1小时",str);
        start = end.minusHours(3);
        duration = Duration.between(start, end);
        str = DurationUtil.toChineseDuration(duration);
        assertEquals("3小时",str);
        start = end.minusHours(1).minusMinutes(5).minusSeconds(22);
        duration = Duration.between(start, end);
        str = DurationUtil.toChineseDuration(duration);
        assertEquals("1小时5分22秒",str);
    }
}
smart-man-boot/src/test/java/com/qianwen/smartman/modules/workinghour/service/PartWorkingHourServiceTest.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,510 @@
package com.qianwen.smartman.modules.workinghour.service;
import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Chart;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.junit.jupiter.api.Test;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBoolean;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTCatAx;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDLbls;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTLegend;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumRef;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTScaling;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTStrRef;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx;
import org.openxmlformats.schemas.drawingml.x2006.chart.STAxPos;
import org.openxmlformats.schemas.drawingml.x2006.chart.STBarDir;
import org.openxmlformats.schemas.drawingml.x2006.chart.STBarGrouping;
import org.openxmlformats.schemas.drawingml.x2006.chart.STDispBlanksAs;
import org.openxmlformats.schemas.drawingml.x2006.chart.STLegendPos;
import org.openxmlformats.schemas.drawingml.x2006.chart.STOrientation;
import org.openxmlformats.schemas.drawingml.x2006.chart.STTickLblPos;
public class PartWorkingHourServiceTest {
    static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    private static String systemTime = System.currentTimeMillis()+"";//df.format(System.currentTimeMillis());;
    private static SXSSFWorkbook wb = new SXSSFWorkbook();
    private SXSSFSheet sheet = null;
    @Test
    public void testMain() {
        // å­—段名
        List<String> fldNameArr = new ArrayList();
        // æ ‡é¢˜
        List<String> titleArr = new ArrayList();
        // æ¨¡æ‹Ÿæ•°æ®
        List<Map> dataList = new ArrayList();
        Map dataMap1 = new HashMap();
        dataMap1.put("value1", "货币基金");
        dataMap1.put("value2", Math.floor(Math.random() * 100) + "");
        dataMap1.put("value3", Math.floor(Math.random() * 100) + "");
        dataMap1.put("value4", Math.floor(Math.random() * 100) + "");
        Map dataMap2 = new HashMap();
        dataMap2.put("value1", "指数基金");
        dataMap2.put("value2", Math.floor(Math.random() * 100) + "");
        dataMap2.put("value3", Math.floor(Math.random() * 100) + "");
        dataMap2.put("value4", Math.floor(Math.random() * 100) + "");
        Map dataMap3 = new HashMap();
        dataMap3.put("value1", "偏股基金");
        dataMap3.put("value2", Math.floor(Math.random() * 100) + "");
        dataMap3.put("value3", Math.floor(Math.random() * 100) + "");
        dataMap3.put("value4", Math.floor(Math.random() * 100) + "");
        Map dataMap4 = new HashMap();
        dataMap4.put("value1", "债券基金");
        dataMap4.put("value2", Math.floor(Math.random() * 100) + "");
        dataMap4.put("value3", Math.floor(Math.random() * 100) + "");
        dataMap4.put("value4", Math.floor(Math.random() * 100) + "");
        fldNameArr.add("value1");
        fldNameArr.add("value2");
        fldNameArr.add("value3");
        fldNameArr.add("value4");
        titleArr.add("类型");
        titleArr.add("买入");
        titleArr.add("卖出");
        titleArr.add("分红");
        dataList.add(dataMap1);
        dataList.add(dataMap2);
        dataList.add(dataMap3);
        dataList.add(dataMap4);
        //PoiExcelUtil ecu = new PoiExcelUtil();
        try {
            // åˆ›å»ºæŸ±çж图
            //ecu.createBarChart(titleArr, fldNameArr, dataList);
            createBarChart(titleArr, fldNameArr, dataList);
            // åˆ›å»ºé¥¼çж图
           // ecu.createPieChart(titleArr, fldNameArr, dataList);
            // åˆ›å»ºæŠ˜çº¿å›¾
            //ecu.createTimeXYChar(titleArr, fldNameArr, dataList);
 //
            // åˆ›å»ºé¢ç§¯å›¾
            //ecu.createAreaChart(titleArr, fldNameArr, dataList);
            String title="测试数据";
            //导出到文件
            FileOutputStream out = new FileOutputStream(new File("D:/PoiExcel/"+systemTime+"_"+title+".xls"));
            wb.write(out);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * åˆ›å»ºæŸ±çж图(堆积图,多组)
     *
     * @throws IOException
     */
    public void createBarChart(List<String> titleArr, List<String> fldNameArr, List<Map> dataList) {
        // åˆ›å»ºä¸€ä¸ªsheet页
        sheet = wb.createSheet("sheet0");
        // drawSheet0Table(sheet,titleArr,fldNameArr,dataList);
        // å †ç§¯=STBarGrouping.STACKED å¤šç»„=STBarGrouping.CLUSTERED
        //boolean result = drawSheet0Map(sheet, STBarGrouping.CLUSTERED, fldNameArr, dataList, titleArr);
        boolean result = drawSheet0Map(sheet, STBarGrouping.STACKED, fldNameArr, dataList, titleArr);//yys改
        System.out.println("生成柱状图(堆积or多组)-->" + result);
    }
    /**
     * ç”ŸæˆæŸ±çж图
     *
     * @param sheet      é¡µç­¾
     * @param group      æŸ±çŠ¶å›¾ç±»åž‹(堆积,多组)
     * @param fldNameArr åæ ‡åç§°
     * @param dataList   ç»Ÿè®¡æ•°æ®
     * @return
     */
    // private boolean drawSheet0Map(SXSSFSheet sheet, Enum group, List fldNameArr, List<Map> dataList, List titleArr) {
    private boolean drawSheet0Map(SXSSFSheet sheet, STBarGrouping.Enum group, List<String> fldNameArr, List<Map> dataList, List<String> titleArr) {
        boolean result = false;
        // èŽ·å–sheet名称
        String sheetName = sheet.getSheetName();
        result = drawSheet0Table(sheet, titleArr, fldNameArr, dataList);
        // åˆ›å»ºä¸€ä¸ªç”»å¸ƒ
        Drawing drawing = sheet.createDrawingPatriarch();
        // ç”»ä¸€ä¸ªå›¾åŒºåŸŸ
        // å‰å››ä¸ªé»˜è®¤0,从第8行到第25行,从第0列到第6列的区域
        ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 8, 6, 25);
        // åˆ›å»ºä¸€ä¸ªchart对象
        Chart chart = drawing.createChart(anchor);
        CTChart ctChart = ((XSSFChart) chart).getCTChart();
        CTPlotArea ctPlotArea = ctChart.getPlotArea();
        // åˆ›å»ºæŸ±çŠ¶å›¾æ¨¡åž‹
        CTBarChart ctBarChart = ctPlotArea.addNewBarChart();
        CTBoolean ctBoolean = ctBarChart.addNewVaryColors();
        ctBarChart.getVaryColors().setVal(true);
        // è®¾ç½®å›¾ç±»åž‹
        // STBarGrouping.Enum group = null;
        ctBarChart.addNewGrouping().setVal(group);
        ctBoolean.setVal(true);
        //ctBarChart.addNewBarDir().setVal(STBarDir.COL);
        ctBarChart.addNewBarDir().setVal(STBarDir.BAR);//yangysmod ,改成了横向
        // æ˜¯å¦æ·»åŠ å·¦ä¾§åæ ‡è½´
        ctChart.addNewDispBlanksAs().setVal(STDispBlanksAs.ZERO);
        ctChart.addNewShowDLblsOverMax().setVal(true);
        // è®¾ç½®è¿™ä¸¤ä¸ªå‚数是为了在STACKED模式下生成堆积模式;(standard)标准模式时需要将这两行去掉
        if ("stacked".equals(group.toString()) || "percentStacked".equals(group.toString())) {
            ctBarChart.addNewGapWidth().setVal(150);
            ctBarChart.addNewOverlap().setVal((byte) 100);
        }
        // åˆ›å»ºåºåˆ—,并且设置选中区域
        //for (int i = 0; i < fldNameArr.size() - 1; i++) {
            CTBarSer ctBarSer = ctBarChart.addNewSer();
            CTSerTx ctSerTx = ctBarSer.addNewTx();
            // å›¾ä¾‹åŒº
            CTStrRef ctStrRef = ctSerTx.addNewStrRef();
            // é€‰å®šåŒºåŸŸç¬¬0行,第1,2,3列标题作为图例 //1 2 3
            //String legendDataRange = new CellRangeAddress(0, 0, i + 1, i + 1).formatAsString(sheetName, true);
            //ctStrRef.setF(legendDataRange);
            ctBarSer.addNewIdx().setVal(3);//
            //ctBarSer.
            // æ¨ªåæ ‡åŒº
            CTAxDataSource cttAxDataSource = ctBarSer.addNewCat();
            ctStrRef = cttAxDataSource.addNewStrRef();
            // é€‰ç¬¬0列,第1-6行作为横坐标区域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0).formatAsString(sheetName, true);
            ctStrRef.setF(axisDataRange);
            // æ•°æ®åŒºåŸŸ
            CTNumDataSource ctNumDataSource = ctBarSer.addNewVal();
            CTNumRef ctNumRef = ctNumDataSource.addNewNumRef();
            // é€‰ç¬¬1-6行,第1-3列作为数据区域 //1 2 3
            //String numDataRange = new CellRangeAddress(1, dataList.size(), i + 1, i + 1).formatAsString(sheetName, true);
            String numDataRange = new CellRangeAddress(1, dataList.size(), 1, 1).formatAsString(sheetName, true);//yangys mod
            System.out.println("数据区域"+numDataRange);
            ctNumRef.setF(numDataRange);
            // æ·»åŠ æŸ±çŠ¶è¾¹æ¡†çº¿
            ctBarSer.addNewSpPr().addNewLn().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{0, 0, 0});
            // è®¾ç½®è´Ÿè½´é¢œè‰²ä¸æ˜¯ç™½è‰²
            ctBarSer.addNewInvertIfNegative().setVal(false);
            // è®¾ç½®æ ‡ç­¾æ ¼å¼
            ctBoolean.setVal(false);
            CTDLbls newDLbls = ctBarSer.addNewDLbls();
            newDLbls.setShowLegendKey(ctBoolean);
            ctBoolean.setVal(true);
            newDLbls.setShowVal(ctBoolean);
            ctBoolean.setVal(false);
            newDLbls.setShowCatName(ctBoolean);
            newDLbls.setShowSerName(ctBoolean);
            newDLbls.setShowPercent(ctBoolean);
            newDLbls.setShowBubbleSize(ctBoolean);
            newDLbls.setShowLeaderLines(ctBoolean);
        //}
        // å‘Šè¯‰BarChart它有坐标轴,并给它们id
        ctBarChart.addNewAxId().setVal(123456);
        ctBarChart.addNewAxId().setVal(123457);
        // æ¨ªåæ ‡
        CTCatAx ctCatAx = ctPlotArea.addNewCatAx();
        ctCatAx.addNewAxId().setVal(123456); // id of the cat axis
        CTScaling ctScaling = ctCatAx.addNewScaling();
        ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
        ctCatAx.addNewAxPos().setVal(STAxPos.B);
        ctCatAx.addNewCrossAx().setVal(123457); // id of the val axis
        ctCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);
        // çºµåæ ‡
        CTValAx ctValAx = ctPlotArea.addNewValAx();
        ctValAx.addNewAxId().setVal(123457); // id of the val axis
        ctScaling = ctValAx.addNewScaling();
        ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
        // è®¾ç½®ä½ç½®
        ctValAx.addNewAxPos().setVal(STAxPos.L);
        ctValAx.addNewCrossAx().setVal(123456); // id of the cat axis
        ctValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);
        // æ˜¯å¦åˆ é™¤ä¸»å·¦è¾¹è½´
        ctValAx.addNewDelete().setVal(false);
        // æ˜¯å¦åˆ é™¤æ¨ªåæ ‡
        ctCatAx.addNewDelete().setVal(false);
        // legend图注
//        if (true) {
        CTLegend ctLegend = ctChart.addNewLegend();
        ctLegend.addNewLegendPos().setVal(STLegendPos.B);
        ctLegend.addNewOverlay().setVal(false);
//        }
        return result;
    }
    /**
     * ç”Ÿæˆæ•°æ®è¡¨
     *
     * @param sheet      sheet页对象
     * @param titleArr   è¡¨å¤´å­—段
     * @param fldNameArr å·¦è¾¹æ ‡é¢˜å­—段
     * @param dataList   æ•°æ®
     * @return æ˜¯å¦ç”ŸæˆæˆåŠŸ
     */
    private boolean drawSheet0Table(SXSSFSheet sheet, List<String> titleArr, List<String> fldNameArr, List<Map> dataList) {
        // æµ‹è¯•时返回值
        boolean result = true;
        // åˆå§‹åŒ–表格样式
        List styleList = tableStyle();
        // æ ¹æ®æ•°æ®åˆ›å»ºexcel第一行标题行
        SXSSFRow row0 = sheet.createRow(0);
        for (int i = 0; i < titleArr.size(); i++) {
            // è®¾ç½®æ ‡é¢˜
            row0.createCell(i).setCellValue(titleArr.get(i));
            // è®¾ç½®æ ‡é¢˜è¡Œæ ·å¼
            row0.getCell(i).setCellStyle((CellStyle) styleList.get(0));
        }
        // å¡«å……数据
        for (int i = 0; i < dataList.size(); i++) {
            // èŽ·å–æ¯ä¸€é¡¹çš„æ•°æ®
            Map data = (Map) dataList.get(i);
            // è®¾ç½®æ¯ä¸€è¡Œçš„字段标题和数据
            SXSSFRow rowi = sheet.createRow(i + 1);
            for (int j = 0; j < data.size(); j++) {
                // åˆ¤æ–­æ˜¯å¦æ˜¯æ ‡é¢˜å­—段列
                if (j == 0) {
                    rowi.createCell(j).setCellValue((String) data.get("value" + (j + 1)));
                    // è®¾ç½®å·¦è¾¹å­—段样式
                    sheet.getRow(i + 1).getCell(j).setCellStyle((CellStyle) styleList.get(0));
                } else {
                    rowi.createCell(j).setCellValue(Double.valueOf((String) data.get("value" + (j + 1))));
                    // è®¾ç½®æ•°æ®æ ·å¼
                    sheet.getRow(i + 1).getCell(j).setCellStyle((CellStyle) styleList.get(2));
                }
            }
        }
        return result;
    }
    /**
     * ç”Ÿæˆè¡¨æ ¼æ ·å¼
     *
     * @return
     */
    private static List tableStyle() {
        List cellStyleList = new ArrayList();
        // æ ·å¼å‡†å¤‡
        // æ ‡é¢˜æ ·å¼
        CellStyle style = wb.createCellStyle();
        style.setFillForegroundColor(IndexedColors.ROYAL_BLUE.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setBorderBottom(BorderStyle.THIN); // ä¸‹è¾¹æ¡†
        style.setBorderLeft(BorderStyle.THIN);// å·¦è¾¹æ¡†
        style.setBorderTop(BorderStyle.THIN);// ä¸Šè¾¹æ¡†
        style.setBorderRight(BorderStyle.THIN);// å³è¾¹æ¡†
        style.setAlignment(HorizontalAlignment.CENTER);
        cellStyleList.add(style);
        CellStyle style1 = wb.createCellStyle();
        style1.setBorderBottom(BorderStyle.THIN); // ä¸‹è¾¹æ¡†
        style1.setBorderLeft(BorderStyle.THIN);// å·¦è¾¹æ¡†
        style1.setBorderTop(BorderStyle.THIN);// ä¸Šè¾¹æ¡†
        style1.setBorderRight(BorderStyle.THIN);// å³è¾¹æ¡†
        style1.setAlignment(HorizontalAlignment.CENTER);
        cellStyleList.add(style1);
        CellStyle cellStyle = wb.createCellStyle();
        cellStyle.setBorderTop(BorderStyle.THIN);// ä¸Šè¾¹æ¡†
        cellStyle.setBorderBottom(BorderStyle.THIN); // ä¸‹è¾¹æ¡†
        cellStyle.setBorderLeft(BorderStyle.THIN);// å·¦è¾¹æ¡†
        cellStyle.setBorderRight(BorderStyle.THIN);// å³è¾¹æ¡†
        cellStyle.setAlignment(HorizontalAlignment.CENTER);// æ°´å¹³å¯¹é½æ–¹å¼
        // cellStyle.setVerticalAlignment(VerticalAlignment.TOP);//垂直对齐方式
        cellStyleList.add(cellStyle);
        return cellStyleList;
    }
//https://blog.csdn.net/Lyq2017901206/article/details/126547542
}