yxh
昨天 8c215c8be0f5076e8c95daf1b2203440ca7dfcad
ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceReimbursementdetailController.java
@@ -52,7 +52,7 @@
     * 查询报销申请明细列表
     */
    @ApiOperation("查询报销申请明细列表")
    //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:list')")
    //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:list')")
    @GetMapping("/list")
    public TableDataInfo list(ServiceReimbursementdetail serviceReimbursementdetail) {
        startPage();
@@ -65,7 +65,7 @@
     * 导出报销申请明细列表
     */
    @ApiOperation("导出报销申请明细列表")
    //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:export')")
    //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:export')")
    @Log(title = "报销申请明细", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    public AjaxResult export(ServiceReimbursementdetail serviceReimbursementdetail) {
@@ -87,7 +87,7 @@
     * 获取报销申请明细详细信息
     */
    @ApiOperation("获取报销申请明细详细信息")
    //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:query')")
    //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return AjaxResult.success(serviceReimbursementdetailService.getById(id));
@@ -97,11 +97,26 @@
     * 新增报销申请明细
     */
    @ApiOperation("新增报销申请明细")
    //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:add')")
    //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:add')")
    @Log(title = "报销申请明细", businessType = BusinessType.INSERT)
    @PostMapping
    @PostMapping("/add")
    @RepeatSubmit
    public AjaxResult add(@RequestBody ServiceReimbursementdetailVO serviceReimbursementdetailVO) {
        // 2026-10-15:附件文件名规范二次校验(与前端 opo-web/src/utils/fileNameCheck.js 同口径,
        // 目的是防止绕过前端直接调接口保存不合规附件名)。新增场景没有历史附件,用严格模式。
        // 注意:List 为空时必须回退校验字符串字段(annexfiles / invoicefiles),
        // 否则只传字符串字段就能绕过校验(接口层面的绕过口)。
        String invoiceJson = CollectionUtils.isEmpty(serviceReimbursementdetailVO.getInvoicefilesList())
                ? serviceReimbursementdetailVO.getInvoicefiles()
                : JSON.toJSONString(serviceReimbursementdetailVO.getInvoicefilesList());
        String annexJson = CollectionUtils.isEmpty(serviceReimbursementdetailVO.getAnnexfilesList())
                ? serviceReimbursementdetailVO.getAnnexfiles()
                : JSON.toJSONString(serviceReimbursementdetailVO.getAnnexfilesList());
        String nameError = com.ruoyi.project.common.AttachmentNameValidator
                .checkJsonList(invoiceJson, annexJson);
        if (nameError != null) {
            return AjaxResult.error("附件文件名不符合要求,无法保存:" + nameError);
        }
        ServiceReimbursementdetail serviceReimbursementdetail = DtoConversionUtils.sourceToTarget(serviceReimbursementdetailVO, ServiceReimbursementdetail.class);
        //将前端传来的附件集合转成字符串
        if (!CollectionUtils.isEmpty(serviceReimbursementdetailVO.getAnnexfilesList())) {
@@ -110,18 +125,37 @@
        if (!CollectionUtils.isEmpty(serviceReimbursementdetailVO.getInvoicefilesList())) {
            serviceReimbursementdetail.setInvoicefiles(JSON.toJSONString(serviceReimbursementdetailVO.getInvoicefilesList()));
        }
        return toAjax(serviceReimbursementdetailService.save(serviceReimbursementdetail));
        boolean save = serviceReimbursementdetailService.save(serviceReimbursementdetail);
        return AjaxResult.success(serviceReimbursementdetail);
    }
    /**
     * 修改报销申请明细
     */
    @ApiOperation("修改报销申请明细")
    //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:edit')")
    //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:edit')")
    @Log(title = "修改申请明细", businessType = BusinessType.UPDATE)
    @PostMapping("/updateRDlList")
    public AjaxResult updateRDlList(@RequestBody List<ServiceReimbursementdetail> serviceReimbursementdetails) {
        for (ServiceReimbursementdetail serviceReimbursementdetail : serviceReimbursementdetails) {
            // 2026-10-15:附件文件名规范二次校验(只校验本次变更的附件,历史附件放行)
            java.util.Set<String> existingNames = new java.util.HashSet<>();
            if (serviceReimbursementdetail.getId() != null) {
                ServiceReimbursementdetail oldDetail = serviceReimbursementdetailService
                        .getById(serviceReimbursementdetail.getId());
                if (oldDetail != null) {
                    existingNames.addAll(com.ruoyi.project.common.AttachmentNameValidator
                            .collectNames(oldDetail.getInvoicefiles()));
                    existingNames.addAll(com.ruoyi.project.common.AttachmentNameValidator
                            .collectNames(oldDetail.getAnnexfiles()));
                }
            }
            String nameError = com.ruoyi.project.common.AttachmentNameValidator.checkJsonListForUpdate(
                    existingNames, serviceReimbursementdetail.getInvoicefiles(),
                    serviceReimbursementdetail.getAnnexfiles());
            if (nameError != null) {
                return AjaxResult.error("附件文件名不符合要求,无法保存:" + nameError);
            }
            serviceReimbursementdetailService.saveOrUpdate(serviceReimbursementdetail);
        }
@@ -132,11 +166,36 @@
     * 修改报销申请明细
     */
    @ApiOperation("修改报销申请明细")
    //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:edit')")
    //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:edit')")
    @Log(title = "报销申请明细", businessType = BusinessType.UPDATE)
    @PostMapping("/reimbursementdetailEdit")
    //@RepeatSubmit
    public AjaxResult edit(@RequestBody ServiceReimbursementdetailVO serviceReimbursementdetailVO) {
        // 2026-10-15:附件文件名规范二次校验(与前端 fileNameCheck 同口径,防止绕过前端)。
        // 修改场景按业务口径"只校验本次变更的附件":保存前已存在的历史附件名不参与校验,避免卡住老单据。
        java.util.Set<String> existingNames = new java.util.HashSet<>();
        if (serviceReimbursementdetailVO.getId() != null) {
            ServiceReimbursementdetail oldDetail = serviceReimbursementdetailService
                    .getById(serviceReimbursementdetailVO.getId());
            if (oldDetail != null) {
                existingNames.addAll(com.ruoyi.project.common.AttachmentNameValidator
                        .collectNames(oldDetail.getInvoicefiles()));
                existingNames.addAll(com.ruoyi.project.common.AttachmentNameValidator
                        .collectNames(oldDetail.getAnnexfiles()));
            }
        }
        // List 为空时回退校验字符串字段(annexfiles / invoicefiles),堵住"只传字符串字段"的绕过口
        String invoiceJson = CollectionUtils.isEmpty(serviceReimbursementdetailVO.getInvoicefilesList())
                ? serviceReimbursementdetailVO.getInvoicefiles()
                : JSON.toJSONString(serviceReimbursementdetailVO.getInvoicefilesList());
        String annexJson = CollectionUtils.isEmpty(serviceReimbursementdetailVO.getAnnexfilesList())
                ? serviceReimbursementdetailVO.getAnnexfiles()
                : JSON.toJSONString(serviceReimbursementdetailVO.getAnnexfilesList());
        String nameError = com.ruoyi.project.common.AttachmentNameValidator
                .checkJsonListForUpdate(existingNames, invoiceJson, annexJson);
        if (nameError != null) {
            return AjaxResult.error("附件文件名不符合要求,无法保存:" + nameError);
        }
        if (serviceReimbursementdetailVO.getTrafficexpense() == null) {
            serviceReimbursementdetailVO.setTrafficexpense(new BigDecimal(0));
        }
@@ -162,6 +221,14 @@
        if (!CollectionUtils.isEmpty(serviceReimbursementdetailVO.getAnnexfilesList())) {
            //对前端传过来的数组,进行JSON序列化,并赋值给Annexfiles
            serviceReimbursementdetail.setAnnexfiles(JSON.toJSONString(serviceReimbursementdetailVO.getAnnexfilesList()));
        } else {
            serviceReimbursementdetail.setAnnexfiles(null);
        }
        if (!CollectionUtils.isEmpty(serviceReimbursementdetailVO.getInvoicefilesList())) {
            //对前端传过来的数组,进行JSON序列化,并赋值给Invoicefiles
            serviceReimbursementdetail.setInvoicefiles(JSON.toJSONString(serviceReimbursementdetailVO.getInvoicefilesList()));
        } else {
            serviceReimbursementdetail.setInvoicefiles(null);
        }
        return toAjax(serviceReimbursementdetailService.updateById(serviceReimbursementdetail));
    }
@@ -170,7 +237,7 @@
     * 删除报销申请明细
     */
    @ApiOperation("删除报销申请明细")
    //@PreAuthorize("@ss.hasPermi('project:reimbursementdetail:remove')")
    //// @PreAuthorize("@ss.hasPermi('project:reimbursementdetail:remove')")
    @Log(title = "报销申请明细", businessType = BusinessType.DELETE)
    @GetMapping("/remove/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {