diff --git a/gear-admin/src/main/resources/application-prod.yml b/gear-admin/src/main/resources/application-prod.yml index 758469c..86275f9 100644 --- a/gear-admin/src/main/resources/application-prod.yml +++ b/gear-admin/src/main/resources/application-prod.yml @@ -60,9 +60,9 @@ spring: lazy: true type: ${spring.datasource.type} driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://47.117.71.33:11293/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true - username: - password: + url: jdbc:mysql://47.117.71.33:11293/gear?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true + username: root + password: Fuande@666 # oracle: # type: ${spring.datasource.type} # driverClassName: oracle.jdbc.OracleDriver diff --git a/gear-oa/pom.xml b/gear-oa/pom.xml index a05a137..da5c3ab 100644 --- a/gear-oa/pom.xml +++ b/gear-oa/pom.xml @@ -21,7 +21,22 @@ com.gear gear-common - + + + com.alibaba.fastjson2 + fastjson2 + 2.0.35 + + + com.zto.zop + zopsdk + 0.11 + + + com.yundasys + kfpt-sdk + 1.0.0 + diff --git a/gear-oa/src/main/java/com/gear/oa/controller/OaExpressController.java b/gear-oa/src/main/java/com/gear/oa/controller/OaExpressController.java new file mode 100644 index 0000000..eb2663a --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/controller/OaExpressController.java @@ -0,0 +1,108 @@ +package com.gear.oa.controller; + +import java.io.IOException; +import java.util.List; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import lombok.RequiredArgsConstructor; +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.*; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import com.gear.common.annotation.RepeatSubmit; +import com.gear.common.annotation.Log; +import com.gear.common.core.controller.BaseController; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.domain.R; +import com.gear.common.core.validate.AddGroup; +import com.gear.common.core.validate.EditGroup; +import com.gear.common.core.validate.QueryGroup; +import com.gear.common.enums.BusinessType; +import com.gear.common.utils.poi.ExcelUtil; +import com.gear.oa.domain.vo.OaExpressVo; +import com.gear.oa.domain.bo.OaExpressBo; +import com.gear.oa.service.IOaExpressService; +import com.gear.common.core.page.TableDataInfo; + +/** + * 物流预览 + * + * @author hdka + * @date 2025-07-20 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/oa/express") +public class OaExpressController extends BaseController { + + private final IOaExpressService iOaExpressService; + + /** + * 查询物流预览列表 + */ + @GetMapping("/list") + public TableDataInfo list(OaExpressBo bo, PageQuery pageQuery) { + return iOaExpressService.queryPageList(bo, pageQuery); + } + + /** + * 导出物流预览列表 + */ + @Log(title = "物流预览", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(OaExpressBo bo, HttpServletResponse response) { + List list = iOaExpressService.queryList(bo); + ExcelUtil.exportExcel(list, "物流预览", OaExpressVo.class, response); + } + + /** + * 获取物流预览详细信息 + * + * @param expressId 主键 + */ + @GetMapping("/{expressId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long expressId) { + return R.ok(iOaExpressService.queryById(expressId)); + } + + /** + * 新增物流预览 + */ + @Log(title = "物流预览", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody OaExpressBo bo) { + return toAjax(iOaExpressService.insertByBo(bo)); + } + + /** + * 修改物流预览 + */ + @Log(title = "物流预览", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody OaExpressBo bo) { + return toAjax(iOaExpressService.updateByBo(bo)); + } + + /** + * 删除物流预览 + * + * @param expressIds 主键串 + */ + @Log(title = "物流预览", businessType = BusinessType.DELETE) + @DeleteMapping("/{expressIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] expressIds) { + return toAjax(iOaExpressService.deleteWithValidByIds(Arrays.asList(expressIds), true)); + } + + + @GetMapping("/refresh/{expressIds}") + public R getRefreshExpress(@PathVariable Long[] expressIds) throws IOException { + return toAjax(iOaExpressService.getRefreshExpress(Arrays.asList(expressIds))); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/controller/OaExpressQuestionController.java b/gear-oa/src/main/java/com/gear/oa/controller/OaExpressQuestionController.java new file mode 100644 index 0000000..b8ca562 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/controller/OaExpressQuestionController.java @@ -0,0 +1,101 @@ +package com.gear.oa.controller; + +import java.util.List; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import lombok.RequiredArgsConstructor; +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.*; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import com.gear.common.annotation.RepeatSubmit; +import com.gear.common.annotation.Log; +import com.gear.common.core.controller.BaseController; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.domain.R; +import com.gear.common.core.validate.AddGroup; +import com.gear.common.core.validate.EditGroup; +import com.gear.common.core.validate.QueryGroup; +import com.gear.common.enums.BusinessType; +import com.gear.common.utils.poi.ExcelUtil; +import com.gear.oa.domain.vo.OaExpressQuestionVo; +import com.gear.oa.domain.bo.OaExpressQuestionBo; +import com.gear.oa.service.IOaExpressQuestionService; +import com.gear.common.core.page.TableDataInfo; + +/** + * 快递问题 + * + * @author hdka + * @date 2025-07-21 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/oa/expressQuestion") +public class OaExpressQuestionController extends BaseController { + + private final IOaExpressQuestionService iOaExpressQuestionService; + + /** + * 查询快递问题列表 + */ + @GetMapping("/list") + public TableDataInfo list(OaExpressQuestionBo bo, PageQuery pageQuery) { + return iOaExpressQuestionService.queryPageList(bo, pageQuery); + } + + /** + * 导出快递问题列表 + */ + @Log(title = "快递问题", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(OaExpressQuestionBo bo, HttpServletResponse response) { + List list = iOaExpressQuestionService.queryList(bo); + ExcelUtil.exportExcel(list, "快递问题", OaExpressQuestionVo.class, response); + } + + /** + * 获取快递问题详细信息 + * + * @param questionId 主键 + */ + @GetMapping("/{questionId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long questionId) { + return R.ok(iOaExpressQuestionService.queryById(questionId)); + } + + /** + * 新增快递问题 + */ + @Log(title = "快递问题", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody OaExpressQuestionBo bo) { + return toAjax(iOaExpressQuestionService.insertByBo(bo)); + } + + /** + * 修改快递问题 + */ + @Log(title = "快递问题", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody OaExpressQuestionBo bo) { + return toAjax(iOaExpressQuestionService.updateByBo(bo)); + } + + /** + * 删除快递问题 + * + * @param questionIds 主键串 + */ + @Log(title = "快递问题", businessType = BusinessType.DELETE) + @DeleteMapping("/{questionIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] questionIds) { + return toAjax(iOaExpressQuestionService.deleteWithValidByIds(Arrays.asList(questionIds), true)); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/controller/OaFeedbackController.java b/gear-oa/src/main/java/com/gear/oa/controller/OaFeedbackController.java new file mode 100644 index 0000000..2c5c63e --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/controller/OaFeedbackController.java @@ -0,0 +1,122 @@ +package com.gear.oa.controller; + +import com.gear.common.annotation.RepeatSubmit; +import com.gear.common.core.controller.BaseController; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.domain.R; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.core.validate.AddGroup; +import com.gear.common.core.validate.EditGroup; +import com.gear.common.utils.poi.ExcelUtil; +import com.gear.oa.domain.bo.OaFeedbackBo; +import com.gear.oa.domain.vo.OaFeedbackVo; +import com.gear.oa.service.IOaFeedbackService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.List; + +/** + * 问题反馈 + * + * @author ruoyi + * @date 2025-03-28 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/oa/feedback") +public class OaFeedbackController extends BaseController { + + private final IOaFeedbackService iOaFeedbackService; + + /** + * 查询问题反馈列表 + */ + @GetMapping("/list") + public TableDataInfo list(OaFeedbackBo bo, PageQuery pageQuery) { + return iOaFeedbackService.queryPageList(bo, pageQuery); + } + + /** + * 查询问题反馈列表 + */ + @GetMapping("/index-list") + public TableDataInfo indexList(OaFeedbackBo bo, PageQuery pageQuery) { + return iOaFeedbackService.indexQueryList(bo, pageQuery); + } + + /** + * 导出问题反馈列表 + */ + @PostMapping("/export") + public void export(OaFeedbackBo bo, HttpServletResponse response) { + List list = iOaFeedbackService.queryList(bo); + ExcelUtil.exportExcel(list, "问题反馈", OaFeedbackVo.class, response); + } + + /** + * 获取问题反馈详细信息 + * + * @param feedbackId 主键 + */ + @GetMapping("/{feedbackId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long feedbackId) { + return R.ok(iOaFeedbackService.queryById(feedbackId)); + } + + /** + * 新增问题反馈 + */ + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody OaFeedbackBo bo) { + return toAjax(iOaFeedbackService.insertByBo(bo)); + } + + /** + * 修改问题反馈 + */ + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody OaFeedbackBo bo) { + return toAjax(iOaFeedbackService.updateByBo(bo)); + } + + /** + * 删除问题反馈 + * + * @param feedbackIds 主键串 + */ + @DeleteMapping("/{feedbackIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] feedbackIds) { + return toAjax(iOaFeedbackService.deleteWithValidByIds(Arrays.asList(feedbackIds), true)); + } + /** + * 删除问题反馈 + * + * @param feedbackId 主键 + */ + @DeleteMapping("/remove/{feedbackId}") + public R removeItem(@PathVariable("feedbackId") Long feedbackId) { + return toAjax(iOaFeedbackService.delItem(feedbackId)); + } + + + /** + * 修改问题反馈 + */ + @RepeatSubmit() + @PutMapping("/toRead") + public R toRead(@Validated(EditGroup.class) @RequestBody OaFeedbackBo bo) { + return toAjax(iOaFeedbackService.updateToRead(bo)); + } + +} diff --git a/gear-oa/src/main/java/com/gear/oa/controller/OaReportController.java b/gear-oa/src/main/java/com/gear/oa/controller/OaReportController.java new file mode 100644 index 0000000..27996fa --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/controller/OaReportController.java @@ -0,0 +1,193 @@ +package com.gear.oa.controller; + +import com.gear.common.annotation.Log; +import com.gear.common.annotation.RepeatSubmit; +import com.gear.common.core.controller.BaseController; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.domain.R; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.core.validate.AddGroup; +import com.gear.common.core.validate.EditGroup; +import com.gear.common.enums.BusinessType; +import com.gear.common.utils.poi.ExcelUtil; +import com.gear.oa.domain.bo.OaReportBo; +import com.gear.oa.domain.vo.OaReportVo; +import com.gear.oa.domain.vo.ReportCardVo; +import com.gear.oa.domain.vo.ReportPieVo; +import com.gear.oa.domain.vo.ReportTrendVo; +import com.gear.oa.service.IOaReportService; +import lombok.RequiredArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; + +/** + * 项目报工 + * + * @author hdka + * @date 2025-06-16 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/oa/projectReport") +public class OaReportController extends BaseController { + + private final IOaReportService iOaReportService; + + /** + * 查询项目报工列表 + */ +// @SaCheckPermission("oa:projectReport:list") + @GetMapping("/list") + public TableDataInfo list(OaReportBo bo, PageQuery pageQuery) { + return iOaReportService.queryPageList(bo, pageQuery); + } + + /** + * 查询项目报工列表 + */ +// @SaCheckPermission("oa:projectReport:list") + @GetMapping("/report") + public R> clearList(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate start, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate end) { + return R.ok(iOaReportService.clearList(start,end)); + } + + /** + * 导出项目报工列表 + */ +// @SaCheckPermission("oa:projectReport:export") + @Log(title = "项目报工", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(@RequestBody OaReportBo bo, HttpServletResponse response) { + List list = iOaReportService.queryList(bo); + // 处理content去标签 + for (OaReportVo reportVo : list) { + reportVo.setContent(stripHtml(reportVo.getContent())); + reportVo.setTrip(reportVo.getIsTrip() == 1 ? "是" : "否"); + reportVo.setWorkTypeName(reportVo.getWorkType() == 1 ? "国外" : "国内"); + if (reportVo.getIsTrip() == null) { + reportVo.setIsTrip(0L); // 防止ExcelDictConvert NPE + } + } + ExcelUtil.exportExcel(list, "项目报工", OaReportVo.class, response); + } + + // 工具方法 + private static String stripHtml(String html) { + return html == null ? null : html.replaceAll("<[^>]+>", ""); + } + + /** + * 获取项目报工详细信息 + * + * @param reportId 主键 + */ +// @SaCheckPermission("oa:projectReport:query") + @GetMapping("/{reportId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long reportId) { + return R.ok(iOaReportService.queryById(reportId)); + } + + /** + * 新增项目报工 + */ +// @SaCheckPermission("oa:projectReport:add") + @Log(title = "项目报工", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody OaReportBo bo) { + return toAjax(iOaReportService.insertByBo(bo)); + } + + /** + * 修改项目报工 + */ +// @SaCheckPermission("oa:projectReport:edit") + @Log(title = "项目报工", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody OaReportBo bo) { + return toAjax(iOaReportService.updateByBo(bo)); + } + + /** + * 删除项目报工 + * + * @param reportIds 主键串 + */ +// @SaCheckPermission("oa:projectReport:remove") + @Log(title = "项目报工", businessType = BusinessType.DELETE) + @DeleteMapping("/{reportIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] reportIds) { + return toAjax(iOaReportService.deleteWithValidByIds(Arrays.asList(reportIds), true)); + } + + + + /** + * 数据统计接口 + */ + @GetMapping("/rank") + public R> getRankData(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate start, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate end + ){ + + return R.ok(iOaReportService.getRankData(start,end)); + } + + + /** + * 数据统计接口 + */ + @GetMapping("/card") + public R getCardData(){ + + return R.ok(iOaReportService.getCardData()); + } + + /** + * GET /api/reports/trend?start=2025-06-01&end=2025-06-07 + */ + @GetMapping("/trend") + public R> trend( + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate start, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate end + ) { + return R.ok(iOaReportService.getTrend(start, end)); + } + +// /** +// * GET /api/reports/distribution +// */ +// @GetMapping("/distribution") +// public R> distribution( +// @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate start, +// @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate end +// ) { +// return R.ok(iOaReportService.getDistribution(start,end)); +// } + + @GetMapping("/projects") + public R> getProjects(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate start, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate end) { + return R.ok(iOaReportService.getProjects(start,end)); + } + + + @GetMapping("/summary") + public R> summary(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate start, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate end) { + return R.ok(iOaReportService.getSummaryData(start,end)); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/OaExpress.java b/gear-oa/src/main/java/com/gear/oa/domain/OaExpress.java new file mode 100644 index 0000000..05a6f14 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/OaExpress.java @@ -0,0 +1,86 @@ +package com.gear.oa.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 物流预览对象 oa_express + * + * @author hdka + * @date 2025-07-20 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("oa_express") +public class OaExpress extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * 主键id + */ + @TableId(value = "express_id") + private Long expressId; + + /** + * 物流编号 + */ + private String expressCode; + /** + * 数据状态0未确认1进行中2已完成 + */ + private Long status; + /** + * 供应商姓名 + */ + private String supplyName; + /** + * 供应商联系方式 + */ + private String supplyPhone; + /** + * 负责人id + */ + private Long ownerId; + /** + * 负责人手机号(快递手机号) + */ + private String ownerPhone; + /** + * 计划到货时间 + */ + private Date planDate; + /** + * 物流公司标识 + */ + private String expressType; + /** + * 删除标志 + */ + @TableLogic + private Long delFlag; + /** + * 备注 + */ + private String remark; + + + /** + * 节点变化时间 + */ + private Date lastUpdateTime; + + /** + * 当前节点 + */ + private String lastStatus; + + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/OaExpressQuestion.java b/gear-oa/src/main/java/com/gear/oa/domain/OaExpressQuestion.java new file mode 100644 index 0000000..7b54f5d --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/OaExpressQuestion.java @@ -0,0 +1,60 @@ +package com.gear.oa.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 快递问题对象 oa_express_question + * + * @author hdka + * @date 2025-07-21 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("oa_express_question") +public class OaExpressQuestion extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * 主键id + */ + @TableId(value = "question_id") + private Long questionId; + /** + * 关联快递 + */ + private Long expressId; + /** + * 问题描述 + */ + private String description; + /** + * 汇报时间 + */ + private Date reportTime; + /** + * 汇报人 + */ + private String reportBy; + /** + * 0未解决1已解决 + */ + private Long status; + /** + * 删除标志 + */ + @TableLogic + private Long delFlag; + /** + * 备注 + */ + private String remark; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/OaFeedback.java b/gear-oa/src/main/java/com/gear/oa/domain/OaFeedback.java new file mode 100644 index 0000000..5761bf8 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/OaFeedback.java @@ -0,0 +1,48 @@ +package com.gear.oa.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 问题反馈对象 oa_feedback + * + * @author ruoyi + * @date 2025-03-28 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("oa_feedback") +public class OaFeedback extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * 主键id + */ + @TableId(value = "feedback_id") + private Long feedbackId; + /** + * 反馈内容 + */ + private String content; + /** + * 反馈状态 + */ + private Long status; + /** + * + */ + private String remark; + /** + * + */ + @TableLogic + private Long delFlag; + + private String title; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/OaReport.java b/gear-oa/src/main/java/com/gear/oa/domain/OaReport.java new file mode 100644 index 0000000..4dbca34 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/OaReport.java @@ -0,0 +1,65 @@ +package com.gear.oa.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 项目报工对象 oa_project_report + * + * @author hdka + * @date 2025-06-16 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("oa_project_report") +public class OaReport extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * 主键 ID + */ + @TableId(value = "report_id") + private Long reportId; + /** + * 经办人 + */ + private Long userId; + /** + * 工作地点 + */ + private String workPlace; + /** + * 项目 ID + */ + private Long projectId; + /** + * 报工内容 + */ + private String content; + /** + * 删除标志 (0 正常, 1 删除) + */ + @TableLogic + private Integer delFlag; + /** + * 备注 + */ + private String remark; + + /** + * 是否出差 + */ + private Long isTrip; + + /** + * 报工时间 + */ + private Long workType; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/bo/OaExpressBo.java b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaExpressBo.java new file mode 100644 index 0000000..05bdfde --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaExpressBo.java @@ -0,0 +1,81 @@ +package com.gear.oa.domain.bo; + +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 物流预览业务对象 oa_express + * + * @author hdka + * @date 2025-07-20 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class OaExpressBo extends BaseEntity { + + /** + * 主键id + */ + private Long expressId; + + /** + * 物流编号 + */ + private String expressCode; + + /** + * 数据状态0未确认1进行中2已完成 + */ + private Long status; + + /** + * 供应商姓名 + */ + private String supplyName; + + /** + * 供应商联系方式 + */ + private String supplyPhone; + + /** + * 负责人id + */ + private Long ownerId; + + /** + * 负责人手机号(快递手机号) + */ + private String ownerPhone; + + /** + * 计划到货时间 + */ + private Date planDate; + + /** + * 物流公司标识 + */ + private String expressType; + + /** + * 备注 + */ + private String remark; + + + /** + * 节点变化时间 + */ + private Date lastUpdateTime; + + /** + * 当前节点 + */ + private String lastStatus; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/bo/OaExpressQuestionBo.java b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaExpressQuestionBo.java new file mode 100644 index 0000000..2631520 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaExpressQuestionBo.java @@ -0,0 +1,58 @@ +package com.gear.oa.domain.bo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 快递问题业务对象 oa_express_question + * + * @author hdka + * @date 2025-07-21 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class OaExpressQuestionBo extends BaseEntity { + + /** + * 主键id + */ + private Long questionId; + + /** + * 关联快递 + */ + private Long expressId; + + /** + * 问题描述 + */ + private String description; + + /** + * 汇报时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date reportTime; + + /** + * 汇报人 + */ + private String reportBy; + + /** + * 0未解决1已解决 + */ + private Long status; + + /** + * 备注 + */ + private String remark; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/bo/OaFeedbackBo.java b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaFeedbackBo.java new file mode 100644 index 0000000..a8e6dbe --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaFeedbackBo.java @@ -0,0 +1,41 @@ +package com.gear.oa.domain.bo; + +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 问题反馈业务对象 oa_feedback + * + * @author ruoyi + * @date 2025-03-28 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class OaFeedbackBo extends BaseEntity { + + /** + * 主键id + */ + private Long feedbackId; + + /** + * 反馈内容 + */ + private String content; + + /** + * 反馈状态 + */ + private Long status; + + /** + * + */ + private String remark; + + private Long state; + + private String title; +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/bo/OaReportBo.java b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaReportBo.java new file mode 100644 index 0000000..b075b64 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaReportBo.java @@ -0,0 +1,91 @@ +package com.gear.oa.domain.bo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; +import java.util.List; + +/** + * 项目报工业务对象 oa_project_report + * + * @author hdka + * @date 2025-06-16 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class OaReportBo extends BaseEntity { + + /** + * 主键 ID + */ + private Long reportId; + + /** + * 经办人 + */ + private Long userId; + + /** + * 工作地点 + */ + private String workPlace; + + + /** + * 报工内容 + */ + private String content; + + /** + * 备注 + */ + private String remark; + + /** + * 是否出差 + */ + private Long isTrip; + + /** + * 部门id + */ + private Long deptId; + + /** + * 项目编号 + */ + private String projectNum; + + /** + * 项目代号 + */ + private String projectCode; + + /** + * 名字 + */ + private String nickName; + + /** + * 报工时间 + */ + private Long workType; + + /** + * 修改创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date time; + + // 新增:多用户ID和时间范围 + private List userIds; + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date startDate; + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date endDate; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/OaExpressQuestionVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaExpressQuestionVo.java new file mode 100644 index 0000000..7eb7a53 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaExpressQuestionVo.java @@ -0,0 +1,70 @@ +package com.gear.oa.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.util.Date; + + +/** + * 快递问题视图对象 oa_express_question + * + * @author hdka + * @date 2025-07-21 + */ +@Data +@ExcelIgnoreUnannotated +public class OaExpressQuestionVo { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @ExcelProperty(value = "主键id") + private Long questionId; + + /** + * 关联快递 + */ + @ExcelProperty(value = "关联快递") + private Long expressId; + + /** + * 问题描述 + */ + @ExcelProperty(value = "问题描述") + private String description; + + /** + * 汇报时间 + */ + @ExcelProperty(value = "汇报时间") + private Date reportTime; + + /** + * 汇报人 + */ + @ExcelProperty(value = "汇报人") + private String reportBy; + + /** + * 0未解决1已解决 + */ + @ExcelProperty(value = "状态") + private Long status; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 快递单号 + */ + private String expressCode; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/OaExpressVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaExpressVo.java new file mode 100644 index 0000000..090dd75 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaExpressVo.java @@ -0,0 +1,116 @@ +package com.gear.oa.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.gear.common.annotation.ExcelDictFormat; +import com.gear.common.convert.ExcelDictConvert; +import lombok.Data; + +import java.util.Date; + + +/** + * 物流预览视图对象 oa_express + * + * @author hdka + * @date 2025-07-20 + */ +@Data +@ExcelIgnoreUnannotated +public class OaExpressVo { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @ExcelProperty(value = "主键id") + private Long expressId; + + /** + * 物流编号 + */ + @ExcelProperty(value = "物流编号") + private String expressCode; + + /** + * 数据状态0未确认1进行中2已完成 + */ + @ExcelProperty(value = "数据状态0未确认1进行中2已完成") + private Long status; + + /** + * 供应商姓名 + */ + @ExcelProperty(value = "供应商姓名") + private String supplyName; + + /** + * 供应商联系方式 + */ + @ExcelProperty(value = "供应商联系方式") + private String supplyPhone; + + /** + * 负责人id + */ + private Long ownerId; + + + /** + * 负责人id + */ + @ExcelProperty(value = "负责人") + private String ownerName; + + /** + * 负责人手机号(快递手机号) + */ + @ExcelProperty(value = "负责人手机号", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "快=递手机号") + private String ownerPhone; + + /** + * 计划到货时间 + */ + @ExcelProperty(value = "计划到货时间") + private Date planDate; + + /** + * 物流公司标识 + */ + @ExcelProperty(value = "物流公司标识", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "oa_express_type") + private String expressType; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 接收时间 + */ + private Date acceptTime; + + /** + * 物流状态 + */ + private String firstStatusName; + + /** + * 节点变化时间 + */ + private Date lastUpdateTime; + + /** + * 当前节点 + */ + private String lastStatus; + + /** + * 更新时间 + */ + private Date updateTime; +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/OaFeedbackVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaFeedbackVo.java new file mode 100644 index 0000000..4f81a5d --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaFeedbackVo.java @@ -0,0 +1,52 @@ +package com.gear.oa.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + + +/** + * 问题反馈视图对象 oa_feedback + * + * @author ruoyi + * @date 2025-03-28 + */ +@Data +@ExcelIgnoreUnannotated +public class OaFeedbackVo { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @ExcelProperty(value = "主键id") + private Long feedbackId; + + /** + * 反馈内容 + */ + @ExcelProperty(value = "反馈内容") + private String content; + + /** + * 反馈状态 + */ + @ExcelProperty(value = "反馈状态") + private Long status; + + /** + * + */ + @ExcelProperty(value = "") + private String remark; + /** + * + */ + @ExcelProperty(value = "") + private Long state; + + private String title; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/OaReportVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaReportVo.java new file mode 100644 index 0000000..79274b9 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaReportVo.java @@ -0,0 +1,125 @@ +package com.gear.oa.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; + + +/** + * 项目报工视图对象 oa_project_report + * + * @author hdka + * @date 2025-06-16 + */ +@Data +@ExcelIgnoreUnannotated +public class OaReportVo { + + private static final long serialVersionUID = 1L; + + /** + * 主键 ID + */ + @ExcelProperty(value = "主键 ID") + private Long reportId; + + /** + * 经办人 + */ + private Long userId; + + /** + * 经办人姓名 + */ + @ExcelProperty(value = "姓名") + private String nickName; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 工作地点 + */ + @ExcelProperty(value = "工作地点") + private String workPlace; + + + /** + * 报工内容 + */ + @ExcelProperty(value = "报工内容") + private String content; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 是否出差 + */ + + private Long isTrip; + /** + * 是否出差 + */ + @ExcelProperty(value = "是否出差") + private String trip; + /** + * 报工次数 + */ + private Long count; + /** + * 报工次数 + */ + private Long reportCount; + + /** + * 项目剩余时间 + */ + private Long remainTime; + + /** + * 项目状态 + */ + private Long projectStatus; + + /** + * 报工时间 + */ + @ExcelProperty(value = "报工时间") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") // EasyExcel注解 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") // Jackson注解,便于前后端一致 + private Date createTime; + + /** + * 国内外标志 + */ + private Long workType; + /** + * 国内外 + */ + @ExcelProperty(value = "国内/国外") + private String workTypeName; + + /** + * inWorkNum + * 国内工作时间 + */ + private Long inWorkNum; + + /** + * inWorkNum + * 国外工作时间 + */ + private Long outWorkNum; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/ReportCardVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/ReportCardVo.java new file mode 100644 index 0000000..eeea653 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/ReportCardVo.java @@ -0,0 +1,44 @@ +package com.gear.oa.domain.vo; + + +import lombok.Data; + +@Data +public class ReportCardVo { + + /** + * 今日报工 + */ + private Long todayCount; + + /** + * 昨日报工 + */ + private Long todayCountChange; + + /** + * 今日涉及项目数 + */ + private Long inProgressProjects; + + /** + * 昨日涉及项目数量 + */ + private Long projectChange; + + /** + * 涉及完成 + */ + private Long completionRate; + + /** + * 昨日涉及完成 + */ + private Long completionChange; + + /** + * 未完成(等待,未完成,待) + */ + private Long exceptions; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/ReportPieVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/ReportPieVo.java new file mode 100644 index 0000000..b3e7e22 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/ReportPieVo.java @@ -0,0 +1,11 @@ +package com.gear.oa.domain.vo; + + +import lombok.Data; + +@Data +public class ReportPieVo { + + private String projectName; + private Integer value; +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/ReportTrendVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/ReportTrendVo.java new file mode 100644 index 0000000..d6b9a55 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/ReportTrendVo.java @@ -0,0 +1,14 @@ +package com.gear.oa.domain.vo; + +import lombok.Data; + +import java.time.LocalDate; + +@Data +public class ReportTrendVo { + + private LocalDate date; + + private Integer count; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/mapper/OaExpressMapper.java b/gear-oa/src/main/java/com/gear/oa/mapper/OaExpressMapper.java new file mode 100644 index 0000000..5527ffa --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/mapper/OaExpressMapper.java @@ -0,0 +1,23 @@ +package com.gear.oa.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gear.common.core.mapper.BaseMapperPlus; +import com.gear.oa.domain.OaExpress; +import com.gear.oa.domain.vo.OaExpressVo; +import org.apache.ibatis.annotations.Param; + +/** + * 物流预览Mapper接口 + * + * @author hdka + * @date 2025-07-20 + */ +public interface OaExpressMapper extends BaseMapperPlus { + + Page selectVoPagePlus(@Param("build") Page build, @Param(Constants.WRAPPER) QueryWrapper lqw); + + OaExpressVo selectVoByIdPlus(@Param("expressId") Long expressId); + +} diff --git a/gear-oa/src/main/java/com/gear/oa/mapper/OaExpressQuestionMapper.java b/gear-oa/src/main/java/com/gear/oa/mapper/OaExpressQuestionMapper.java new file mode 100644 index 0000000..01ab48f --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/mapper/OaExpressQuestionMapper.java @@ -0,0 +1,20 @@ +package com.gear.oa.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gear.common.core.mapper.BaseMapperPlus; +import com.gear.oa.domain.OaExpressQuestion; +import com.gear.oa.domain.vo.OaExpressQuestionVo; +import org.apache.ibatis.annotations.Param; + +/** + * 快递问题Mapper接口 + * + * @author hdka + * @date 2025-07-21 + */ +public interface OaExpressQuestionMapper extends BaseMapperPlus { + + Page selectVoPagePlus(@Param("build") Page build, @Param(Constants.WRAPPER) QueryWrapper lqw); +} diff --git a/gear-oa/src/main/java/com/gear/oa/mapper/OaFeedbackMapper.java b/gear-oa/src/main/java/com/gear/oa/mapper/OaFeedbackMapper.java new file mode 100644 index 0000000..4571b67 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/mapper/OaFeedbackMapper.java @@ -0,0 +1,26 @@ +package com.gear.oa.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gear.common.core.mapper.BaseMapperPlus; +import com.gear.oa.domain.OaFeedback; +import com.gear.oa.domain.vo.OaFeedbackVo; +import org.apache.ibatis.annotations.Param; + +/** + * 问题反馈Mapper接口 + * + * @author ruoyi + * @date 2025-03-28 + */ +public interface OaFeedbackMapper extends BaseMapperPlus { + + Page selectVoPageAndStatus(@Param("page") Page build, @Param(Constants.WRAPPER) QueryWrapper lqw); + + int updateToRead(@Param("feedbackId") Long feedbackId, @Param("userId") Long userId); + + void insertItem(Long feedbackId); + + int delItem(@Param("feedbackId") Long feedbackId, @Param("userId") Long userId); +} diff --git a/gear-oa/src/main/java/com/gear/oa/mapper/OaReportMapper.java b/gear-oa/src/main/java/com/gear/oa/mapper/OaReportMapper.java new file mode 100644 index 0000000..026bae6 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/mapper/OaReportMapper.java @@ -0,0 +1,55 @@ +package com.gear.oa.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gear.common.core.mapper.BaseMapperPlus; +import com.gear.oa.domain.OaReport; +import com.gear.oa.domain.bo.OaReportBo; +import com.gear.oa.domain.vo.OaReportVo; +import com.gear.oa.domain.vo.ReportPieVo; +import com.gear.oa.domain.vo.ReportTrendVo; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDate; +import java.util.Date; +import java.util.List; + +/** + * 项目报工Mapper接口 + * + * @author hdka + * @date 2025-06-16 + */ +public interface OaReportMapper extends BaseMapperPlus { + List selectAll(@Param("bo") OaReportBo bo); + Page selectVoPagePlus(@Param("build") Page build, @Param(Constants.WRAPPER) QueryWrapper lqw); + + OaReportVo selectVoByIdPlus(@Param("reportId") Long reportId); + + Long countWithPending(Date date); + + Long countWithCompleted(Date createTime); + + /** + * 报工趋势:按天统计报工记录数 + */ + List selectReportTrend( + @Param("start") + LocalDate start, + @Param("end") LocalDate end + ); + + /** + * 项目分布:各项目报工次数分布 + */ + List selectProjectDistribution(@Param("start") LocalDate start, @Param("end") LocalDate end); + + List selectRankData(@Param("start") LocalDate start, @Param("end") LocalDate end); + + List getProjects(@Param("start") LocalDate start, @Param("end") LocalDate end); + + List getClearList(@Param("start") LocalDate start, @Param("end") LocalDate end); + + List getSummaryData(@Param("start") LocalDate start, @Param("end") LocalDate end); +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/IOaExpressQuestionService.java b/gear-oa/src/main/java/com/gear/oa/service/IOaExpressQuestionService.java new file mode 100644 index 0000000..45a984a --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/IOaExpressQuestionService.java @@ -0,0 +1,48 @@ +package com.gear.oa.service; + +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.oa.domain.bo.OaExpressQuestionBo; +import com.gear.oa.domain.vo.OaExpressQuestionVo; + +import java.util.Collection; +import java.util.List; + +/** + * 快递问题Service接口 + * + * @author hdka + * @date 2025-07-21 + */ +public interface IOaExpressQuestionService { + + /** + * 查询快递问题 + */ + OaExpressQuestionVo queryById(Long questionId); + + /** + * 查询快递问题列表 + */ + TableDataInfo queryPageList(OaExpressQuestionBo bo, PageQuery pageQuery); + + /** + * 查询快递问题列表 + */ + List queryList(OaExpressQuestionBo bo); + + /** + * 新增快递问题 + */ + Boolean insertByBo(OaExpressQuestionBo bo); + + /** + * 修改快递问题 + */ + Boolean updateByBo(OaExpressQuestionBo bo); + + /** + * 校验并批量删除快递问题信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/IOaExpressService.java b/gear-oa/src/main/java/com/gear/oa/service/IOaExpressService.java new file mode 100644 index 0000000..72b0c3b --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/IOaExpressService.java @@ -0,0 +1,57 @@ +package com.gear.oa.service; + +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.oa.domain.bo.OaExpressBo; +import com.gear.oa.domain.vo.OaExpressVo; + +import java.io.IOException; +import java.util.Collection; +import java.util.List; + +/** + * 物流预览Service接口 + * + * @author hdka + * @date 2025-07-20 + */ +public interface IOaExpressService { + + /** + * 查询物流预览 + */ + OaExpressVo queryById(Long expressId); + + /** + * 查询物流预览列表 + */ + TableDataInfo queryPageList(OaExpressBo bo, PageQuery pageQuery); + + /** + * 查询物流预览列表 + */ + List queryList(OaExpressBo bo); + + /** + * 新增物流预览 + */ + Boolean insertByBo(OaExpressBo bo); + + /** + * 修改物流预览 + */ + Boolean updateByBo(OaExpressBo bo); + + /** + * 校验并批量删除物流预览信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 及时更新选中的状态 + * @param list + * @return + */ + Boolean getRefreshExpress(List list) throws IOException; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/IOaFeedbackService.java b/gear-oa/src/main/java/com/gear/oa/service/IOaFeedbackService.java new file mode 100644 index 0000000..8caebf6 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/IOaFeedbackService.java @@ -0,0 +1,55 @@ +package com.gear.oa.service; + +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.oa.domain.bo.OaFeedbackBo; +import com.gear.oa.domain.vo.OaFeedbackVo; + +import java.util.Collection; +import java.util.List; + +/** + * 问题反馈Service接口 + * + * @author ruoyi + * @date 2025-03-28 + */ +public interface IOaFeedbackService { + + /** + * 查询问题反馈 + */ + OaFeedbackVo queryById(Long feedbackId); + + /** + * 查询问题反馈列表 + */ + TableDataInfo queryPageList(OaFeedbackBo bo, PageQuery pageQuery); + + /** + * 查询问题反馈列表 + */ + List queryList(OaFeedbackBo bo); + + /** + * 新增问题反馈 + */ + Boolean insertByBo(OaFeedbackBo bo); + + /** + * 修改问题反馈 + */ + Boolean updateByBo(OaFeedbackBo bo); + + /** + * 校验并批量删除问题反馈信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + Boolean updateToRead(OaFeedbackBo bo); + + int delItem(Long feedbackId); + + TableDataInfo indexQueryList(OaFeedbackBo bo, PageQuery pageQuery); + +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/IOaReportService.java b/gear-oa/src/main/java/com/gear/oa/service/IOaReportService.java new file mode 100644 index 0000000..ba148c8 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/IOaReportService.java @@ -0,0 +1,71 @@ +package com.gear.oa.service; + +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.oa.domain.bo.OaReportBo; +import com.gear.oa.domain.vo.OaReportVo; +import com.gear.oa.domain.vo.ReportCardVo; +import com.gear.oa.domain.vo.ReportPieVo; +import com.gear.oa.domain.vo.ReportTrendVo; + +import java.time.LocalDate; +import java.util.Collection; +import java.util.List; + +/** + * 项目报工Service接口 + * + * @author hdka + * @date 2025-06-16 + */ +public interface IOaReportService { + + /** + * 查询项目报工 + */ + OaReportVo queryById(Long reportId); + + /** + * 查询项目报工列表 + */ + TableDataInfo queryPageList(OaReportBo bo, PageQuery pageQuery); + + /** + * 查询项目报工列表 + */ + List queryList(OaReportBo bo); + + /** + * 新增项目报工 + */ + Boolean insertByBo(OaReportBo bo); + + /** + * 修改项目报工 + */ + Boolean updateByBo(OaReportBo bo); + + /** + * 校验并批量删除项目报工信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 报工数据看板 + * @return + */ + ReportCardVo getCardData(); + + public List getTrend(LocalDate start, LocalDate end); + + public List getDistribution(LocalDate start, LocalDate end); + + + List getRankData(LocalDate start, LocalDate end); + + List getProjects(LocalDate start, LocalDate end); + + List clearList(LocalDate start, LocalDate end); + + List getSummaryData(LocalDate start, LocalDate end); +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/impl/OaExpressQuestionServiceImpl.java b/gear-oa/src/main/java/com/gear/oa/service/impl/OaExpressQuestionServiceImpl.java new file mode 100644 index 0000000..2fb951c --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/impl/OaExpressQuestionServiceImpl.java @@ -0,0 +1,150 @@ +package com.gear.oa.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.helper.LoginHelper; +import com.gear.common.utils.StringUtils; +import com.gear.oa.domain.OaExpressQuestion; +import com.gear.oa.domain.bo.OaExpressQuestionBo; +import com.gear.oa.domain.vo.OaExpressQuestionVo; +import com.gear.oa.mapper.OaExpressQuestionMapper; +import com.gear.oa.service.IOaExpressQuestionService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 快递问题Service业务层处理 + * + * @author hdka + * @date 2025-07-21 + */ +@RequiredArgsConstructor +@Service +public class OaExpressQuestionServiceImpl implements IOaExpressQuestionService { + + private final OaExpressQuestionMapper baseMapper; + + /** + * 查询快递问题 + */ + @Override + public OaExpressQuestionVo queryById(Long questionId){ + return baseMapper.selectVoById(questionId); + } + + /** + * 查询快递问题列表 + */ + @Override + public TableDataInfo queryPageList(OaExpressQuestionBo bo, PageQuery pageQuery) { + QueryWrapper lqw = buildQueryWrapperPlus(bo); + Page result = baseMapper.selectVoPagePlus(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询快递问题列表 + */ + @Override + public List queryList(OaExpressQuestionBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + private LambdaQueryWrapper buildQueryWrapper(OaExpressQuestionBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + + if (bo.getExpressId() != null) { + lqw.eq(OaExpressQuestion::getExpressId, bo.getExpressId()); + } + if (StringUtils.isNotBlank(bo.getDescription())) { + lqw.eq(OaExpressQuestion::getDescription, bo.getDescription()); + } + if (bo.getReportTime() != null) { + lqw.eq(OaExpressQuestion::getReportTime, bo.getReportTime()); + } + if (StringUtils.isNotBlank(bo.getReportBy())) { + lqw.eq(OaExpressQuestion::getReportBy, bo.getReportBy()); + } + if (bo.getStatus() != null) { + lqw.eq(OaExpressQuestion::getStatus, bo.getStatus()); + } + return lqw; + } + + private QueryWrapper buildQueryWrapperPlus(OaExpressQuestionBo bo) { + Map params = bo.getParams(); + QueryWrapper qw = new QueryWrapper<>(); + // 设置表别名 + if (bo.getExpressId() != null) { + qw.eq("oeq.express_id", bo.getExpressId()); + } + if (StringUtils.isNotBlank(bo.getDescription())) { + qw.eq("oeq.description", bo.getDescription()); + } + if (bo.getReportTime() != null) { + qw.eq("oeq.report_time", bo.getReportTime()); + } + if (StringUtils.isNotBlank(bo.getReportBy())) { + qw.eq("oeq.report_by", bo.getReportBy()); + } + if (bo.getStatus() != null) { + qw.eq("oeq.status", bo.getStatus()); + } + // 逻辑删除 + qw.eq("oeq.del_flag", 0); + + return qw; + } + + /** + * 新增快递问题 + */ + @Override + public Boolean insertByBo(OaExpressQuestionBo bo) { + OaExpressQuestion add = BeanUtil.toBean(bo, OaExpressQuestion.class); + validEntityBeforeSave(add); + add.setReportBy(LoginHelper.getNickName()); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setQuestionId(add.getQuestionId()); + } + return flag; + } + + /** + * 修改快递问题 + */ + @Override + public Boolean updateByBo(OaExpressQuestionBo bo) { + OaExpressQuestion update = BeanUtil.toBean(bo, OaExpressQuestion.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(OaExpressQuestion entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除快递问题 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/impl/OaExpressServiceImpl.java b/gear-oa/src/main/java/com/gear/oa/service/impl/OaExpressServiceImpl.java new file mode 100644 index 0000000..9766e90 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/impl/OaExpressServiceImpl.java @@ -0,0 +1,246 @@ +package com.gear.oa.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.utils.StringUtils; +import com.gear.oa.domain.OaExpress; +import com.gear.oa.domain.bo.OaExpressBo; +import com.gear.oa.domain.vo.OaExpressVo; +import com.gear.oa.mapper.OaExpressMapper; +import com.gear.oa.service.IOaExpressService; +import com.gear.oa.utils.*; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 物流预览Service业务层处理 + * + * @author hdka + * @date 2025-07-20 + */ +@RequiredArgsConstructor +@Service +public class OaExpressServiceImpl implements IOaExpressService { + + private final OaExpressMapper baseMapper; + + /** + * 查询物流预览 + */ + @Override + public OaExpressVo queryById(Long expressId){ + return baseMapper.selectVoByIdPlus(expressId); + } + + /** + * 查询物流预览列表 + */ + @Override + public TableDataInfo queryPageList(OaExpressBo bo, PageQuery pageQuery) { + QueryWrapper lqw = buildQueryWrapperPlus(bo); + Page result = baseMapper.selectVoPagePlus(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询物流预览列表 + */ + @Override + public List queryList(OaExpressBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + private LambdaQueryWrapper buildQueryWrapper(OaExpressBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotBlank(bo.getExpressCode())) { + lqw.like(OaExpress::getExpressCode, bo.getExpressCode()); + } + if (bo.getStatus() != null) { + lqw.eq(OaExpress::getStatus, bo.getStatus()); + } + if (StringUtils.isNotBlank(bo.getSupplyName())) { + lqw.like(OaExpress::getSupplyName, bo.getSupplyName()); + } + if (StringUtils.isNotBlank(bo.getSupplyPhone())) { + lqw.eq(OaExpress::getSupplyPhone, bo.getSupplyPhone()); + } + if (bo.getOwnerId() != null) { + lqw.eq(OaExpress::getOwnerId, bo.getOwnerId()); + } + if (StringUtils.isNotBlank(bo.getOwnerPhone())) { + lqw.eq(OaExpress::getOwnerPhone, bo.getOwnerPhone()); + } + if (bo.getPlanDate() != null) { + lqw.eq(OaExpress::getPlanDate, bo.getPlanDate()); + } + if (StringUtils.isNotBlank(bo.getExpressType())) { + lqw.eq(OaExpress::getExpressType, bo.getExpressType()); + } + return lqw; + } + + private QueryWrapper buildQueryWrapperPlus(OaExpressBo bo) { + Map params = bo.getParams(); + QueryWrapper qw = new QueryWrapper<>(); + // 设置表别名 + if (StringUtils.isNotBlank(bo.getExpressCode())) { + qw.like("oe.express_code", bo.getExpressCode()); + } + if (bo.getStatus() != null) { + qw.eq("oe.status", bo.getStatus()); + } + if (StringUtils.isNotBlank(bo.getSupplyName())) { + qw.like("oe.supply_name", bo.getSupplyName()); + } + if (StringUtils.isNotBlank(bo.getSupplyPhone())) { + qw.eq("oe.supply_phone", bo.getSupplyPhone()); + } + if (bo.getOwnerId() != null) { + qw.eq("oe.owner_id", bo.getOwnerId()); + } + if (StringUtils.isNotBlank(bo.getOwnerPhone())) { + qw.eq("oe.owner_phone", bo.getOwnerPhone()); + } + if (bo.getPlanDate() != null) { + qw.eq("oe.plan_date", bo.getPlanDate()); + } + if (StringUtils.isNotBlank(bo.getExpressType())) { + qw.eq("oe.express_type", bo.getExpressType()); + } + // 添加逻辑删除条件 + qw.eq("oe.del_flag", 0); + + return qw; + } + + + /** + * 新增物流预览 + */ + @Override + public Boolean insertByBo(OaExpressBo bo) { + OaExpress add = BeanUtil.toBean(bo, OaExpress.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setExpressId(add.getExpressId()); + } + return flag; + } + + /** + * 修改物流预览 + */ + @Override + public Boolean updateByBo(OaExpressBo bo) { + OaExpress update = BeanUtil.toBean(bo, OaExpress.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(OaExpress entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除物流预览 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } + + /** + * 获取所有需要刷新的快递ID(示例:所有类型为SF且状态为1的快递单) + */ + public List getAllSfExpressIdsToRefresh() { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(OaExpress::getExpressType, "SF"); + lqw.eq(OaExpress::getStatus, 1L); + List list = baseMapper.selectList(lqw); + return list.stream().map(OaExpress::getExpressId).collect(Collectors.toList()); + } + + @Override + public Boolean getRefreshExpress(List expressIds) throws IOException { + for (Long expressId : expressIds) { + OaExpressVo oaExpressVo = baseMapper.selectVoById(expressId); + String expressType = oaExpressVo.getExpressType(); + if (expressType.equals("SF") && oaExpressVo.getStatus() ==1L) { + // 校验为顺丰则进入此位置更新状态 + String result = SfRouteQueryUtil.queryRoute(oaExpressVo.getExpressCode(), oaExpressVo.getOwnerPhone() != null ? oaExpressVo.getOwnerPhone() : oaExpressVo.getSupplyPhone()); + OaExpressVo oaExpressVo1 = SfRouteQueryUtil.parseData(result); + if (oaExpressVo1 != null) { + oaExpressVo.setLastUpdateTime(oaExpressVo1.getAcceptTime()); + oaExpressVo.setLastStatus(oaExpressVo1.getFirstStatusName()); + } + } + if (expressType.equals("ZTO") && oaExpressVo.getStatus() ==1L) { + // 校验为顺丰则进入此位置更新状态 + OaExpressVo oaExpressVo1 = ZtoTrackQueryUtil.queryTrack(oaExpressVo.getExpressCode(), oaExpressVo.getOwnerPhone() != null ? oaExpressVo.getOwnerPhone() : oaExpressVo.getSupplyPhone()); + if (oaExpressVo1 != null) { + oaExpressVo.setLastUpdateTime(oaExpressVo1.getAcceptTime()); + oaExpressVo.setLastStatus(oaExpressVo1.getFirstStatusName()); + } + } + if (expressType.equals("Best") && oaExpressVo.getStatus() ==1L) { + // 校验为顺丰则进入此位置更新状态 + OaExpressVo oaExpressVo1 = BestRouteQueryUtil.queryRoute(oaExpressVo.getExpressCode()); + + if (oaExpressVo1 != null) { + oaExpressVo.setLastUpdateTime(oaExpressVo1.getAcceptTime()); + oaExpressVo.setLastStatus(oaExpressVo1.getFirstStatusName()); + } + } + if (expressType.equals("YD") && oaExpressVo.getStatus() == 1L) { + // 韵达快递轨迹查询 + String result = com.gear.oa.utils.YdRouteQueryUtil.queryRoute(oaExpressVo.getExpressCode()); + OaExpressVo ydVo = YdRouteQueryUtil.parseData(result); + if (ydVo != null) { + oaExpressVo.setLastUpdateTime(ydVo.getLastUpdateTime()); + oaExpressVo.setLastStatus(ydVo.getLastStatus()); + } + } + if (expressType.equals("YT") && oaExpressVo.getStatus() == 1L) { + // 圆通快递轨迹查询 + String result = com.gear.oa.utils.YtRouteQueryUtil.queryRoute(oaExpressVo.getExpressCode()); + OaExpressVo ytVo = YtRouteQueryUtil.parseData(result); + if (ytVo != null) { + oaExpressVo.setLastUpdateTime(ytVo.getLastUpdateTime()); + oaExpressVo.setLastStatus(ytVo.getLastStatus()); + } + } + if (expressType.equals("STO") && oaExpressVo.getStatus() == 1L) { + // 申通快递轨迹查询 + String result = StoRouteQueryUtil.queryRoute(Collections.singletonList(oaExpressVo.getExpressCode())); + OaExpressVo stoVo = StoRouteQueryUtil.parseData(result); + if (stoVo != null) { + oaExpressVo.setLastUpdateTime(stoVo.getAcceptTime()); + oaExpressVo.setLastStatus(stoVo.getFirstStatusName()); + } + } + OaExpress add = BeanUtil.toBean(oaExpressVo, OaExpress.class); + baseMapper.updateById(add);; + } + return true; + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/impl/OaFeedbackServiceImpl.java b/gear-oa/src/main/java/com/gear/oa/service/impl/OaFeedbackServiceImpl.java new file mode 100644 index 0000000..058ef94 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/impl/OaFeedbackServiceImpl.java @@ -0,0 +1,135 @@ +package com.gear.oa.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.helper.LoginHelper; +import com.gear.oa.domain.OaFeedback; +import com.gear.oa.domain.bo.OaFeedbackBo; +import com.gear.oa.domain.vo.OaFeedbackVo; +import com.gear.oa.mapper.OaFeedbackMapper; +import com.gear.oa.service.IOaFeedbackService; +import lombok.RequiredArgsConstructor; +import lombok.val; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 问题反馈Service业务层处理 + * + * @author ruoyi + * @date 2025-03-28 + */ +@RequiredArgsConstructor +@Service +public class OaFeedbackServiceImpl implements IOaFeedbackService { + + private final OaFeedbackMapper baseMapper; + + /** + * 查询问题反馈 + */ + @Override + public OaFeedbackVo queryById(Long feedbackId){ + return baseMapper.selectVoById(feedbackId); + } + + /** + * 查询问题反馈列表 + */ + @Override + public TableDataInfo queryPageList(OaFeedbackBo bo, PageQuery pageQuery) { + QueryWrapper lqw = buildQueryWrapper(bo); + val result = baseMapper.selectVoPageAndStatus(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + + /** + * 查询问题反馈列表 + */ + @Override + public TableDataInfo indexQueryList(OaFeedbackBo bo, PageQuery pageQuery) { + QueryWrapper lqw = buildQueryWrapper(bo); + lqw.eq("ofi.status", 0L); + val result = baseMapper.selectVoPageAndStatus(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询问题反馈列表 + */ + @Override + public List queryList(OaFeedbackBo bo) { + QueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private QueryWrapper buildQueryWrapper(OaFeedbackBo bo) { + Map params = bo.getParams(); + QueryWrapper lqw = Wrappers.query(); + lqw.eq("ofi.user_id", LoginHelper.getUserId()); + return lqw; + } + + /** + * 新增问题反馈 + */ + @Override + public Boolean insertByBo(OaFeedbackBo bo) { + + OaFeedback add = BeanUtil.toBean(bo, OaFeedback.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setFeedbackId(add.getFeedbackId()); + } + baseMapper.insertItem(add.getFeedbackId()); + return flag; + } + + /** + * 修改问题反馈 + */ + @Override + public Boolean updateByBo(OaFeedbackBo bo) { + OaFeedback update = BeanUtil.toBean(bo, OaFeedback.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(OaFeedback entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除问题反馈 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } + + @Override + public Boolean updateToRead(OaFeedbackBo bo) { + + return baseMapper.updateToRead(bo.getFeedbackId(),LoginHelper.getUserId())>0; + } + + @Override + public int delItem(Long feedbackId) { + + return baseMapper.delItem(feedbackId,LoginHelper.getUserId()); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/impl/OaReportServiceImpl.java b/gear-oa/src/main/java/com/gear/oa/service/impl/OaReportServiceImpl.java new file mode 100644 index 0000000..6ab90e2 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/impl/OaReportServiceImpl.java @@ -0,0 +1,220 @@ +package com.gear.oa.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.helper.LoginHelper; +import com.gear.common.utils.StringUtils; +import com.gear.oa.domain.OaReport; +import com.gear.oa.domain.bo.OaReportBo; +import com.gear.oa.domain.vo.OaReportVo; +import com.gear.oa.domain.vo.ReportCardVo; +import com.gear.oa.domain.vo.ReportPieVo; +import com.gear.oa.domain.vo.ReportTrendVo; +import com.gear.oa.mapper.OaReportMapper; +import com.gear.oa.service.IOaReportService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * 项目报工Service业务层处理 + * + * @author hdka + * @date 2025-06-16 + */ +@RequiredArgsConstructor +@Service +public class OaReportServiceImpl implements IOaReportService { + + private final OaReportMapper baseMapper; + + /** + * 查询项目报工 + */ + @Override + public OaReportVo queryById(Long reportId){ + return baseMapper.selectVoByIdPlus(reportId); + } + + /** + * 查询项目报工列表 + */ + @Override + public TableDataInfo queryPageList(OaReportBo bo, PageQuery pageQuery) { + QueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPagePlus(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询项目报工列表 + */ + @Override + public List queryList(OaReportBo bo) { + return baseMapper.selectAll(bo); + } + + + private QueryWrapper buildQueryWrapper(OaReportBo bo) { + Map params = bo.getParams(); + QueryWrapper lqw = Wrappers.query(); + lqw.eq("opr.del_flag", 0); + lqw.eq(bo.getUserId()!=null, "opr.user_id", bo.getUserId()); + lqw.eq(bo.getWorkType()!=null, "opr.work_type", bo.getWorkType()); + lqw.like(StringUtils.isNotBlank(bo.getNickName()), "su.nick_name", bo.getNickName()); + lqw.like(StringUtils.isNotBlank(bo.getProjectNum()), "op.project_num", bo.getProjectNum()); + lqw.like(StringUtils.isNotBlank(bo.getProjectCode()), "op.project_code", bo.getProjectCode()); + lqw.eq(bo.getDeptId()!=null, "su.dept_id", bo.getDeptId()); + if (bo.getCreateTime() != null) { + LocalDateTime start = bo.getCreateTime() // LocalDateTime / Date 都行 + .toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate() // 先取日期 + .atStartOfDay(); // 00:00:00 + LocalDateTime end = start.plusDays(1); // 下一天 00:00:00 + + lqw.ge("opr.create_time", start) + .lt("opr.create_time", end); // [start, end) + } + lqw.orderByDesc("opr.create_time"); + return lqw; + } + + private QueryWrapper ClearbuildQueryWrapper(OaReportBo bo) { + Map params = bo.getParams(); + QueryWrapper lqw = Wrappers.query(); + if (bo.getCreateTime() != null) { + LocalDateTime start = bo.getCreateTime() // LocalDateTime / Date 都行 + .toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate() // 先取日期 + .atStartOfDay(); // 00:00:00 + LocalDateTime end = start.plusDays(1); // 下一天 00:00:00 + + lqw.ge("create_time", start) + .lt("create_time", end); // [start, end) + } + return lqw; + } + + /** + * 新增项目报工 + */ + @Override + public Boolean insertByBo(OaReportBo bo) { + OaReport add = BeanUtil.toBean(bo, OaReport.class); + validEntityBeforeSave(add); + add.setUserId(LoginHelper.getUserId()); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setReportId(add.getReportId()); + } + return flag; + } + + /** + * 修改项目报工 + */ + @Override + public Boolean updateByBo(OaReportBo bo) { + OaReport update = BeanUtil.toBean(bo, OaReport.class); + // 如果time字段不为空,则用time覆盖createTime + if (bo.getTime() != null) { + update.setCreateTime(bo.getTime()); + } + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(OaReport entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除项目报工 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } + + @Override + public ReportCardVo getCardData() { + ReportCardVo reportCardVo = new ReportCardVo(); + OaReportBo oaReportBo = new OaReportBo(); + oaReportBo.setCreateTime(new Date()); + QueryWrapper oaProjectReportQueryWrapper = ClearbuildQueryWrapper(oaReportBo); + // 查询今日数据 + reportCardVo.setTodayCount(baseMapper.selectCount(oaProjectReportQueryWrapper)); + oaProjectReportQueryWrapper.select("DISTINCT project_id"); + reportCardVo.setInProgressProjects(baseMapper.selectCount(oaProjectReportQueryWrapper)); + reportCardVo.setExceptions(baseMapper.countWithPending(new Date())); + reportCardVo.setCompletionRate(baseMapper.countWithCompleted(new Date())); + + // 把 new Date() 换成昨天 + Date yesterday = Date.from( + LocalDate.now() + .minusDays(1) // 昨天的日期 + .atStartOfDay(ZoneId.systemDefault()) // 当天零点 + .toInstant() + ); + oaReportBo.setCreateTime(yesterday); + // 查询昨日报工数据两 + reportCardVo.setTodayCountChange(baseMapper.selectCount(ClearbuildQueryWrapper(oaReportBo))); + + // 查询昨日涉及项目数据量 + oaProjectReportQueryWrapper.select("DISTINCT project_id"); + reportCardVo.setProjectChange(baseMapper.selectCount(oaProjectReportQueryWrapper)); + reportCardVo.setCompletionChange(baseMapper.countWithCompleted(yesterday)); + return reportCardVo; + } + + public List getTrend(LocalDate start, LocalDate end) { + return baseMapper.selectReportTrend(start, end); + } + + public List getDistribution(LocalDate start, LocalDate end) { + return baseMapper.selectProjectDistribution(start,end); + } + + @Override + public List getRankData(LocalDate start, LocalDate end) { + + return baseMapper.selectRankData(start,end); + } + + @Override + public List getProjects(LocalDate start, LocalDate end) { + return baseMapper.getProjects(start,end); + } + + @Override + public List clearList(LocalDate start, LocalDate end) { + + return baseMapper.getClearList(start,end); + } + + @Override + public List getSummaryData(LocalDate start, LocalDate end) { + + return baseMapper.getSummaryData(start,end); + + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/utils/BestRouteQueryUtil.java b/gear-oa/src/main/java/com/gear/oa/utils/BestRouteQueryUtil.java new file mode 100644 index 0000000..6a9f89d --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/utils/BestRouteQueryUtil.java @@ -0,0 +1,156 @@ +package com.gear.oa.utils; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.gear.oa.domain.vo.OaExpressVo; +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.Arrays; + +public class BestRouteQueryUtil { + // 百世开放平台 partnerID + private static final String PARTNER_ID = "7285"; + // 百世开放平台接口地址(请替换为实际地址) + private static final String API_URL = "http://openapi.800best.com/api-server/ky/api/process"; + // 百世开放平台 partnerKey + private static final String PARTNER_KEY = "NMGA0BQI"; + // 固定参数 + private static final String SERVICE_TYPE = "KY_TRACE_QUERY"; + + /** + * 查询百世快递路由 + * @param mailNo 运单号 + * @return 查询结果OaExpressVo + */ + public static OaExpressVo queryRoute(String mailNo) { + try { + // 1. 构造业务数据bizData + JSONObject bizData = new JSONObject(); + bizData.put("logisticCompanyID", "BESTQJT"); + bizData.put("codes", Arrays.asList(mailNo)); + String bizDataStr = bizData.toJSONString(); + + // 2. 生成签名(签名前不做URLEncode) + String sign = genSign(bizDataStr, PARTNER_KEY); + + // 3. 拼接表单参数(此处做URLEncode) + StringBuilder formParams = new StringBuilder(); + formParams.append("partnerID=").append(URLEncoder.encode(PARTNER_ID, "UTF-8")); + formParams.append("&serviceType=").append(URLEncoder.encode(SERVICE_TYPE, "UTF-8")); + formParams.append("&sign=").append(URLEncoder.encode(sign, "UTF-8")); + formParams.append("&bizData=").append(URLEncoder.encode(bizDataStr, "UTF-8")); + String formBody = formParams.toString(); + + // 4. 发送POST请求(表单格式,UTF-8编码) + return doPost(API_URL, formBody); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 百世签名生成方式:MD5(bizData + partnerKey),再转大写 + */ + private static String genSign(String bizData, String partnerKey) throws Exception { + String toSign = bizData + partnerKey; + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(toSign.getBytes("UTF-8")); + byte[] digest = md5.digest(); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + sb.append(String.format("%02x", b)); + } + return sb.toString(); + } + + /** + * 发送POST请求(表单格式,UTF-8编码) + */ + private static OaExpressVo doPost(String urlStr, String formBody) throws Exception { + URL url = new URL(urlStr); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); + conn.setDoOutput(true); + try (OutputStream os = conn.getOutputStream()) { + os.write(formBody.getBytes(StandardCharsets.UTF_8)); + } + int code = conn.getResponseCode(); + if (code == 200) { + try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) { + StringBuilder sb = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + sb.append(line); + } + return parseData(sb.toString()); + } + } else { + throw new RuntimeException("HTTP请求失败,状态码:" + code); + } + } + + /** + * 解析百世快递返回数据,只取第一个轨迹的acceptTime和remark + */ + public static OaExpressVo parseData(String result) { + if (StringUtils.isBlank(result)) { + System.out.println("返回结果为空"); + return null; + } + try { + JSONObject json = JSON.parseObject(result); + Boolean success = json.getBoolean("result"); + if (success == null || !success) { + System.out.println("查询失败:" + json.getString("resultInfo")); + return null; + } + JSONArray orderTraceList = json.getJSONArray("orderTraceList"); + if (orderTraceList == null || orderTraceList.isEmpty()) { + System.out.println("无轨迹信息"); + return null; + } + // 只取第一个轨迹的最后一个步骤 + JSONObject orderTrace = orderTraceList.getJSONObject(0); + JSONArray steps = orderTrace.getJSONArray("steps"); + if (steps == null || steps.isEmpty()) { + System.out.println("无轨迹步骤信息"); + return null; + } + JSONObject step = steps.getJSONObject(steps.size() - 1); + OaExpressVo vo = new OaExpressVo(); + vo.setExpressCode(orderTrace.getString("code")); + vo.setFirstStatusName(step.getString("remark")); + String acceptTimeStr = step.getString("acceptTime"); + if (acceptTimeStr != null) { + // 假设格式为 yyyy-MM-dd HH:mm:ss + try { + vo.setAcceptTime(java.sql.Timestamp.valueOf(acceptTimeStr)); + } catch (Exception e) { + vo.setAcceptTime(null); + } + } + return vo; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + // main方法测试 + public static void main(String[] args) { + String mailNo = "80004559434"; + OaExpressVo vo = queryRoute(mailNo); + System.out.println(vo); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/utils/SfRouteQueryUtil.java b/gear-oa/src/main/java/com/gear/oa/utils/SfRouteQueryUtil.java new file mode 100644 index 0000000..c7db803 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/utils/SfRouteQueryUtil.java @@ -0,0 +1,216 @@ +package com.gear.oa.utils; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.gear.common.utils.DateUtils; +import com.gear.oa.domain.vo.OaExpressVo; +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.*; + +/** + * 顺丰路由地址查询工具 + */ +public class SfRouteQueryUtil { + // 顺丰开放平台 partnerID + private static final String PARTNER_ID = "YIX65G10"; + // 顺丰开放平台接口地址 + private static final String API_URL = "https://bspgw.sf-express.com/std/service"; + + // 顺丰开放平台 checkWord + private static final String CHECK_WORD = "PkJL4cpEQIUuV1goWvhIznqthletmddX"; + + // 顺丰OAuth认证 + private static final String OAUTH_URL = "https://sfapi.sf-express.com/oauth2/accessToken"; + + private static final String GRANT_TYPE = "password"; + /** + * 查询顺丰路由 + * @param mailNo 顺丰运单号 + * @return 查询结果JSON + */ + public static String queryRoute(String mailNo,String phoneNumber) { + List mailNos = Arrays.asList(mailNo); + try { + // 1. 构造业务数据msgData + JSONObject msgData = new JSONObject(); + msgData.put("language", "zh-CN"); + msgData.put("trackingType", "1"); // 1:运单号 2:订单号 + msgData.put("methodType", "1"); // 1:标准路由 + msgData.put("trackingNumber", mailNos); + msgData.put("checkPhoneNo", StringUtils.right(phoneNumber, 4)); + String msgDataStr = msgData.toJSONString(); + System.out.println(msgDataStr); + + // 2. 公共参数 + String requestID = UUID.randomUUID().toString().replaceAll("-", ""); + String serviceCode = "EXP_RECE_SEARCH_ROUTES"; + String timestamp = String.valueOf(System.currentTimeMillis()); +// String msgDigest = genSign(msgDataStr, timestamp, CHECK_WORD); +// System.out.println(msgDigest); + String accessToken = oAuth(); + System.out.println(accessToken); + // 3. 拼接表单参数 + StringBuilder formParams = new StringBuilder(); + formParams.append("partnerID=").append(URLEncoder.encode(PARTNER_ID, "UTF-8")); + formParams.append("&requestID=").append(URLEncoder.encode(requestID, "UTF-8")); + formParams.append("&serviceCode=").append(URLEncoder.encode(serviceCode, "UTF-8")); + formParams.append("×tamp=").append(URLEncoder.encode(timestamp, "UTF-8")); + formParams.append("&accessToken=").append(URLEncoder.encode(accessToken, "UTF-8")); + formParams.append("&msgData=").append(URLEncoder.encode(msgDataStr, "UTF-8")); + String formBody = formParams.toString(); + System.out.println(formBody); + + // 4. 发送POST请求 + return doPost(API_URL, formBody); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + + + /** + * 顺丰msgDigest生成方式:Base64(MD5(URLEncode(msgData+timestamp+partnerId+checkWord))) + */ + private static String genSign(String msgData, String timestamp, String checkWord) throws Exception { + String toVerifyText = msgData + timestamp + checkWord; + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(toVerifyText.getBytes("UTF-8")); + byte[] digest = md5.digest(); + return Base64.getEncoder().encodeToString(digest); + } + + /** + * 顺丰OAUTH2 + */ + private static String oAuth() throws Exception { + StringBuilder formParams = new StringBuilder(); + formParams.append("partnerID=").append(URLEncoder.encode(PARTNER_ID, "UTF-8")); + formParams.append("&secret=").append(URLEncoder.encode(CHECK_WORD, "UTF-8")); + formParams.append("&grantType=").append(URLEncoder.encode(GRANT_TYPE, "UTF-8")); + String oauthResponse = doPost(OAUTH_URL, formParams.toString()); + JSONObject jsonObject = JSON.parseObject(oauthResponse); + return jsonObject.getString("accessToken"); + } + /** + * 发送POST请求(表单格式) + */ + private static String doPost(String urlStr, String formBody) throws Exception { + URL url = new URL(urlStr); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); + conn.setDoOutput(true); + try (OutputStream os = conn.getOutputStream()) { + os.write(formBody.getBytes(StandardCharsets.UTF_8)); + } + int code = conn.getResponseCode(); + if (code == 200) { + try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) { + StringBuilder sb = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + sb.append(line); + } + return sb.toString(); + } + } else { + throw new RuntimeException("HTTP请求失败,状态码:" + code); + } + } + + public static OaExpressVo parseData(String result) { + if (StringUtils.isBlank(result)) { + return null; + } + + try { + // 1. 解析最外层的JSON + JSONObject outerJson = JSON.parseObject(result); + if (outerJson == null) { + return null; + } + + // 2. 获取apiResultData字符串并再次解析 + String apiResultDataStr = outerJson.getString("apiResultData"); + if (StringUtils.isBlank(apiResultDataStr)) { + return null; + } + + JSONObject innerJson = JSON.parseObject(apiResultDataStr); + if (innerJson == null) { + return null; + } + + // 3. 提取所需数据 + JSONObject msgData = innerJson.getJSONObject("msgData"); + if (msgData == null) { + return null; + } + + JSONArray routeResps = msgData.getJSONArray("routeResps"); + if (routeResps == null || routeResps.isEmpty()) { + return null; + } + + JSONObject firstRouteResp = routeResps.getJSONObject(0); + if (firstRouteResp == null) { + return null; + } + + JSONArray routes = firstRouteResp.getJSONArray("routes"); + if (routes == null || routes.isEmpty()) { + return null; + } + + JSONObject lastRoute = routes.getJSONObject(routes.size() - 1); + if (lastRoute == null) { + return null; + } + + String acceptTime = lastRoute.getString("acceptTime"); + String firstStatusName = lastRoute.getString("firstStatusName"); + + OaExpressVo oaExpressVo = new OaExpressVo(); + // 转换日期并设置,如果日期格式不正确则设置为null + if (StringUtils.isNotBlank(acceptTime)) { + try { + Date date = DateUtils.parseDate(acceptTime); + oaExpressVo.setAcceptTime(date); + } catch (Exception e) { + oaExpressVo.setAcceptTime(null); + } + } + oaExpressVo.setFirstStatusName(firstStatusName); + System.out.println(acceptTime); + System.out.println(firstStatusName); + return oaExpressVo; + + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + /** + * main方法测试 + */ + public static void main(String[] args) { + + + String mailNo = "SF3191365477469"; + String result = queryRoute(mailNo,"15075462410"); + System.out.println(result); + OaExpressVo oaExpress = parseData(result); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/utils/StoRouteQueryUtil.java b/gear-oa/src/main/java/com/gear/oa/utils/StoRouteQueryUtil.java new file mode 100644 index 0000000..e487f0c --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/utils/StoRouteQueryUtil.java @@ -0,0 +1,147 @@ +package com.gear.oa.utils; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.gear.oa.domain.vo.OaExpressVo; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +public class StoRouteQueryUtil { + // 请填写你自己的key/secret + private static final String APP_KEY = "CAKDSqybdwbzlUC"; + private static final String APP_SECRET = "wGRMVXwIf8sp4m4W6tWJcOaDfY7EPblQ"; + private static final String FROM_CODE = "CAKDSqybdwbzlUC"; // 你的from_code + private static final String API_URL = "https://cloudinter-linkgateway.sto.cn/gateway/link.do"; + + // 申通签名算法 body+appSecret,MD5后Base64 + public static String sign(String body, String secret) { + String text = body + secret; + byte[] md5 = DigestUtils.md5(text); + return Base64.encodeBase64String(md5); + } + + /** + * 查询申通轨迹,支持批量单号 + * @param waybillNos 运单号集合 + * @return 查询结果JSON + */ + public static String queryRoute(List waybillNos) { + try { + // 构造content参数 + JSONObject content = new JSONObject(); + content.put("order", "asc"); + JSONArray waybillNoList = new JSONArray(); + for (String no : waybillNos) waybillNoList.add(no); + content.put("waybillNoList", waybillNoList); + String contentStr = content.toJSONString(); + + // 构造表单参数字符串 + StringBuilder form = new StringBuilder(); + form.append("api_name=STO_TRACE_QUERY_COMMON"); + form.append("&content=").append(URLEncoder.encode(contentStr, "UTF-8")); + form.append("&from_appkey=").append(APP_KEY); + form.append("&from_code=").append(APP_KEY); + form.append("&to_appkey=sto_trace_query"); + form.append("&to_code=sto_trace_query"); + form.append("&data_digest=").append(URLEncoder.encode(sign(contentStr, APP_SECRET), "UTF-8")); + + System.out.println("申通表单请求体:" + form); + + URL url = new URL(API_URL); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setUseCaches(false); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); + OutputStream out = conn.getOutputStream(); + out.write(form.toString().getBytes(StandardCharsets.UTF_8)); + out.flush(); + out.close(); + StringBuilder sbResult = new StringBuilder(); + if (200 == conn.getResponseCode()) { + BufferedReader responseReader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); + String readLine; + while ((readLine = responseReader.readLine()) != null) { + sbResult.append(readLine).append("\n"); + } + responseReader.close(); + } + return sbResult.toString(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 解析申通返回数据,转为OaExpressVo列表 + */ + public static OaExpressVo parseData(String result) { + if (result == null || result.trim().isEmpty()) { + return null; + } + // 新增:如果返回是XML,直接打印并返回null + if (result.trim().startsWith("<")) { + System.err.println("申通返回XML错误:" + result); + return null; + } + try { + JSONObject json = JSON.parseObject(result); + JSONObject data = json.getJSONObject("data"); + if (data == null) return null; + for (String waybillNo : data.keySet()) { + JSONArray arr = data.getJSONArray(waybillNo); + if (arr == null || arr.isEmpty()) continue; + JSONObject last = arr.getJSONObject(arr.size() - 1); + OaExpressVo vo = new OaExpressVo(); + vo.setExpressCode(last.getString("waybillNo")); + // 设置时间 + String opTime = last.getString("opTime"); + if (opTime != null) { + try { + // 解析时间格式 "2025-07-27 13:01:00" + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + vo.setAcceptTime(sdf.parse(opTime)); + } catch (Exception e) { + vo.setAcceptTime(null); + } + } + // 设置状态 - 使用scanType作为状态 + vo.setFirstStatusName(last.getString("memo")); + // 设置备注 - 使用memo作为备注 + vo.setRemark(last.getString("scanType")); + return vo; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + // main方法测试 + public static void main(String[] args) { + List waybillNos = new ArrayList<>(); + waybillNos.add("777326763655544"); // 测试单号 + String result = queryRoute(waybillNos); + System.out.println("申通原始返回:" + result); + OaExpressVo vo = parseData(result); + if (vo != null) { + System.out.println("解析后:" + vo); + } else { + System.out.println("未解析到数据"); + } + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/utils/YdRouteQueryUtil.java b/gear-oa/src/main/java/com/gear/oa/utils/YdRouteQueryUtil.java new file mode 100644 index 0000000..7ceec9c --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/utils/YdRouteQueryUtil.java @@ -0,0 +1,75 @@ +package com.gear.oa.utils; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.gear.oa.domain.vo.OaExpressVo; +import com.yundasys.OpenApiHttpUtils; + +import java.security.MessageDigest; + +public class YdRouteQueryUtil { + // 请根据实际环境切换key/secret + private static final String APP_KEY = "004160"; // 生产环境 + private static final String APP_SECRET = "ac9ee46d749e44b98e7a9e38f3c8f8f3"; // 生产环境 + private static final String API_URL = "https://openapi.yundaex.com/openapi/outer/logictis/query"; + + /** + * 查询韵达轨迹 + * @param mailNo 运单号 + * @return 查询结果JSON + */ + public static String queryRoute(String mailNo) { + String jsonParams = "{\"mailno\":\"" + mailNo + "\"}"; + return OpenApiHttpUtils.doPostJson(API_URL, jsonParams, APP_KEY, APP_SECRET); + } + + /** + * 解析韵达返回数据,转为OaExpressVo + */ + public static OaExpressVo parseData(String result) { + if (result == null || result.trim().isEmpty()) { + return null; + } + try { + JSONObject json = JSON.parseObject(result); + JSONObject data = json.getJSONObject("data"); + if (data == null) return null; + JSONArray steps = data.getJSONArray("steps"); + if (steps == null || steps.isEmpty()) return null; + JSONObject last = steps.getJSONObject(steps.size() - 1); + OaExpressVo vo = new OaExpressVo(); + vo.setExpressCode(data.getString("mailno")); + vo.setLastUpdateTime(last.getDate("time")); + vo.setLastStatus(last.getString("action")); + vo.setRemark(last.getString("description")); + return vo; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + // MD5签名算法(如需自定义签名,可用此方法) + public static String md5(String str, String charset) throws Exception { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(str.getBytes(charset)); + byte[] result = md.digest(); + StringBuilder sb = new StringBuilder(32); + for (byte b : result) { + int val = b & 0xff; + if (val <= 0xf) sb.append("0"); + sb.append(Integer.toHexString(val)); + } + return sb.toString().toLowerCase(); + } + + // main方法测试 + public static void main(String[] args) { + String mailNo = "464569453467736"; + String result = queryRoute(mailNo); + System.out.println("韵达原始返回:" + result); + OaExpressVo vo = parseData(result); + System.out.println("解析后:" + vo); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/utils/YtRouteQueryUtil.java b/gear-oa/src/main/java/com/gear/oa/utils/YtRouteQueryUtil.java new file mode 100644 index 0000000..8d8da3e --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/utils/YtRouteQueryUtil.java @@ -0,0 +1,118 @@ +package com.gear.oa.utils; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.gear.oa.domain.vo.OaExpressVo; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +public class YtRouteQueryUtil { + // 请填写你自己的密钥、method、v + private static final String SECRET = "TEST"; + private static final String METHOD = "123456"; // 示例 + private static final String VERSION = "v1"; // 示例 + private static final String API_URL = " https://openuat.yto56test.com:6443/open/track_query_adapter/v1/hpLkUl/TEST"; + + // 圆通签名算法 param+method+v+secret,MD5后Base64 + public static String sign(String param, String method, String v, String secret) { + String data = param + method + v; + byte[] md5 = DigestUtils.md5(data + secret); + return Base64.encodeBase64String(md5); + } + + /** + * 查询圆通轨迹 + * @param number 运单号 + * @return 查询结果JSON + */ + public static String queryRoute(String number) { + try { + String timestamp = String.valueOf(System.currentTimeMillis()); + JSONObject paramObj = new JSONObject(); + paramObj.put("NUMBER", number); + String param = paramObj.toJSONString(); + String sign = sign(param, METHOD, VERSION, SECRET); + JSONObject req = new JSONObject(); + req.put("timestamp", timestamp); + req.put("param", param); + req.put("sign", sign); + req.put("format", "JSON"); + req.put("method", METHOD); + req.put("v", VERSION); + String jsonParams = req.toJSONString(); + URL url = new URL(API_URL); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setUseCaches(false); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); + OutputStream out = conn.getOutputStream(); + out.write(jsonParams.getBytes(StandardCharsets.UTF_8)); + out.flush(); + out.close(); + StringBuilder sbResult = new StringBuilder(); + if (200 == conn.getResponseCode()) { + BufferedReader responseReader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); + String readLine; + while ((readLine = responseReader.readLine()) != null) { + sbResult.append(readLine).append("\n"); + } + responseReader.close(); + } + return sbResult.toString(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 解析圆通返回数据,转为OaExpressVo列表 + */ + public static OaExpressVo parseData(String result) { + if (result == null || result.trim().isEmpty()) { + return null; + } + try { + if (result.trim().startsWith("{")) { + JSONObject json = JSON.parseObject(result); + if (json.containsKey("map")) return null; // 查询为空 + } else if (result.trim().startsWith("[")) { + JSONArray arr = JSON.parseArray(result); + if (arr.isEmpty()) return null; + JSONObject last = arr.getJSONObject(arr.size() - 1); + OaExpressVo vo = new OaExpressVo(); + vo.setExpressCode(last.getString("waybill_No")); + vo.setLastUpdateTime(last.getDate("upload_Time")); + vo.setLastStatus(last.getString("infoContent")); + vo.setRemark(last.getString("processInfo")); + return vo; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + // main方法测试 + public static void main(String[] args) { + String number = "YT2600227881409"; // 测试单号 + String result = queryRoute(number); + System.out.println("圆通原始返回:" + result); + OaExpressVo vo = parseData(result); + if (vo != null) { + System.out.println("解析后:" + vo); + } else { + System.out.println("解析后无数据"); + } + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/utils/ZtoTrackQueryUtil.java b/gear-oa/src/main/java/com/gear/oa/utils/ZtoTrackQueryUtil.java new file mode 100644 index 0000000..5bedbbf --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/utils/ZtoTrackQueryUtil.java @@ -0,0 +1,117 @@ +package com.gear.oa.utils; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.gear.oa.domain.vo.OaExpressVo; +import com.zto.zop.ZopClient; +import com.zto.zop.ZopPublicRequest; +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; + +import static com.zto.zop.EncryptionType.MD5; + +public class ZtoTrackQueryUtil { + // 替换为你的appKey和appSecret + private static final String APP_KEY = "1ebf01ae01cc81d78ba9a"; + private static final String APP_SECRET = "4bded7f302da7f7913b01810e3421b80"; + // 测试环境 +// private static final String API_URL = "https://japi-test.zto.com/zto.merchant.waybill.track.query"; + // 正式环境 + private static final String API_URL = "https://japi.zto.com/zto.merchant.waybill.track.query"; + + /** + * 查询中通物流轨迹 + * + * @param billCode 运单号 + * @return 查询结果JSON + */ + public static OaExpressVo queryTrack(String billCode,String phoneNumber) throws IOException { + + ZopClient client = new ZopClient(APP_KEY, APP_SECRET); + ZopPublicRequest request = new ZopPublicRequest(); + request.setBody("{\"billCode\":\""+billCode+"\",\"mobilePhone\":\""+ StringUtils.right(phoneNumber, 4)+"\"}"); + request.setUrl(API_URL); + request.setBase64(true); + request.setEncryptionType(MD5); + request.setTimestamp(null); + String execute = client.execute(request); + System.out.println(execute); + return parseData(execute); + } + + /** + * 解析中通返回数据,封装为OaExpressVo + */ + public static OaExpressVo parseData(String result) { + if (StringUtils.isBlank(result)) { + return null; + } + try { + JSONObject json = JSON.parseObject(result); + if (json == null || !"true".equalsIgnoreCase(String.valueOf(json.get("status")))) { + return null; + } + // 取result数组 + if (!json.containsKey("result")) { + return null; + } + // 只取第一个轨迹(如有多条) + Object resultArr = json.get("result"); + if (!(resultArr instanceof java.util.List)) { + return null; + } + JSONArray arr = json.getJSONArray("result"); + if (arr == null || arr.isEmpty()) { + return null; + } + JSONObject first = arr.getJSONObject(arr.size() - 1); // 取最后一条为最新 + if (first == null) { + return null; + } + String scanDate = first.getString("scanDate"); + String desc = first.getString("desc"); + OaExpressVo vo = new OaExpressVo(); + // scanDate为时间戳字符串 + if (StringUtils.isNotBlank(scanDate)) { + try { + long time = Long.parseLong(scanDate); + vo.setAcceptTime(new java.util.Date(time)); + } catch (Exception e) { + vo.setAcceptTime(null); + } + } + vo.setFirstStatusName(desc); + return vo; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static String getPublicIp() { + String ip = ""; + try { + URL url = new URL("http://ifconfig.me/ip"); + BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); + ip = in.readLine(); + in.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return ip; + } + + // main方法测试 + public static void main(String[] args) throws IOException { + System.out.println("本机公网IP为: " + getPublicIp()); + String billCode = "78925013374727"; + OaExpressVo result = queryTrack(billCode,"2410"); + + System.out.println(result); + } +} diff --git a/gear-oa/src/main/resources/mapper/oa/OaExpressMapper.xml b/gear-oa/src/main/resources/mapper/oa/OaExpressMapper.xml new file mode 100644 index 0000000..275a5b0 --- /dev/null +++ b/gear-oa/src/main/resources/mapper/oa/OaExpressMapper.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gear-oa/src/main/resources/mapper/oa/OaExpressQuestionMapper.xml b/gear-oa/src/main/resources/mapper/oa/OaExpressQuestionMapper.xml new file mode 100644 index 0000000..6e2bea3 --- /dev/null +++ b/gear-oa/src/main/resources/mapper/oa/OaExpressQuestionMapper.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/gear-oa/src/main/resources/mapper/oa/OaFeedbackMapper.xml b/gear-oa/src/main/resources/mapper/oa/OaFeedbackMapper.xml new file mode 100644 index 0000000..522a976 --- /dev/null +++ b/gear-oa/src/main/resources/mapper/oa/OaFeedbackMapper.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + INSERT INTO oa_feedback_item ( + feedback_id, + user_id + ) + SELECT + #{feedbackId}, + su.user_id + FROM sys_user su + WHERE su.del_flag = 0 + + + + + update oa_feedback_item set status = 1 where feedback_id =#{feedbackId} and user_id = #{userId} + + + delete from oa_feedback_item where feedback_id =#{feedbackId} and user_id = #{userId} + + + + + + + diff --git a/gear-oa/src/main/resources/mapper/oa/OaReportMapper.xml b/gear-oa/src/main/resources/mapper/oa/OaReportMapper.xml new file mode 100644 index 0000000..ac12d81 --- /dev/null +++ b/gear-oa/src/main/resources/mapper/oa/OaReportMapper.xml @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +