gaoluyang
昨天 8c65f898ed6e5b0c7a94c792c4562f6ec831dccd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
package cn.iocoder.yudao.module.mes.controller.admin.pd.project;
 
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.mes.controller.admin.pd.project.vo.MesPdProjectPageReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pd.project.vo.MesPdProjectRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pd.project.vo.MesPdProjectSaveReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pd.project.MesPdProjectDO;
import cn.iocoder.yudao.module.mes.enums.pd.MesPdProjectStatusEnum;
import cn.iocoder.yudao.module.mes.service.wm.document.MesWmDocumentRenderer;
import cn.iocoder.yudao.module.system.service.companyconfig.SystemCompanyConfigService;
import cn.iocoder.yudao.module.mes.service.pd.project.MesPdProjectService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
 
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
 
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PD_PROJECT_NOT_EXISTS;
 
@Tag(name = "管理后台 - MES 设计项目")
@RestController
@RequestMapping("/mes/pd/project")
@Validated
public class MesPdProjectController {
 
    @Resource
    private MesPdProjectService projectService;
 
    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private SystemCompanyConfigService companyConfigService;
 
    @PostMapping("/create")
    @Operation(summary = "创建设计项目")
    @PreAuthorize("@ss.hasPermission('mes:pd-project:create')")
    public CommonResult<Long> createProject(@Valid @RequestBody MesPdProjectSaveReqVO createReqVO) {
        return success(projectService.createProject(createReqVO));
    }
 
    @PutMapping("/update")
    @Operation(summary = "更新设计项目")
    @PreAuthorize("@ss.hasPermission('mes:pd-project:update')")
    public CommonResult<Boolean> updateProject(@Valid @RequestBody MesPdProjectSaveReqVO updateReqVO) {
        projectService.updateProject(updateReqVO);
        return success(true);
    }
 
    @DeleteMapping("/delete")
    @Operation(summary = "删除设计项目")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('mes:pd-project:delete')")
    public CommonResult<Boolean> deleteProject(@RequestParam("id") Long id) {
        projectService.deleteProject(id);
        return success(true);
    }
 
    @GetMapping("/get")
    @Operation(summary = "获得设计项目")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    public CommonResult<MesPdProjectRespVO> getProject(@RequestParam("id") Long id) {
        MesPdProjectDO project = projectService.getProject(id);
        if (project == null) {
            return success(null);
        }
        return success(buildProjectRespVOList(Collections.singletonList(project)).get(0));
    }
 
    @GetMapping("/page")
    @Operation(summary = "获得设计项目分页")
    public CommonResult<PageResult<MesPdProjectRespVO>> getProjectPage(@Valid MesPdProjectPageReqVO pageReqVO) {
        PageResult<MesPdProjectDO> pageResult = projectService.getProjectPage(pageReqVO);
        return success(new PageResult<>(buildProjectRespVOList(pageResult.getList()), pageResult.getTotal()));
    }
 
    @GetMapping("/export-excel")
    @Operation(summary = "导出设计项目 Excel")
    @PreAuthorize("@ss.hasPermission('mes:pd-project:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportProjectExcel(@Valid MesPdProjectPageReqVO pageReqVO,
                                   HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<MesPdProjectDO> list = projectService.getProjectPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "设计项目.xls", "数据", MesPdProjectRespVO.class,
                buildProjectRespVOList(list));
    }
 
    @GetMapping("/export-word")
    @Operation(summary = "导出项目跟踪表 Word(表头自动填充,跟踪记录留空可手填)")
    @Parameter(name = "id", description = "设计项目编号", required = true)
    @PreAuthorize("@ss.hasPermission('mes:pd-project:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportProjectTrackingWord(@RequestParam("id") Long id,
                                          HttpServletResponse response) throws IOException {
        MesPdProjectDO project = projectService.getProject(id);
        if (project == null) {
            throw exception(PD_PROJECT_NOT_EXISTS);
        }
        Map<String, String> fields = new LinkedHashMap<>();
        fields.put("taskCode", project.getTaskCode());
        fields.put("taskName", project.getTaskName());
        fields.put("productCode", project.getProductCode());
        fields.put("productName", project.getProductName());
        fields.put("version", project.getVersion());
        fields.put("status", resolveStatusName(project.getStatus()));
        fields.put("chiefDesigner", resolveUserName(project.getChiefDesigner()));
        fields.put("reviewer", resolveUserName(project.getReviewer()));
        fields.put("planFinishTime", project.getPlanFinishTime() == null ? null
                : project.getPlanFinishTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
        fields.put("printDate", java.time.LocalDate.now().toString());
        fields.put("remark", project.getRemark());
 
        var companyConfig = companyConfigService.getCompanyConfig();
        byte[] content = MesWmDocumentRenderer.renderProjectTracking(fields,
                companyConfig != null ? companyConfig.getCompanyName() : null);
        String filename = "项目跟踪表-" + project.getTaskCode() + ".docx";
        String encoded = URLEncoder.encode(filename, StandardCharsets.UTF_8).replace("+", "%20");
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encoded);
        response.getOutputStream().write(content);
    }
 
    private String resolveStatusName(Integer status) {
        if (status == null) {
            return null;
        }
        for (MesPdProjectStatusEnum item : MesPdProjectStatusEnum.values()) {
            if (item.getStatus().equals(status)) {
                return item.getName();
            }
        }
        return "未知状态(" + status + ")";
    }
 
    private String resolveUserName(Long userId) {
        if (userId == null) {
            return null;
        }
        AdminUserRespDTO user = adminUserApi.getUser(userId);
        return user != null ? user.getNickname() : "ID=" + userId;
    }
 
    @PutMapping("/publish")
    @Operation(summary = "发布设计项目(待发布→待上传)")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('mes:pd-project:update')")
    public CommonResult<Boolean> publishProject(@RequestParam("id") Long id) {
        projectService.publishProject(id);
        return success(true);
    }
 
    @PutMapping("/upload")
    @Operation(summary = "上传资料(待上传→待审核),同时自动创建资料审核记录")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('mes:pd-project:update')")
    public CommonResult<Boolean> uploadProject(@RequestParam("id") Long id) {
        projectService.uploadProject(id, getLoginUserId());
        return success(true);
    }
 
    @PutMapping("/submit-approval")
    @Operation(summary = "提交设计项目审批(待审核→审批中)")
    @Parameter(name = "id", description = "编号", required = true)
    @Parameter(name = "processDefinitionKey", description = "流程定义 Key", required = true)
    @PreAuthorize("@ss.hasPermission('mes:pd-project:update')")
    public CommonResult<Boolean> submitProjectApproval(@RequestParam("id") Long id,
                                                       @RequestParam("processDefinitionKey") String processDefinitionKey) {
        projectService.submitProjectApproval(id, processDefinitionKey);
        return success(true);
    }
 
    @GetMapping("/approve-process-list")
    @Operation(summary = "获得设计项目审批流程列表")
    @PreAuthorize("@ss.hasPermission('mes:pd-project:update')")
    public CommonResult<List<Map<String, Object>>> getProjectApproveProcessDefinitionList() {
        return success(projectService.getProjectApproveProcessDefinitionList());
    }
 
    @PutMapping("/archive")
    @Operation(summary = "归档设计项目(待归档→已归档),同时自动创建归档台账")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('mes:pd-project:update')")
    public CommonResult<Boolean> archiveProject(@RequestParam("id") Long id) {
        projectService.archiveProject(id, getLoginUserId());
        return success(true);
    }
 
    // ==================== 拼接 VO ====================
 
    private List<MesPdProjectRespVO> buildProjectRespVOList(List<MesPdProjectDO> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        // 1.1 批量获取关联数据(主设计师 + 审核人)
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(list,
                project -> Stream.of(project.getChiefDesigner(), project.getReviewer())));
        // 1.2 批量获取各项目待审核文件数
        Map<Long, Integer> pendingAuditCountMap = projectService.getPendingAuditCountMap(
                convertSet(list, MesPdProjectDO::getId));
        // 2. 拼接 VO
        return BeanUtils.toBean(list, MesPdProjectRespVO.class, vo -> {
            MapUtils.findAndThen(userMap, vo.getChiefDesigner(),
                    user -> vo.setChiefDesignerNickname(user.getNickname()));
            MapUtils.findAndThen(userMap, vo.getReviewer(),
                    user -> vo.setReviewerNickname(user.getNickname()));
            vo.setPendingAuditCount(pendingAuditCountMap.getOrDefault(vo.getId(), 0));
        });
    }
 
}