推送项目重构代码
This commit is contained in:
@@ -24,6 +24,10 @@ import com.ruoyi.oa.domain.vo.OaProjectScheduleVo;
|
||||
import com.ruoyi.oa.domain.bo.OaProjectScheduleBo;
|
||||
import com.ruoyi.oa.service.IOaProjectScheduleService;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.helper.LoginHelper;
|
||||
import com.ruoyi.oa.im.ImSendService;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
|
||||
/**
|
||||
* 项目进度
|
||||
@@ -38,6 +42,43 @@ import com.ruoyi.common.core.page.TableDataInfo;
|
||||
public class OaProjectScheduleController extends BaseController {
|
||||
|
||||
private final IOaProjectScheduleService iOaProjectScheduleService;
|
||||
private final ImSendService imSendService;
|
||||
private final ISysUserService userService;
|
||||
|
||||
/**
|
||||
* 催促进度:给项目负责人发一条 IM 消息
|
||||
*/
|
||||
@PostMapping("/urge/{scheduleId}")
|
||||
public R<Void> urgeProgress(@PathVariable Long scheduleId) {
|
||||
OaProjectScheduleVo vo = iOaProjectScheduleService.queryById(scheduleId);
|
||||
if (vo == null) {
|
||||
return R.fail("项目进度不存在");
|
||||
}
|
||||
String header = vo.getHeader();
|
||||
if (header == null || header.isEmpty()) {
|
||||
return R.fail("该项目未设置负责人");
|
||||
}
|
||||
SysUser user = userService.selectUserByNickName(header);
|
||||
if (user == null) {
|
||||
return R.fail("找不到负责人 " + header + " 的账号");
|
||||
}
|
||||
// 防止自己催自己 → 还是发,但提示
|
||||
String me = LoginHelper.getNickName();
|
||||
String projectName = vo.getProjectName() == null ? "(未命名项目)" : vo.getProjectName();
|
||||
String currentStep = vo.getCurrentStepName() == null ? "(无)" : vo.getCurrentStepName();
|
||||
int percent = vo.getSchedulePercentage() == null ? 0 : vo.getSchedulePercentage().intValue();
|
||||
long delay = vo.getDelayCount() == null ? 0 : vo.getDelayCount();
|
||||
|
||||
String title = "进度催促";
|
||||
String desc = String.format("[%s] 催促您推进【%s】,当前 %d%%,当前步骤:%s%s",
|
||||
me == null ? "系统" : me, projectName, percent, currentStep,
|
||||
delay > 0 ? ",已有 " + delay + " 步延期" : "");
|
||||
|
||||
imSendService.sendToOaUser(user.getUserId(), title, desc,
|
||||
"schedule", scheduleId, "/projectSchedule?scheduleId=" + scheduleId);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询项目进度列表
|
||||
|
||||
@@ -57,6 +57,9 @@ public class SysOaWarehouseMaster extends BaseEntity {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/** 收货单/相关附件 OSS ID(逗号分隔) */
|
||||
private String receiptDoc;
|
||||
|
||||
private Integer isLike;
|
||||
private Long status;
|
||||
private Integer returnType;
|
||||
|
||||
@@ -61,6 +61,9 @@ public class SysOaWarehouseMasterBo extends BaseEntity {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/** 收货单/相关附件 OSS ID(逗号分隔) */
|
||||
private String receiptDoc;
|
||||
|
||||
/**
|
||||
* 涉及物料
|
||||
*/
|
||||
|
||||
@@ -97,5 +97,9 @@ public class SysOaWarehouseMasterVo {
|
||||
private Long totalQty;
|
||||
/** 物料概览(GROUP_CONCAT 名称) */
|
||||
private String itemsSummary;
|
||||
/** 收货单 OSS ID(CSV) */
|
||||
private String receiptDoc;
|
||||
/** 收货单文件信息(已联查 sys_oss,格式 ossId|name|url,, ) */
|
||||
private String receiptFiles;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.ruoyi.oa.im;
|
||||
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.helper.LoginHelper;
|
||||
import com.ruoyi.oa.im.mapper.ImBindMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 当前用户的 IM 凭据(供 Web SDK 登录)
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/system/user/im")
|
||||
public class ImCredentialsController extends BaseController {
|
||||
|
||||
private final ImBindMapper bindMapper;
|
||||
private final OpenImClient openImClient;
|
||||
private final OpenImProperties props;
|
||||
|
||||
/** 当前用户 IM 登录所需信息:imUserId + token + apiUrl + wsUrl */
|
||||
@GetMapping("/credentials")
|
||||
public R<Map<String, Object>> credentials() {
|
||||
Long userId = LoginHelper.getUserId();
|
||||
ImBind bind = bindMapper.selectById(userId);
|
||||
if (bind == null || bind.getImUserId() == null) {
|
||||
return R.fail("当前账号未绑定 IM");
|
||||
}
|
||||
// platformId=5: Web
|
||||
String token = openImClient.issueUserToken(bind.getImUserId(), 5);
|
||||
if (token == null) {
|
||||
return R.fail("获取 IM token 失败");
|
||||
}
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("imUserId", bind.getImUserId());
|
||||
data.put("imToken", token);
|
||||
data.put("apiUrl", props.getPublicApiUrl());
|
||||
data.put("wsUrl", props.getWsUrl());
|
||||
return R.ok(data);
|
||||
}
|
||||
}
|
||||
@@ -106,20 +106,21 @@ public class OpenImClient {
|
||||
offlinePush.put("iOSPushSound", "default");
|
||||
offlinePush.put("iOSBadgeCount", true);
|
||||
|
||||
Map<String, Object> sendMsg = new HashMap<>();
|
||||
sendMsg.put("sendID", props.getNotificationSender());
|
||||
sendMsg.put("recvID", recvImUserId);
|
||||
sendMsg.put("senderNickname", "系统通知");
|
||||
sendMsg.put("senderPlatformID", 1);
|
||||
sendMsg.put("content", content);
|
||||
sendMsg.put("contentType", CUSTOM_CONTENT_TYPE);
|
||||
sendMsg.put("sessionType", SESSION_SINGLE);
|
||||
sendMsg.put("isOnlineOnly", false);
|
||||
sendMsg.put("notOfflinePush", false);
|
||||
sendMsg.put("offlinePushInfo", offlinePush);
|
||||
// SendMsg 字段需要嵌套在 sendMessage 对象里(OpenIM v3.8 约定)
|
||||
Map<String, Object> sendMessage = new HashMap<>();
|
||||
sendMessage.put("sendID", props.getNotificationSender());
|
||||
sendMessage.put("recvID", recvImUserId);
|
||||
sendMessage.put("senderNickname", "系统通知");
|
||||
sendMessage.put("senderPlatformID", 1);
|
||||
sendMessage.put("content", content);
|
||||
sendMessage.put("contentType", CUSTOM_CONTENT_TYPE);
|
||||
sendMessage.put("sessionType", SESSION_SINGLE);
|
||||
sendMessage.put("isOnlineOnly", false);
|
||||
sendMessage.put("notOfflinePush", false);
|
||||
sendMessage.put("offlinePushInfo", offlinePush);
|
||||
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("sendMsg", sendMsg);
|
||||
body.put("sendMessage", sendMessage);
|
||||
|
||||
JSONObject resp = postJson(props.getApiUrl() + "/msg/send_msg", body, getAdminToken());
|
||||
Integer errCode = resp.getInteger("errCode");
|
||||
@@ -130,6 +131,26 @@ public class OpenImClient {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用 admin 身份签发 IM 用户 token(Web SDK 登录需要)。
|
||||
* @param imUserId IM userID
|
||||
* @param platformId 平台编号(5=Web)
|
||||
*/
|
||||
public String issueUserToken(String imUserId, int platformId) {
|
||||
if (!props.isEnabled()) { return null; }
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("secret", props.getSecret());
|
||||
body.put("platformID", platformId);
|
||||
body.put("userID", imUserId);
|
||||
JSONObject resp = postJson(props.getApiUrl() + "/auth/get_user_token", body, getAdminToken());
|
||||
JSONObject data = resp.getJSONObject("data");
|
||||
if (data == null) {
|
||||
log.warn("[OpenIM] issueUserToken failed: {}", resp);
|
||||
return null;
|
||||
}
|
||||
return data.getString("token");
|
||||
}
|
||||
|
||||
/** chat 后端 admin token */
|
||||
public String getChatAdminToken() {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
@@ -14,14 +14,20 @@ import org.springframework.stereotype.Component;
|
||||
@ConfigurationProperties(prefix = "openim")
|
||||
public class OpenImProperties {
|
||||
|
||||
/** OpenIM 核心 API 地址 */
|
||||
private String apiUrl = "http://49.232.154.205:10002";
|
||||
/** OpenIM 核心 API 地址(走 nginx 网关,:10002 直连端口外网未开放) */
|
||||
private String apiUrl = "http://49.232.154.205:10006/api";
|
||||
|
||||
/** OpenIM chat 业务 API 地址 */
|
||||
private String chatUrl = "http://49.232.154.205:10008";
|
||||
/** OpenIM WS 长连接地址(前端 SDK 用) */
|
||||
private String wsUrl = "ws://49.232.154.205:10006/msg_gateway";
|
||||
|
||||
/** OpenIM chat 管理 API 地址(注册新用户、admin login) */
|
||||
private String chatAdminUrl = "http://49.232.154.205:10009";
|
||||
/** 前端 SDK 可以直接访问的 API 地址(如果跟后端调用地址不同) */
|
||||
private String publicApiUrl = "http://49.232.154.205:10006/api";
|
||||
|
||||
/** OpenIM chat 业务 API 地址(走 nginx 网关) */
|
||||
private String chatUrl = "http://49.232.154.205:10006/chat";
|
||||
|
||||
/** OpenIM chat 管理 API 地址(走 nginx 网关) */
|
||||
private String chatAdminUrl = "http://49.232.154.205:10006/chat";
|
||||
|
||||
/** chat 后端 admin 账号 */
|
||||
private String chatAdminAccount = "chatAdmin";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.ruoyi.oa.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
@@ -18,5 +19,7 @@ import java.util.Map;
|
||||
*/
|
||||
public interface OaProjectScheduleMapper extends BaseMapperPlus<OaProjectScheduleMapper, OaProjectSchedule, OaProjectScheduleVo> {
|
||||
|
||||
/** dataPermission="true" 让 PlusDataPermissionInterceptor 跳过解析(SQL 太复杂 JsqlParser 不识别) */
|
||||
@InterceptorIgnore(dataPermission = "true")
|
||||
Page<OaProjectScheduleVo> selectVoPagePlus(@Param("page") Page<OaProjectScheduleVo> build,@Param(Constants.WRAPPER) QueryWrapper<OaProjectSchedule> lqw);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.ruoyi.oa.suggestion;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 用户修改意见(区别于已有的 oa_feedback 问题反馈,本表为顶栏入口提交的改进意见)
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_oa_feedback")
|
||||
public class UserSuggestion {
|
||||
|
||||
@TableId(value = "feedback_id")
|
||||
private Long feedbackId;
|
||||
|
||||
private String title;
|
||||
private String content;
|
||||
private String category;
|
||||
private Integer priority;
|
||||
private String pagePath;
|
||||
private String attachment;
|
||||
|
||||
private Long submitterId;
|
||||
private String submitterName;
|
||||
|
||||
/** 0待处理 1已受理 2已完成 3已关闭 */
|
||||
private Integer status;
|
||||
|
||||
private Long handlerId;
|
||||
private String handlerName;
|
||||
private String acceptRemark;
|
||||
private Date acceptTime;
|
||||
private Date finishTime;
|
||||
|
||||
private String createBy;
|
||||
private Date createTime;
|
||||
private String updateBy;
|
||||
private Date updateTime;
|
||||
private Integer delFlag;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package com.ruoyi.oa.suggestion;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.helper.LoginHelper;
|
||||
import com.ruoyi.oa.im.ImSendService;
|
||||
import com.ruoyi.oa.suggestion.mapper.UserSuggestionMapper;
|
||||
import com.ruoyi.system.mapper.SysUserMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户修改意见
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/oa/suggestion")
|
||||
public class UserSuggestionController extends BaseController {
|
||||
|
||||
/** 信息化部 dept_id */
|
||||
private static final Long IT_DEPT_ID = 1858416909042524161L;
|
||||
|
||||
private final UserSuggestionMapper mapper;
|
||||
private final ImSendService imSendService;
|
||||
private final SysUserMapper userMapper;
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<UserSuggestion> list(UserSuggestion query, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<UserSuggestion> qw = Wrappers.lambdaQuery();
|
||||
qw.eq(UserSuggestion::getDelFlag, 0);
|
||||
Long uid = LoginHelper.getUserId();
|
||||
if (!isItDeptMember(uid)) {
|
||||
qw.eq(UserSuggestion::getSubmitterId, uid);
|
||||
}
|
||||
if (query.getStatus() != null) qw.eq(UserSuggestion::getStatus, query.getStatus());
|
||||
if (query.getCategory() != null && !query.getCategory().isEmpty()) {
|
||||
qw.eq(UserSuggestion::getCategory, query.getCategory());
|
||||
}
|
||||
if (query.getTitle() != null && !query.getTitle().isEmpty()) {
|
||||
qw.like(UserSuggestion::getTitle, query.getTitle());
|
||||
}
|
||||
qw.orderByDesc(UserSuggestion::getCreateTime);
|
||||
Page<UserSuggestion> result = mapper.selectPage(pageQuery.build(), qw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public R<Void> submit(@RequestBody UserSuggestion body) {
|
||||
Long uid = LoginHelper.getUserId();
|
||||
String name = LoginHelper.getNickName();
|
||||
body.setFeedbackId(null);
|
||||
body.setSubmitterId(uid);
|
||||
body.setSubmitterName(name);
|
||||
body.setStatus(0);
|
||||
body.setCreateBy(name);
|
||||
body.setCreateTime(new Date());
|
||||
body.setDelFlag(0);
|
||||
mapper.insert(body);
|
||||
|
||||
List<SysUser> itUsers = userMapper.selectList(
|
||||
Wrappers.<SysUser>lambdaQuery()
|
||||
.eq(SysUser::getDeptId, IT_DEPT_ID)
|
||||
.eq(SysUser::getDelFlag, "0"));
|
||||
String title = "新的修改意见";
|
||||
String desc = String.format("[%s] %s", name == null ? "用户" : name,
|
||||
body.getTitle() == null ? "未命名" : body.getTitle());
|
||||
for (SysUser u : itUsers) {
|
||||
if (u.getUserId() == null || u.getUserId().equals(uid)) continue;
|
||||
imSendService.sendToOaUser(u.getUserId(), title, desc,
|
||||
"suggestion", body.getFeedbackId(),
|
||||
"/system/feedback?id=" + body.getFeedbackId());
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PutMapping("/{id}/accept")
|
||||
public R<Void> accept(@PathVariable Long id, @RequestParam(required = false) String remark) {
|
||||
UserSuggestion fb = mapper.selectById(id);
|
||||
if (fb == null) return R.fail("不存在");
|
||||
if (!isItDeptMember(LoginHelper.getUserId())) return R.fail("仅信息化部可操作");
|
||||
fb.setStatus(1);
|
||||
fb.setHandlerId(LoginHelper.getUserId());
|
||||
fb.setHandlerName(LoginHelper.getNickName());
|
||||
fb.setAcceptRemark(remark);
|
||||
fb.setAcceptTime(new Date());
|
||||
mapper.updateById(fb);
|
||||
if (fb.getSubmitterId() != null) {
|
||||
imSendService.sendToOaUser(fb.getSubmitterId(),
|
||||
"您的意见已受理",
|
||||
String.format("[%s] 受理了您的意见:%s%s",
|
||||
fb.getHandlerName() == null ? "信息化部" : fb.getHandlerName(),
|
||||
fb.getTitle(),
|
||||
remark == null || remark.isEmpty() ? "" : "(备注:" + remark + ")"),
|
||||
"suggestion", id, "/system/feedback?id=" + id);
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PutMapping("/{id}/finish")
|
||||
public R<Void> finish(@PathVariable Long id, @RequestParam(required = false) String remark) {
|
||||
UserSuggestion fb = mapper.selectById(id);
|
||||
if (fb == null) return R.fail("不存在");
|
||||
if (!isItDeptMember(LoginHelper.getUserId())) return R.fail("仅信息化部可操作");
|
||||
fb.setStatus(2);
|
||||
fb.setFinishTime(new Date());
|
||||
if (remark != null) fb.setAcceptRemark(remark);
|
||||
mapper.updateById(fb);
|
||||
if (fb.getSubmitterId() != null) {
|
||||
imSendService.sendToOaUser(fb.getSubmitterId(),
|
||||
"您的意见已完成",
|
||||
String.format("[%s] 已处理完毕:%s", fb.getHandlerName(), fb.getTitle()),
|
||||
"suggestion", id, "/system/feedback?id=" + id);
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PutMapping("/{id}/close")
|
||||
public R<Void> close(@PathVariable Long id, @RequestParam(required = false) String remark) {
|
||||
UserSuggestion fb = mapper.selectById(id);
|
||||
if (fb == null) return R.fail("不存在");
|
||||
Long uid = LoginHelper.getUserId();
|
||||
if (!isItDeptMember(uid) && !uid.equals(fb.getSubmitterId())) return R.fail("无权关闭");
|
||||
fb.setStatus(3);
|
||||
if (remark != null) fb.setAcceptRemark(remark);
|
||||
mapper.updateById(fb);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/isItMember")
|
||||
public R<Boolean> isItMember() {
|
||||
return R.ok(isItDeptMember(LoginHelper.getUserId()));
|
||||
}
|
||||
|
||||
private boolean isItDeptMember(Long userId) {
|
||||
if (userId == null) return false;
|
||||
SysUser u = userMapper.selectById(userId);
|
||||
return u != null && IT_DEPT_ID.equals(u.getDeptId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ruoyi.oa.suggestion.mapper;
|
||||
|
||||
import com.ruoyi.common.core.mapper.BaseMapperPlus;
|
||||
import com.ruoyi.oa.suggestion.UserSuggestion;
|
||||
|
||||
public interface UserSuggestionMapper extends BaseMapperPlus<UserSuggestionMapper, UserSuggestion, UserSuggestion> {
|
||||
}
|
||||
@@ -22,6 +22,13 @@
|
||||
</resultMap>
|
||||
|
||||
|
||||
<select id="selectVoPagePlus_COUNT" resultType="java.lang.Long">
|
||||
SELECT COUNT(*)
|
||||
FROM oa_project_schedule AS ops
|
||||
LEFT JOIN sys_oa_project AS op ON ops.project_id = op.project_id
|
||||
${ew.getCustomSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="selectVoPagePlus" resultType="com.ruoyi.oa.domain.vo.OaProjectScheduleVo">
|
||||
SELECT ops.schedule_id,
|
||||
ops.project_id,
|
||||
@@ -32,7 +39,6 @@
|
||||
ops.status,
|
||||
ops.steward,
|
||||
ops.remark,
|
||||
/* ======================== 项目信息 ==================== */
|
||||
op.project_id AS opProjectId,
|
||||
op.project_name,
|
||||
op.project_num,
|
||||
@@ -48,22 +54,33 @@
|
||||
op.trade_type,
|
||||
op.project_code,
|
||||
op.pre_pay,
|
||||
op.is_top AS isTop,
|
||||
(SELECT COUNT(*) FROM oa_project_schedule_step opss
|
||||
WHERE opss.schedule_id = ops.schedule_id AND opss.del_flag = '0') AS totalCount,
|
||||
(SELECT COUNT(*) FROM oa_project_schedule_step opss
|
||||
WHERE opss.schedule_id = ops.schedule_id AND opss.del_flag = '0' AND opss.status IN (0,1)) AS unFinishCount,
|
||||
(SELECT COUNT(*) FROM oa_project_schedule_step opss
|
||||
WHERE opss.schedule_id = ops.schedule_id AND opss.del_flag = '0'
|
||||
AND (
|
||||
opss.use_flag = 0
|
||||
OR (opss.original_end_time IS NOT NULL AND opss.plan_end IS NOT NULL AND opss.plan_end > opss.original_end_time)
|
||||
OR (opss.status = 0 AND opss.original_end_time IS NOT NULL AND CURDATE() > DATE(opss.original_end_time))
|
||||
)
|
||||
) AS delayCount
|
||||
op.is_top AS isTop,
|
||||
op.functionary AS header,
|
||||
cs.step_name AS currentStepName,
|
||||
IFNULL(agg.total_count, 0) AS totalCount,
|
||||
IFNULL(agg.unfinish_count, 0) AS unFinishCount,
|
||||
IFNULL(agg.delay_count, 0) AS delayCount,
|
||||
IFNULL(agg.percent, 0) AS schedulePercentage
|
||||
FROM oa_project_schedule AS ops
|
||||
LEFT JOIN sys_oa_project AS op
|
||||
ON ops.project_id = op.project_id
|
||||
LEFT JOIN oa_project_schedule_step cs
|
||||
ON cs.track_id = ops.current_step
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
opss.schedule_id,
|
||||
COUNT(*) AS total_count,
|
||||
SUM(CASE WHEN opss.status IN (0,1) THEN 1 ELSE 0 END) AS unfinish_count,
|
||||
SUM(CASE
|
||||
WHEN opss.use_flag = 0
|
||||
OR (opss.original_end_time IS NOT NULL AND opss.plan_end IS NOT NULL AND opss.plan_end > opss.original_end_time)
|
||||
OR (opss.status = 0 AND opss.original_end_time IS NOT NULL AND CURDATE() > DATE(opss.original_end_time))
|
||||
THEN 1 ELSE 0 END) AS delay_count,
|
||||
ROUND(SUM(CASE WHEN opss.status = 2 THEN 1 ELSE 0 END) / COUNT(*) * 100, 1) AS percent
|
||||
FROM oa_project_schedule_step opss
|
||||
WHERE opss.del_flag = '0'
|
||||
GROUP BY opss.schedule_id
|
||||
) AS agg ON agg.schedule_id = ops.schedule_id
|
||||
${ew.getCustomSqlSegment}
|
||||
</select>
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
SELECT GROUP_CONCAT(CONCAT_WS('|', o.oss_id, COALESCE(o.original_name, o.file_name), o.url)
|
||||
ORDER BY FIND_IN_SET(o.oss_id, r.accessory) SEPARATOR ',,')
|
||||
FROM sys_oss o
|
||||
WHERE r.accessory IS NOT NULL AND r.accessory <> ''
|
||||
WHERE r.accessory IS NOT NULL AND r.accessory != ''
|
||||
AND FIND_IN_SET(o.oss_id, r.accessory)
|
||||
) AS accessory_files
|
||||
FROM oa_requirements r
|
||||
@@ -52,7 +52,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
SELECT GROUP_CONCAT(CONCAT_WS('|', o.oss_id, COALESCE(o.original_name, o.file_name), o.url)
|
||||
ORDER BY FIND_IN_SET(o.oss_id, r.accessory) SEPARATOR ',,')
|
||||
FROM sys_oss o
|
||||
WHERE r.accessory IS NOT NULL AND r.accessory <> ''
|
||||
WHERE r.accessory IS NOT NULL AND r.accessory != ''
|
||||
AND FIND_IN_SET(o.oss_id, r.accessory)
|
||||
) AS accessory_files
|
||||
FROM oa_requirements r
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
<result property="itemCount" column="item_count"/>
|
||||
<result property="totalQty" column="total_qty"/>
|
||||
<result property="itemsSummary" column="items_summary"/>
|
||||
<result property="receiptDoc" column="receipt_doc"/>
|
||||
<result property="receiptFiles" column="receipt_files"/>
|
||||
|
||||
<collection property="warehouseList"
|
||||
column="master_id"
|
||||
@@ -56,6 +58,7 @@
|
||||
sowm.sign_time,
|
||||
sowm.sign_user,
|
||||
sowm.remark,
|
||||
sowm.receipt_doc,
|
||||
sowm.status,
|
||||
sowm.is_like,
|
||||
sowm.requirement_id,
|
||||
@@ -64,7 +67,14 @@
|
||||
req.title AS requirementName,
|
||||
agg.item_count,
|
||||
agg.total_qty,
|
||||
agg.items_summary
|
||||
agg.items_summary,
|
||||
(
|
||||
SELECT GROUP_CONCAT(CONCAT_WS('|', o.oss_id, COALESCE(o.original_name, o.file_name), o.url)
|
||||
ORDER BY FIND_IN_SET(o.oss_id, sowm.receipt_doc) SEPARATOR ',,')
|
||||
FROM sys_oss o
|
||||
WHERE sowm.receipt_doc IS NOT NULL AND sowm.receipt_doc != ''
|
||||
AND FIND_IN_SET(o.oss_id, sowm.receipt_doc)
|
||||
) AS receipt_files
|
||||
FROM sys_oa_warehouse_master sowm
|
||||
LEFT JOIN sys_oa_project sop ON sop.project_id = sowm.project_id
|
||||
LEFT JOIN oa_requirements req ON req.requirement_id = sowm.requirement_id
|
||||
|
||||
Reference in New Issue
Block a user